The Spotify SDK provides two client classes for interacting with the Spotify API: SpotifyClient for synchronous code and AsyncSpotifyClient for asynchronous code.
Client Classes
SpotifyClient
The synchronous client for blocking I/O operations:
from spotify_sdk import SpotifyClient
client = SpotifyClient( access_token = "your-access-token" )
album = client.albums.get( "4aawyAB9vmqN3uQ7FjRGTy" )
print ( f " { album.name } by { album.artists[ 0 ].name } " )
client.close()
Source : src/spotify_sdk/_sync/_client.py:22-115
AsyncSpotifyClient
The asynchronous client for non-blocking I/O with async/await:
import asyncio
from spotify_sdk import AsyncSpotifyClient
async def main ():
client = AsyncSpotifyClient( access_token = "your-access-token" )
album = await client.albums.get( "4aawyAB9vmqN3uQ7FjRGTy" )
print ( f " { album.name } by { album.artists[ 0 ].name } " )
await client.close()
asyncio.run(main())
Source : src/spotify_sdk/_async/_client.py:22-115
Both clients share the same API surface. The only difference is that AsyncSpotifyClient methods are async and must be awaited.
When to Use Each Client
Use SpotifyClient
Simple scripts and CLI tools
Synchronous web frameworks (Flask, Django)
Jupyter notebooks
Sequential data processing
Use AsyncSpotifyClient
Async frameworks (FastAPI, aiohttp)
Concurrent requests
High-performance applications
WebSocket servers
Client Initialization
Both clients support three initialization methods:
Access Token
Client Credentials
Auth Provider
from spotify_sdk import SpotifyClient
client = SpotifyClient( access_token = "your-access-token" )
from spotify_sdk import SpotifyClient
client = SpotifyClient(
client_id = "your-client-id" ,
client_secret = "your-client-secret" ,
)
from spotify_sdk import SpotifyClient
from spotify_sdk.auth import AuthorizationCode
auth = AuthorizationCode(
client_id = "your-client-id" ,
client_secret = "your-client-secret" ,
redirect_uri = "http://127.0.0.1:8080/callback" ,
)
auth.authorize_local()
client = SpotifyClient( auth_provider = auth)
You must provide exactly one authentication method. Providing multiple methods raises a ValueError.
Configuration Options
Customize client behavior with configuration parameters:
Timeout
Set the default request timeout in seconds:
client = SpotifyClient(
access_token = "your-access-token" ,
timeout = 30.0 , # Default: 30.0 seconds
)
Default request timeout in seconds. Applies to all HTTP requests made by the client.
Max Retries
Configure automatic retry behavior:
client = SpotifyClient(
access_token = "your-access-token" ,
max_retries = 3 , # Default: 3
)
Maximum number of retry attempts for failed requests. The SDK automatically retries on:
Connection errors and timeouts
Rate limit responses (429)
Server errors (5xx)
Retries use exponential backoff with jitter:
Initial delay: 0.5 seconds
Maximum delay: 8.0 seconds
Multiplier: 2x per retry
Complete Configuration
from spotify_sdk import SpotifyClient
client = SpotifyClient(
access_token = "your-access-token" ,
timeout = 15.0 , # 15 second timeout
max_retries = 5 , # Retry up to 5 times
)
Factory Methods
Convenience methods for common initialization patterns:
from_client_credentials
Create a client using the client credentials flow:
from spotify_sdk import SpotifyClient
client = SpotifyClient.from_client_credentials(
client_id = "your-client-id" ,
client_secret = "your-client-secret" ,
timeout = 30.0 ,
max_retries = 3 ,
)
Source : src/spotify_sdk/_sync/_client.py:90-108
Service Properties
Clients provide access to API services through properties:
client = SpotifyClient( access_token = "your-access-token" )
# Access different services
client.albums # Album operations
client.artists # Artist operations
client.audiobooks # Audiobook operations
client.chapters # Chapter operations
client.episodes # Episode operations
client.library # User library operations
client.playlists # Playlist operations
client.search # Search operations
client.shows # Show/podcast operations
client.tracks # Track operations
client.users # User profile operations
Each service is initialized when the client is created:
# From source: src/spotify_sdk/_sync/_client.py:73-84
self .albums = AlbumService( self ._base_client)
self .audiobooks = AudiobookService( self ._base_client)
self .chapters = ChapterService( self ._base_client)
self .episodes = EpisodeService( self ._base_client)
self .library = LibraryService( self ._base_client)
self .search = SearchService( self ._base_client)
self .shows = ShowService( self ._base_client)
self .tracks = TrackService( self ._base_client)
self .artists = ArtistService( self ._base_client)
self .playlists = PlaylistService( self ._base_client)
self .users = UserService( self ._base_client)
Context Managers
Use context managers for automatic resource cleanup:
Synchronous Context Manager
from spotify_sdk import SpotifyClient
with SpotifyClient( access_token = "your-access-token" ) as client:
album = client.albums.get( "4aawyAB9vmqN3uQ7FjRGTy" )
print (album.name)
# Client is automatically closed
Source : src/spotify_sdk/_sync/_client.py:110-114
Asynchronous Context Manager
import asyncio
from spotify_sdk import AsyncSpotifyClient
async def main ():
async with AsyncSpotifyClient( access_token = "your-access-token" ) as client:
album = await client.albums.get( "4aawyAB9vmqN3uQ7FjRGTy" )
print (album.name)
# Client is automatically closed
asyncio.run(main())
Source : src/spotify_sdk/_async/_client.py:110-114
Context managers automatically call close() (or await close()) when exiting the context, ensuring proper resource cleanup.
Resource Management
Manual Cleanup
Explicitly close clients when done:
from spotify_sdk import SpotifyClient
client = SpotifyClient( access_token = "your-access-token" )
try :
album = client.albums.get( "4aawyAB9vmqN3uQ7FjRGTy" )
print (album.name)
finally :
client.close()
What Gets Closed
Calling client.close() releases:
HTTP connections : Closes the underlying httpx.Client or httpx.AsyncClient
Auth provider : Closes the auth provider’s HTTP client (if using an auth provider)
# From source: src/spotify_sdk/_sync/_client.py:86-88
def close ( self ) -> None :
"""Close the client and release resources."""
self ._base_client.close()
Failing to close clients may result in:
Resource warnings about unclosed sockets
Connection pool exhaustion
Memory leaks in long-running applications
Long-Lived Clients
For long-running applications, reuse a single client instance:
from spotify_sdk import SpotifyClient
class MusicService :
def __init__ ( self ):
self .client = SpotifyClient.from_client_credentials(
client_id = "your-client-id" ,
client_secret = "your-client-secret" ,
)
def get_album ( self , album_id : str ):
return self .client.albums.get(album_id)
def search_tracks ( self , query : str ):
return self .client.search.search( q = query, types = [ "track" ])
def close ( self ):
self .client.close()
# Use the service
service = MusicService()
try :
album = service.get_album( "4aawyAB9vmqN3uQ7FjRGTy" )
results = service.search_tracks( "kind of blue" )
finally :
service.close()
Multiple Clients
You can use multiple clients simultaneously:
from spotify_sdk import SpotifyClient
from spotify_sdk.auth import AuthorizationCode, ClientCredentials
# Public data client (client credentials)
public_client = SpotifyClient.from_client_credentials(
client_id = "your-client-id" ,
client_secret = "your-client-secret" ,
)
# User-specific client (authorization code)
auth = AuthorizationCode(
client_id = "your-client-id" ,
client_secret = "your-client-secret" ,
redirect_uri = "http://127.0.0.1:8080/callback" ,
scope = [ "user-library-read" ],
)
auth.authorize_local()
user_client = SpotifyClient( auth_provider = auth)
try :
# Get public album data
album = public_client.albums.get( "4aawyAB9vmqN3uQ7FjRGTy" )
# Get user's saved albums
saved = user_client.albums.get_saved( limit = 10 )
finally :
public_client.close()
user_client.close()
Error Handling
Clients raise specific exceptions for different error conditions:
from spotify_sdk import (
SpotifyClient,
AuthenticationError,
NotFoundError,
RateLimitError,
ServerError,
)
client = SpotifyClient( access_token = "your-access-token" )
try :
album = client.albums.get( "invalid-id" )
except AuthenticationError:
print ( "Invalid or expired token" )
except NotFoundError:
print ( "Album not found" )
except RateLimitError as e:
print ( f "Rate limited. Retry after { e.retry_after } seconds" )
except ServerError:
print ( "Spotify server error" )
finally :
client.close()
See Error Handling for more details.
Thread Safety
SpotifyClient is not thread-safe . Do not share client instances across threads.
For multi-threaded applications, create a client per thread:
import threading
from spotify_sdk import SpotifyClient
def fetch_album ( album_id : str ):
# Each thread gets its own client
client = SpotifyClient( access_token = "your-access-token" )
try :
album = client.albums.get(album_id)
print ( f " { album.name } by { album.artists[ 0 ].name } " )
finally :
client.close()
threads = [
threading.Thread( target = fetch_album, args = (album_id,))
for album_id in [ "4aawyAB9vmqN3uQ7FjRGTy" , "5K79FLRUCSysQnVESLcTdb" ]
]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
Best Practices
Use Context Managers
Prefer with or async with for automatic resource cleanup: with SpotifyClient( access_token = "token" ) as client:
album = client.albums.get( "id" )
Reuse Clients
Create one client and reuse it for multiple requests to benefit from connection pooling: client = SpotifyClient( access_token = "token" )
for album_id in album_ids:
album = client.albums.get(album_id)
client.close()
Configure Timeouts
Set appropriate timeouts for your use case: client = SpotifyClient(
access_token = "token" ,
timeout = 15.0 , # Shorter timeout for interactive apps
)
Handle Errors
Always handle potential exceptions: from spotify_sdk import NotFoundError
try :
album = client.albums.get(album_id)
except NotFoundError:
print ( "Album not found" )