Spotify Web API Guide: Complete Tutorial (2026)
Build music-powered applications with the Spotify API
Start Building with Hypereal
Access Kling, Flux, Sora, Veo & more through a single API. Free credits to start, scale to millions.
No credit card required • 100k+ developers • Enterprise ready
Spotify Web API Guide: Complete Tutorial (2026)
The Spotify Web API gives developers access to Spotify's massive music catalog, user playlists, playback control, audio features, and recommendation engine. Whether you are building a music discovery app, a playlist generator, a data visualization tool, or integrating Spotify into an existing product, this guide covers everything you need to get started.
What Can You Build with the Spotify API?
| Use Case | Endpoints Used |
|---|---|
| Music search and discovery | Search, Recommendations, Browse |
| Playlist creation and management | Playlists, Tracks |
| User profile and listening data | User Profile, Top Items, Recently Played |
| Audio analysis (BPM, key, energy) | Audio Features, Audio Analysis |
| Playback control | Player (requires Premium) |
| Artist and album data | Artists, Albums |
Getting Started
Step 1: Create a Spotify Developer Account
- Go to developer.spotify.com.
- Log in with your Spotify account (free or Premium both work).
- Navigate to the Dashboard.
- Click Create App.
- Fill in the app name, description, and redirect URI (use
http://localhost:3000/callbackfor development). - Note your Client ID and Client Secret.
Step 2: Understand the Authentication Flows
Spotify uses OAuth 2.0 with several flows depending on your use case:
| Flow | Use Case | User Login Required | Access to User Data |
|---|---|---|---|
| Client Credentials | Server-to-server, public data only | No | No |
| Authorization Code | Web apps that need user data | Yes | Yes |
| Authorization Code + PKCE | SPAs and mobile apps | Yes | Yes |
| Implicit Grant | Deprecated (do not use) | Yes | Yes |
For most applications, you will use either Client Credentials (for public data) or Authorization Code + PKCE (for user-specific data).
Step 3: Install the SDK
Python:
pip install spotipy
Node.js:
npm install spotify-web-api-node
Or use raw HTTP requests with any language -- the API is REST-based.
Authentication: Client Credentials Flow
Use this flow when you only need public data (search, artist info, album tracks) and do not need to access any user's private data.
Python with Spotipy
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
client_credentials_manager = SpotifyClientCredentials(
client_id="your-client-id",
client_secret="your-client-secret",
)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
# Search for tracks
results = sp.search(q="artist:Radiohead", type="track", limit=10)
for track in results["tracks"]["items"]:
print(f"{track['name']} - {track['album']['name']}")
Node.js
import SpotifyWebApi from "spotify-web-api-node";
const spotifyApi = new SpotifyWebApi({
clientId: "your-client-id",
clientSecret: "your-client-secret",
});
// Get access token
const data = await spotifyApi.clientCredentialsGrant();
spotifyApi.setAccessToken(data.body["access_token"]);
// Search for tracks
const results = await spotifyApi.searchTracks("artist:Radiohead", { limit: 10 });
results.body.tracks.items.forEach((track) => {
console.log(`${track.name} - ${track.album.name}`);
});
cURL
# Get access token
TOKEN=$(curl -s -X POST https://accounts.spotify.com/api/token \
-u "your-client-id:your-client-secret" \
-d "grant_type=client_credentials" | jq -r '.access_token')
# Search for tracks
curl -s "https://api.spotify.com/v1/search?q=artist:Radiohead&type=track&limit=5" \
-H "Authorization: Bearer $TOKEN" | jq '.tracks.items[] | {name, album: .album.name}'
Authentication: Authorization Code Flow with PKCE
Use this flow when you need access to user-specific data like their playlists, top tracks, or playback control.
Python Example with Flask
import spotipy
from spotipy.oauth2 import SpotifyOAuth
from flask import Flask, redirect, request, session
app = Flask(__name__)
app.secret_key = "your-secret-key"
SCOPE = "user-read-recently-played user-top-read playlist-modify-public"
@app.route("/login")
def login():
sp_oauth = SpotifyOAuth(
client_id="your-client-id",
client_secret="your-client-secret",
redirect_uri="http://localhost:3000/callback",
scope=SCOPE,
)
auth_url = sp_oauth.get_authorize_url()
return redirect(auth_url)
@app.route("/callback")
def callback():
sp_oauth = SpotifyOAuth(
client_id="your-client-id",
client_secret="your-client-secret",
redirect_uri="http://localhost:3000/callback",
scope=SCOPE,
)
code = request.args.get("code")
token_info = sp_oauth.get_access_token(code)
session["token_info"] = token_info
return redirect("/top-tracks")
@app.route("/top-tracks")
def top_tracks():
token_info = session.get("token_info")
sp = spotipy.Spotify(auth=token_info["access_token"])
results = sp.current_user_top_tracks(limit=20, time_range="medium_term")
tracks = []
for track in results["items"]:
tracks.append(f"{track['name']} by {track['artists'][0]['name']}")
return "<br>".join(tracks)
Common API Endpoints
Search
Search across tracks, artists, albums, playlists, and podcasts:
# Search for tracks
results = sp.search(q="genre:electronic year:2025-2026", type="track", limit=20)
# Search for artists
results = sp.search(q="Daft Punk", type="artist", limit=5)
# Search with multiple types
results = sp.search(q="jazz", type="track,artist,album", limit=10)
Get Audio Features
Audio features provide musical attributes for tracks:
# Get audio features for a single track
features = sp.audio_features("track-id-here")[0]
print(f"BPM: {features['tempo']}")
print(f"Key: {features['key']}")
print(f"Energy: {features['energy']}")
print(f"Danceability: {features['danceability']}")
print(f"Valence (mood): {features['valence']}")
Audio feature values and their meanings:
| Feature | Range | Low Value Means | High Value Means |
|---|---|---|---|
energy |
0.0-1.0 | Calm, quiet | Loud, intense |
danceability |
0.0-1.0 | Hard to dance to | Easy to dance to |
valence |
0.0-1.0 | Sad, angry | Happy, cheerful |
tempo |
BPM | Slow | Fast |
acousticness |
0.0-1.0 | Electronic | Acoustic |
instrumentalness |
0.0-1.0 | Vocals present | Instrumental |
speechiness |
0.0-1.0 | Music | Spoken word |
Get Recommendations
Build a recommendation engine using seed tracks, artists, or genres:
# Get recommendations based on seed tracks and target audio features
recommendations = sp.recommendations(
seed_tracks=["track-id-1", "track-id-2"],
seed_genres=["electronic"],
limit=20,
target_energy=0.8,
target_danceability=0.7,
min_tempo=120,
max_tempo=140,
)
for track in recommendations["tracks"]:
print(f"{track['name']} by {track['artists'][0]['name']}")
Manage Playlists
Create, read, and modify playlists:
# Create a new playlist
playlist = sp.user_playlist_create(
user=sp.current_user()["id"],
name="My AI-Generated Playlist",
public=True,
description="Created with the Spotify API",
)
# Add tracks to the playlist
track_uris = ["spotify:track:id1", "spotify:track:id2", "spotify:track:id3"]
sp.playlist_add_items(playlist["id"], track_uris)
# Get a playlist's tracks
tracks = sp.playlist_tracks("playlist-id")
for item in tracks["items"]:
track = item["track"]
print(f"{track['name']} by {track['artists'][0]['name']}")
Control Playback (Premium Required)
# Get currently playing track
current = sp.current_playback()
if current and current["is_playing"]:
track = current["item"]
print(f"Now playing: {track['name']} by {track['artists'][0]['name']}")
# Skip to next track
sp.next_track()
# Set volume
sp.volume(75)
# Start playback on a specific device
devices = sp.devices()
device_id = devices["devices"][0]["id"]
sp.start_playback(device_id=device_id, uris=["spotify:track:track-id"])
Building a Playlist Generator
Here is a complete example that creates a playlist based on a mood parameter:
import spotipy
from spotipy.oauth2 import SpotifyOAuth
MOOD_PRESETS = {
"workout": {
"seed_genres": ["electronic", "hip-hop"],
"target_energy": 0.9,
"target_danceability": 0.8,
"min_tempo": 130,
},
"chill": {
"seed_genres": ["ambient", "chill"],
"target_energy": 0.3,
"target_valence": 0.4,
"max_tempo": 100,
},
"focus": {
"seed_genres": ["classical", "ambient"],
"target_instrumentalness": 0.8,
"target_energy": 0.4,
"target_speechiness": 0.0,
},
"party": {
"seed_genres": ["pop", "dance"],
"target_energy": 0.85,
"target_danceability": 0.9,
"target_valence": 0.8,
},
}
def create_mood_playlist(sp, mood, num_tracks=25):
if mood not in MOOD_PRESETS:
raise ValueError(f"Unknown mood: {mood}. Options: {list(MOOD_PRESETS.keys())}")
params = MOOD_PRESETS[mood]
recommendations = sp.recommendations(limit=num_tracks, **params)
track_uris = [track["uri"] for track in recommendations["tracks"]]
user_id = sp.current_user()["id"]
playlist = sp.user_playlist_create(
user=user_id,
name=f"{mood.capitalize()} Mix - AI Generated",
description=f"A {mood} playlist generated with the Spotify API.",
)
sp.playlist_add_items(playlist["id"], track_uris)
return playlist["external_urls"]["spotify"]
# Usage
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(
client_id="your-client-id",
client_secret="your-client-secret",
redirect_uri="http://localhost:3000/callback",
scope="playlist-modify-public",
))
url = create_mood_playlist(sp, "workout")
print(f"Playlist created: {url}")
Rate Limits and Best Practices
Rate Limits
Spotify uses a sliding window rate limit. The exact limits are not publicly documented, but general guidelines:
| Guideline | Recommendation |
|---|---|
| Requests per second | Keep under 10 for most endpoints |
| Batch endpoints | Use batch versions (e.g., get multiple tracks in one call) |
| Retry on 429 | Respect the Retry-After header |
| Token refresh | Refresh before expiry (tokens last 1 hour) |
Error Handling
from spotipy.exceptions import SpotifyException
import time
def safe_request(func, *args, max_retries=3, **kwargs):
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except SpotifyException as e:
if e.http_status == 429:
retry_after = int(e.headers.get("Retry-After", 5))
print(f"Rate limited. Waiting {retry_after}s...")
time.sleep(retry_after)
elif e.http_status == 401:
print("Token expired. Refreshing...")
# Handle token refresh
raise
else:
raise
raise Exception("Max retries exceeded")
Pagination
Many Spotify endpoints return paginated results. Always handle pagination for complete data:
def get_all_playlist_tracks(sp, playlist_id):
tracks = []
results = sp.playlist_tracks(playlist_id, limit=100)
while results:
tracks.extend(results["items"])
results = sp.next(results) if results["next"] else None
return tracks
Available OAuth Scopes
| Scope | Access |
|---|---|
user-read-private |
User's subscription details and country |
user-read-email |
User's email address |
user-top-read |
User's top artists and tracks |
user-read-recently-played |
User's recently played tracks |
playlist-read-private |
User's private playlists |
playlist-modify-public |
Create and edit public playlists |
playlist-modify-private |
Create and edit private playlists |
user-read-playback-state |
Current playback state |
user-modify-playback-state |
Control playback (Premium only) |
user-library-read |
User's saved tracks and albums |
user-library-modify |
Save and remove tracks and albums |
Request only the scopes your application needs. Users see the requested permissions during authorization and may decline if you ask for too much.
Conclusion
The Spotify Web API is one of the most well-documented and developer-friendly music APIs available. Whether you are building a simple playlist generator or a complex music analytics platform, the combination of search, recommendations, audio features, and user data provides a rich foundation.
If you are building applications that combine music with AI-generated media -- such as creating visualizations, talking avatar videos, or AI-generated album art -- check out Hypereal AI. Hypereal provides a unified API for image generation, video creation, and talking avatars with pay-as-you-go pricing.
Related Articles
Start Building Today
Get 35 free credits on signup. No credit card required. Generate your first image in under 5 minutes.
