A light weight Python library for the Spotify Web API
Spotipy supports multiple OAuth2 flows for authenticating with the Spotify Web API. Choose the appropriate flow based on your application type and requirements.
For server-to-server authentication without user interaction. Provides access to public Spotify data only.
class SpotifyClientCredentials:
def __init__(self, client_id=None, client_secret=None, proxies=None,
requests_session=True, requests_timeout=None, cache_handler=None):
"""
Client Credentials flow for app-only authentication.
Args:
client_id (str, optional): Spotify client ID (from environment if not provided)
client_secret (str, optional): Spotify client secret (from environment if not provided)
proxies (dict, optional): Proxy configuration
requests_session (bool or requests.Session): HTTP session configuration
requests_timeout (int, optional): Request timeout in seconds
cache_handler (CacheHandler, optional): Token cache handler instance
"""
def validate_token(self, token_info):
"""
Validate and refresh token if necessary.
Args:
token_info (dict): Token information dictionary
Returns:
dict: Valid token information or None if invalid
"""
def get_access_token(self, as_dict=True):
"""
Get access token for client credentials flow.
Args:
as_dict (bool): Return full token info dict if True, token string if False
Returns:
dict or str: Token information or token string
"""For user authentication with full access to user data and actions. Requires user consent.
class SpotifyOAuth:
def __init__(self, client_id=None, client_secret=None, redirect_uri=None,
state=None, scope=None, cache_path=None, username=None,
proxies=None, requests_session=True, show_dialog=False,
requests_timeout=None, open_browser=True, cache_handler=None):
"""
Authorization Code flow for user authentication.
Args:
client_id (str, optional): Spotify client ID
client_secret (str, optional): Spotify client secret
redirect_uri (str, optional): Redirect URI registered with Spotify app
state (str, optional): State value for CSRF protection
scope (str or list, optional): Requested permission scopes
cache_path (str, optional): Path for token cache file (deprecated, use cache_handler)
username (str, optional): Username for cache file naming
proxies (dict, optional): Proxy configuration
requests_session (bool or requests.Session): HTTP session configuration
show_dialog (bool): Force consent dialog display (default: False)
requests_timeout (int, optional): Request timeout in seconds
open_browser (bool): Automatically open browser for authorization (default: True)
cache_handler (CacheHandler, optional): Token cache handler instance
"""
def validate_token(self, token_info):
"""
Validate token and refresh if necessary.
Args:
token_info (dict): Token information dictionary
Returns:
dict: Valid token information or None if invalid
"""
def get_access_token(self, code=None, as_dict=True, check_cache=True):
"""
Get access token using authorization code.
Args:
code (str, optional): Authorization code from callback
as_dict (bool): Return full token info dict if True, token string if False
check_cache (bool): Check cache for existing valid token
Returns:
dict or str: Token information or token string
"""
def refresh_access_token(self, refresh_token):
"""
Refresh access token using refresh token.
Args:
refresh_token (str): Refresh token from previous authorization
Returns:
dict: New token information
"""
def get_authorization_url(self):
"""
Get authorization URL for user consent.
Returns:
str: Authorization URL for user to visit
"""
def get_auth_response(self, open_browser=None):
"""
Get authorization response from user.
Args:
open_browser (bool, optional): Override open_browser setting
Returns:
str: Authorization code from user consent
"""
def parse_response_code(self, url):
"""
Parse authorization code from callback URL.
Args:
url (str): Callback URL containing authorization code
Returns:
str: Authorization code
"""
def parse_auth_response_url(self, url):
"""
Parse complete auth response from callback URL.
Args:
url (str): Callback URL from authorization
Returns:
str: Authorization code
"""
@property
def cache_handler(self):
"""Get current cache handler."""
@cache_handler.setter
def cache_handler(self, cache_handler):
"""Set cache handler."""Enhanced security flow using Proof Key for Code Exchange, recommended for mobile and single-page applications.
class SpotifyPKCE:
def __init__(self, client_id=None, redirect_uri=None, state=None, scope=None,
cache_path=None, username=None, proxies=None, requests_session=True,
show_dialog=False, requests_timeout=None, open_browser=True,
cache_handler=None):
"""
PKCE flow for enhanced security authentication.
Args:
client_id (str, optional): Spotify client ID
redirect_uri (str, optional): Redirect URI registered with Spotify app
state (str, optional): State value for CSRF protection
scope (str or list, optional): Requested permission scopes
cache_path (str, optional): Path for token cache file (deprecated)
username (str, optional): Username for cache file naming
proxies (dict, optional): Proxy configuration
requests_session (bool or requests.Session): HTTP session configuration
show_dialog (bool): Force consent dialog display (default: False)
requests_timeout (int, optional): Request timeout in seconds
open_browser (bool): Automatically open browser for authorization (default: True)
cache_handler (CacheHandler, optional): Token cache handler instance
"""
def validate_token(self, token_info):
"""Validate token and refresh if necessary."""
def get_access_token(self, code=None, as_dict=True, check_cache=True):
"""Get access token using authorization code with PKCE."""
def refresh_access_token(self, refresh_token):
"""Refresh access token using refresh token."""
def get_authorization_url(self):
"""Get authorization URL with PKCE parameters."""
def get_auth_response(self, open_browser=None):
"""Get authorization response from user."""
def parse_response_code(self, url):
"""Parse authorization code from callback URL."""
def parse_auth_response_url(self, url):
"""Parse complete auth response from callback URL."""Legacy flow for client-side applications. Use PKCE flow instead for new applications.
class SpotifyImplicitGrant:
def __init__(self, client_id=None, redirect_uri=None, state=None, scope=None,
cache_path=None, username=None, requests_session=True,
show_dialog=False, requests_timeout=None, cache_handler=None):
"""
Implicit Grant flow (deprecated - use PKCE instead).
Args:
client_id (str, optional): Spotify client ID
redirect_uri (str, optional): Redirect URI registered with Spotify app
state (str, optional): State value for CSRF protection
scope (str or list, optional): Requested permission scopes
cache_path (str, optional): Path for token cache file (deprecated)
username (str, optional): Username for cache file naming
requests_session (bool or requests.Session): HTTP session configuration
show_dialog (bool): Force consent dialog display (default: False)
requests_timeout (int, optional): Request timeout in seconds
cache_handler (CacheHandler, optional): Token cache handler instance
"""
def validate_token(self, token_info):
"""Validate token (no refresh available in implicit flow)."""
def get_access_token(self, response=None, as_dict=True, check_cache=True):
"""Get access token from implicit grant response."""
def get_authorization_url(self):
"""Get authorization URL for implicit grant."""
def get_auth_response(self):
"""Get authorization response from user."""
def parse_response_token(self, url):
"""Parse access token from callback URL fragment."""import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
# Using environment variables SPOTIPY_CLIENT_ID and SPOTIPY_CLIENT_SECRET
client_credentials_manager = SpotifyClientCredentials()
# Or providing credentials explicitly
client_credentials_manager = SpotifyClientCredentials(
client_id="your_client_id",
client_secret="your_client_secret"
)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
# Now you can access public Spotify data
results = sp.search(q='artist:radiohead', type='artist', limit=1)
artist = results['artists']['items'][0]
print(f"Artist: {artist['name']}")
print(f"Followers: {artist['followers']['total']}")import spotipy
from spotipy.oauth2 import SpotifyOAuth
# Define required scopes
scope = "user-read-private user-read-email user-library-read user-top-read"
# Initialize OAuth manager
auth_manager = SpotifyOAuth(
client_id="your_client_id",
client_secret="your_client_secret",
redirect_uri="http://localhost:8080/callback",
scope=scope,
show_dialog=True # Force consent dialog
)
sp = spotipy.Spotify(auth_manager=auth_manager)
# Access user's private data
user = sp.current_user()
print(f"User: {user['display_name']}")
print(f"Followers: {user['followers']['total']}")
# Get user's saved tracks
saved_tracks = sp.current_user_saved_tracks(limit=10)
print("\\nRecent saved tracks:")
for item in saved_tracks['items']:
track = item['track']
print(f" {track['name']} by {track['artists'][0]['name']}")import spotipy
from spotipy.oauth2 import SpotifyPKCE
scope = "user-read-private user-read-playback-state user-modify-playback-state"
auth_manager = SpotifyPKCE(
client_id="your_client_id",
redirect_uri="http://localhost:8080/callback",
scope=scope
)
sp = spotipy.Spotify(auth_manager=auth_manager)
# Control playback (requires premium account)
devices = sp.devices()
if devices['devices']:
device_id = devices['devices'][0]['id']
sp.start_playback(device_id=device_id)
print("Playback started!")from spotipy.oauth2 import SpotifyOAuth
from spotipy.cache_handler import CacheFileHandler
# Custom cache location
cache_handler = CacheFileHandler(cache_path=".spotify_cache", username="myuser")
auth_manager = SpotifyOAuth(
client_id="your_client_id",
client_secret="your_client_secret",
redirect_uri="http://localhost:8080/callback",
scope="user-library-read",
cache_handler=cache_handler
)
sp = spotipy.Spotify(auth_manager=auth_manager)from spotipy.oauth2 import SpotifyOAuth
auth_manager = SpotifyOAuth(
client_id="your_client_id",
client_secret="your_client_secret",
redirect_uri="http://localhost:8080/callback",
scope="user-library-read"
)
# Get authorization URL
auth_url = auth_manager.get_authorization_url()
print(f"Please visit: {auth_url}")
# Get authorization code from user
auth_code = input("Enter the authorization code: ")
# Exchange code for token
token_info = auth_manager.get_access_token(auth_code)
print(f"Access token: {token_info['access_token']}")
# Use token with Spotify client
sp = spotipy.Spotify(auth=token_info['access_token'])Common OAuth scopes for different functionality:
user-read-private, user-read-emailuser-library-read, user-library-modifyplaylist-read-private, playlist-read-collaborative, playlist-modify-private, playlist-modify-publicuser-read-playback-state, user-modify-playback-state, user-read-currently-playinguser-follow-read, user-follow-modifyuser-top-readuser-read-recently-playedstreaming (Web Playback SDK only)ugc-image-upload (playlist cover images)Combine scopes using spaces: "user-read-private user-library-read playlist-modify-public"
Set these environment variables to avoid hardcoding credentials:
export SPOTIPY_CLIENT_ID='your_client_id'
export SPOTIPY_CLIENT_SECRET='your_client_secret'
export SPOTIPY_REDIRECT_URI='http://localhost:8080/callback'Authentication errors are raised as SpotifyOauthError exceptions:
from spotipy.exceptions import SpotifyOauthError
try:
sp = spotipy.Spotify(auth_manager=auth_manager)
user = sp.current_user()
except SpotifyOauthError as e:
print(f"OAuth Error: {e}")
print(f"Error: {e.error}")
print(f"Description: {e.error_description}")Install with Tessl CLI
npx tessl i tessl/pypi-spotipy