A light weight Python library for the Spotify Web API
Access podcast shows, episodes, and audiobook content with comprehensive metadata and user library integration. Spotify provides extensive podcast catalog with detailed episode information and user management features.
Access podcast show details and metadata.
def show(self, show_id, market=None):
"""
Get show information.
Args:
show_id (str): Spotify show ID or URI
market (str, optional): ISO 3166-1 alpha-2 country code
Returns:
dict: Show object with metadata, episodes, and publisher info
"""
def shows(self, shows, market=None):
"""
Get multiple shows.
Args:
shows (list): List of show IDs or URIs (max 50)
market (str, optional): ISO 3166-1 alpha-2 country code
Returns:
dict: Shows object containing list of show objects
"""Access episodes within podcast shows.
def show_episodes(self, show_id, limit=50, offset=0, market=None):
"""
Get episodes from a show.
Args:
show_id (str): Spotify show ID or URI
limit (int): Number of episodes to return (1-50, default: 50)
offset (int): Index of first episode (default: 0)
market (str, optional): ISO 3166-1 alpha-2 country code
Returns:
dict: Paging object of simplified episode objects
"""Access individual episode details and metadata.
def episode(self, episode_id, market=None):
"""
Get episode information.
Args:
episode_id (str): Spotify episode ID or URI
market (str, optional): ISO 3166-1 alpha-2 country code
Returns:
dict: Episode object with metadata, show info, and playback details
"""
def episodes(self, episodes, market=None):
"""
Get multiple episodes.
Args:
episodes (list): List of episode IDs or URIs (max 50)
market (str, optional): ISO 3166-1 alpha-2 country code
Returns:
dict: Episodes object containing list of episode objects
"""Access audiobook information and chapters.
def get_audiobook(self, id, market=None):
"""
Get audiobook information.
Args:
id (str): Spotify audiobook ID or URI
market (str, optional): ISO 3166-1 alpha-2 country code
Returns:
dict: Audiobook object with metadata, authors, and narrator info
"""
def get_audiobooks(self, ids, market=None):
"""
Get multiple audiobooks.
Args:
ids (list): List of audiobook IDs or URIs (max 50)
market (str, optional): ISO 3166-1 alpha-2 country code
Returns:
dict: Audiobooks object containing list of audiobook objects
"""
def get_audiobook_chapters(self, id, market=None, limit=20, offset=0):
"""
Get chapters from an audiobook.
Args:
id (str): Spotify audiobook ID or URI
market (str, optional): ISO 3166-1 alpha-2 country code
limit (int): Number of chapters to return (1-50, default: 20)
offset (int): Index of first chapter (default: 0)
Returns:
dict: Paging object of simplified chapter objects
"""import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
sp = spotipy.Spotify(client_credentials_manager=SpotifyClientCredentials())
# Search for popular podcast shows
results = sp.search(q='true crime', type='show', limit=10)
shows = results['shows']['items']
print("🎙️ True Crime Podcast Shows:")
for show in shows:
print(f"\\n📻 {show['name']}")
print(f" Publisher: {show['publisher']}")
print(f" Description: {show['description'][:100]}...")
print(f" Total Episodes: {show['total_episodes']}")
print(f" Languages: {', '.join(show['languages'])}")
print(f" Explicit: {'Yes' if show['explicit'] else 'No'}")
if show['images']:
print(f" Cover: {show['images'][0]['url']}")
# Get detailed information for a specific show
if shows:
show_id = shows[0]['id']
detailed_show = sp.show(show_id)
print(f"\\n🔍 Detailed info for '{detailed_show['name']}':")
print(f" Media Type: {detailed_show['media_type']}")
print(f" Available Markets: {len(detailed_show['available_markets'])} markets")
print(f" Copyright: {detailed_show['copyrights'][0]['text'] if detailed_show['copyrights'] else 'N/A'}")# Get episodes from a show
show_id = "4rOoJ6Egrf8K2IrywzwOMk" # Example show ID
# Get recent episodes
episodes = sp.show_episodes(show_id, limit=20)
print(f"📺 Recent episodes ({episodes['total']} total):")
for episode in episodes['items']:
print(f"\\n🎧 {episode['name']}")
print(f" Description: {episode['description'][:150]}...")
print(f" Duration: {episode['duration_ms'] // 60000} minutes")
print(f" Release Date: {episode['release_date']}")
print(f" Language: {', '.join(episode['languages'])}")
print(f" Explicit: {'Yes' if episode['explicit'] else 'No'}")
# Check if episode has external URLs
if episode['external_urls']:
print(f" Spotify URL: {episode['external_urls']['spotify']}")
# Get detailed episode information
if episodes['items']:
episode_id = episodes['items'][0]['id']
detailed_episode = sp.episode(episode_id)
print(f"\\n🔍 Detailed episode info:")
print(f" Show: {detailed_episode['show']['name']}")
print(f" Episode Type: {detailed_episode.get('type', 'episode')}")
print(f" Resume Point: {detailed_episode.get('resume_point', {}).get('resume_position_ms', 0) // 1000}s")
print(f" Fully Played: {detailed_episode.get('resume_point', {}).get('fully_played', False)}")# Search for audiobooks
audiobook_results = sp.search(q='mystery', type='audiobook', limit=5)
audiobooks = audiobook_results['audiobooks']['items']
print("📚 Mystery Audiobooks:")
for audiobook in audiobooks:
print(f"\\n📖 {audiobook['name']}")
print(f" Authors: {', '.join([author['name'] for author in audiobook['authors']])}")
print(f" Narrators: {', '.join([narrator['name'] for narrator in audiobook['narrators']])}")
print(f" Publisher: {audiobook['publisher']}")
print(f" Description: {audiobook['description'][:100]}...")
print(f" Total Chapters: {audiobook['total_chapters']}")
print(f" Languages: {', '.join(audiobook['languages'])}")
print(f" Explicit: {'Yes' if audiobook['explicit'] else 'No'}")
# Get chapters from an audiobook
if audiobooks:
audiobook_id = audiobooks[0]['id']
chapters = sp.get_audiobook_chapters(audiobook_id, limit=10)
print(f"\\n📑 Chapters from '{audiobooks[0]['name']}':")
for i, chapter in enumerate(chapters['items'], 1):
duration_min = chapter['duration_ms'] // 60000
print(f" Chapter {i}: {chapter['name']} ({duration_min} min)")
print(f" Description: {chapter['description'][:80]}...")
print(f" Chapter Number: {chapter.get('chapter_number', 'N/A')}")def analyze_podcast_show(show_id):
"""Analyze a podcast show's episodes and patterns."""
show = sp.show(show_id)
print(f"📊 Analysis for '{show['name']}':")
print(f"Publisher: {show['publisher']}")
print(f"Total Episodes: {show['total_episodes']}")
# Get all episodes
all_episodes = []
episodes = sp.show_episodes(show_id, limit=50)
all_episodes.extend(episodes['items'])
while episodes['next']:
episodes = sp.next(episodes)
all_episodes.extend(episodes['items'])
if all_episodes:
# Calculate statistics
durations = [ep['duration_ms'] for ep in all_episodes]
avg_duration = sum(durations) / len(durations)
# Count explicit episodes
explicit_count = sum(1 for ep in all_episodes if ep.get('explicit', False))
# Get release pattern (episodes per month)
from collections import defaultdict
import datetime
release_months = defaultdict(int)
for episode in all_episodes:
if episode['release_date']:
try:
date = datetime.datetime.strptime(episode['release_date'], '%Y-%m-%d')
month_key = f"{date.year}-{date.month:02d}"
release_months[month_key] += 1
except:
pass
print(f"\\n📈 Episode Statistics:")
print(f" Average Duration: {avg_duration / 60000:.1f} minutes")
print(f" Longest Episode: {max(durations) / 60000:.1f} minutes")
print(f" Shortest Episode: {min(durations) / 60000:.1f} minutes")
print(f" Explicit Episodes: {explicit_count}/{len(all_episodes)} ({explicit_count/len(all_episodes)*100:.1f}%)")
print(f"\\n📅 Recent Release Pattern:")
recent_months = sorted(release_months.keys())[-6:] # Last 6 months
for month in recent_months:
print(f" {month}: {release_months[month]} episodes")
# Show recent episodes
print(f"\\n🆕 Most Recent Episodes:")
for episode in all_episodes[:5]:
print(f" • {episode['name']} ({episode['release_date']})")
print(f" {episode['duration_ms'] // 60000} min - {episode['description'][:60]}...")
# Analyze a popular podcast
# Example: The Joe Rogan Experience (if available in your market)
try:
# You would need to find the actual show ID
# analyze_podcast_show("4rOoJ6Egrf8K2IrywzwOMk")
pass
except Exception as e:
print(f"Could not analyze show: {e}")def discover_podcasts_by_genre(genre_query, limit=10):
"""Discover podcasts by genre or topic."""
# Search for shows
results = sp.search(q=genre_query, type='show', limit=limit)
shows = results['shows']['items']
print(f"🎭 '{genre_query.title()}' Podcasts:")
show_stats = []
for show in shows:
print(f"\\n📻 {show['name']}")
print(f" Publisher: {show['publisher']}")
print(f" Episodes: {show['total_episodes']}")
print(f" Languages: {', '.join(show['languages'])}")
# Get a few recent episodes to analyze
try:
recent_episodes = sp.show_episodes(show['id'], limit=5)
if recent_episodes['items']:
avg_duration = sum(ep['duration_ms'] for ep in recent_episodes['items']) / len(recent_episodes['items'])
print(f" Avg Episode Length: {avg_duration / 60000:.1f} minutes")
# Check update frequency
episodes = recent_episodes['items']
if len(episodes) >= 2:
try:
from datetime import datetime
date1 = datetime.strptime(episodes[0]['release_date'], '%Y-%m-%d')
date2 = datetime.strptime(episodes[1]['release_date'], '%Y-%m-%d')
days_between = abs((date1 - date2).days)
print(f" Update Frequency: ~{days_between} days between episodes")
except:
pass
except:
pass
show_stats.append({
'name': show['name'],
'episodes': show['total_episodes'],
'publisher': show['publisher']
})
# Summary statistics
if show_stats:
total_episodes = sum(s['episodes'] for s in show_stats)
avg_episodes = total_episodes / len(show_stats)
print(f"\\n📊 Genre Summary:")
print(f" Total Shows Found: {len(show_stats)}")
print(f" Total Episodes: {total_episodes}")
print(f" Average Episodes per Show: {avg_episodes:.1f}")
# Top publishers
publishers = {}
for show in show_stats:
pub = show['publisher']
publishers[pub] = publishers.get(pub, 0) + 1
print(f" Top Publishers:")
for pub, count in sorted(publishers.items(), key=lambda x: x[1], reverse=True)[:3]:
print(f" {pub}: {count} shows")
# Discover different podcast genres
genres = ['technology', 'comedy', 'news', 'business', 'health']
for genre in genres:
discover_podcasts_by_genre(genre, 5)
print("-" * 60)def create_podcast_queue(show_ids, episodes_per_show=3):
"""Create a listening queue from multiple podcast shows."""
queue = []
for show_id in show_ids:
try:
show = sp.show(show_id)
episodes = sp.show_episodes(show_id, limit=episodes_per_show)
for episode in episodes['items']:
queue.append({
'show_name': show['name'],
'episode_name': episode['name'],
'duration_minutes': episode['duration_ms'] // 60000,
'release_date': episode['release_date'],
'description': episode['description'][:100] + '...',
'uri': episode['uri']
})
except Exception as e:
print(f"Error processing show {show_id}: {e}")
# Sort by release date (newest first)
queue.sort(key=lambda x: x['release_date'], reverse=True)
print(f"🎧 Podcast Listening Queue ({len(queue)} episodes):")
total_duration = sum(ep['duration_minutes'] for ep in queue)
print(f"Total Duration: {total_duration // 60}h {total_duration % 60}m\\n")
for i, episode in enumerate(queue, 1):
print(f"{i:2d}. [{episode['show_name']}] {episode['episode_name']}")
print(f" {episode['duration_minutes']} min | {episode['release_date']} | {episode['description']}")
print(f" URI: {episode['uri']}")
print()
return queue
# Example usage (you would need actual show IDs)
# show_ids = ["show_id_1", "show_id_2", "show_id_3"]
# podcast_queue = create_podcast_queue(show_ids, 2)def analyze_content_by_market(content_type='show', query='news', markets=['US', 'GB', 'DE', 'ES']):
"""Analyze how content varies across different markets."""
print(f"🌍 {content_type.title()} Content Analysis: '{query}'\\n")
for market in markets:
print(f"📍 Market: {market}")
try:
results = sp.search(q=query, type=content_type, market=market, limit=5)
items = results[f"{content_type}s"]['items']
if items:
languages = set()
publishers = set()
print(f" Top {content_type}s:")
for item in items:
name = item['name']
publisher = item.get('publisher', 'Unknown')
item_languages = item.get('languages', [])
print(f" • {name} ({publisher})")
if item_languages:
print(f" Languages: {', '.join(item_languages)}")
languages.update(item_languages)
publishers.add(publisher)
print(f"\\n Summary for {market}:")
print(f" • Languages found: {', '.join(sorted(languages))}")
print(f" • Unique publishers: {len(publishers)}")
else:
print(f" No {content_type}s found")
except Exception as e:
print(f" Error: {e}")
print("-" * 40)
# Analyze podcast content across markets
analyze_content_by_market('show', 'politics', ['US', 'GB', 'CA', 'AU'])
analyze_content_by_market('audiobook', 'fiction', ['US', 'GB', 'DE'])id, name, description, publishertotal_episodes, languages, explicitimages, available_marketscopyrights, media_typeid, name, description, duration_msrelease_date, languages, explicitimages, show (simplified show object)resume_point (for authenticated users)id, name, description, publisherauthors, narrators, total_chapterslanguages, explicit, imagesavailable_markets, copyrightsNote: Podcast and audiobook availability varies by market. Some content may not be accessible in all regions due to licensing restrictions.
Install with Tessl CLI
npx tessl i tessl/pypi-spotipy