Published on March 22, 2026

Building a playlist generator is one of the most rewarding projects for developers who want to combine music data with real application logic. Whether you're creating a mood-based mixtape tool or a recommendation engine for your users, MusicAPI gives you unified access to catalog data from Spotify, Apple Music, YouTube Music, and more through a single endpoint, making cross-platform playlist generation surprisingly straightforward.
| Takeaway | Explanation |
|---|---|
| Unified music API access | MusicAPI connects to Spotify, Apple Music, YouTube Music, and more via one API |
| Simple track search | Search across platforms with a single request and consistent response format |
| Playlist creation | Programmatically create and populate playlists on any supported platform |
| Cross-platform sync | Match and transfer tracks between services using MusicAPI's matching engine |
| Production-ready code | Complete Python and JavaScript examples you can adapt for your own projects |
In this music API tutorial, you will build a playlist generator that can search for tracks across multiple streaming platforms, assemble them into a cohesive playlist based on genre or artist similarity, and save that playlist directly to a user's streaming account. The finished application works with Spotify, Apple Music, YouTube Music, Deezer, Tidal, and other platforms — all through MusicAPI's unified interface.
By the end of this tutorial, you will have a working playlist generator that:
Before you start, make sure you have the following:
Head to the MusicAPI dashboard and create a new project. Your API key will be displayed on the project settings page. Store it securely — you will need it for every request.
MusicAPI uses a simple Bearer token authentication model. Every request includes your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Python:
pip install requests
JavaScript (Node.js):
npm install axios
That is all you need. MusicAPI is a REST API, so any HTTP client works. We use requests for Python and axios for JavaScript throughout this tutorial because they keep the code clean and readable.
The foundation of any playlist generator is track search. MusicAPI provides a unified search endpoint that queries across all connected platforms simultaneously.
Python:
import requests
API_KEY = "your_musicapi_key"
BASE_URL = "https://api.musicapi.com/v1"
def search_tracks(query, limit=20):
"""Search for tracks across all connected platforms."""
response = requests.get(
f"{BASE_URL}/search",
headers={"Authorization": f"Bearer {API_KEY}"},
params={
"q": query,
"type": "track",
"limit": limit
}
)
response.raise_for_status()
return response.json()["tracks"]
# Search for upbeat pop tracks
results = search_tracks("upbeat pop hits")
for track in results:
print(f"{track['name']} by {track['artist']} — {track['platform']}")
JavaScript:
const axios = require('axios');
const API_KEY = 'your_musicapi_key';
const BASE_URL = 'https://api.musicapi.com/v1';
async function searchTracks(query, limit = 20) {
const response = await axios.get(`${BASE_URL}/search`, {
headers: { Authorization: `Bearer ${API_KEY}` },
params: { q: query, type: 'track', limit }
});
return response.data.tracks;
}
// Search for upbeat pop tracks
const results = await searchTracks('upbeat pop hits');
results.forEach(track => {
console.log(`${track.name} by ${track.artist} — ${track.platform}`);
});
Each track object in the response includes a name, artist, album, platform, platformId, and duration — giving you everything you need to build playlist logic.
Raw search results are a starting point. A good playlist generator filters and ranks tracks to create a coherent listening experience. MusicAPI supports several filter parameters to narrow results before they reach your application:
Python:
def search_with_filters(query, genre=None, year_from=None, year_to=None, limit=20):
"""Search with optional genre and year filters."""
params = {
"q": query,
"type": "track",
"limit": limit
}
if genre:
params["genre"] = genre
if year_from:
params["year_from"] = year_from
if year_to:
params["year_to"] = year_to
response = requests.get(
f"{BASE_URL}/search",
headers={"Authorization": f"Bearer {API_KEY}"},
params=params
)
response.raise_for_status()
return response.json()["tracks"]
# Find indie rock tracks from the last two years
tracks = search_with_filters("indie rock", genre="rock", year_from=2024)
A genre-based playlist generator searches for tracks in a specific genre and assembles them into a balanced mix. The key is variety — you want different artists, tempos, and release years to keep the playlist interesting.
Python:
import random
def generate_genre_playlist(genre, track_count=25):
"""Generate a playlist based on a genre with artist diversity."""
search_queries = [
f"best {genre} songs",
f"new {genre} music",
f"popular {genre} tracks",
f"classic {genre} hits"
]
all_tracks = []
seen_artists = set()
for query in search_queries:
results = search_tracks(f"{query}", limit=30)
for track in results:
# Ensure artist diversity: max 2 tracks per artist
artist = track["artist"].lower()
if seen_artists.get(artist, 0) < 2 if isinstance(seen_artists, dict) else artist not in seen_artists:
all_tracks.append(track)
seen_artists.add(artist)
# Shuffle and trim to desired count
random.shuffle(all_tracks)
return all_tracks[:track_count]
playlist = generate_genre_playlist("electronic", track_count=20)
print(f"Generated playlist with {len(playlist)} tracks")
JavaScript:
async function generateGenrePlaylist(genre, trackCount = 25) {
const queries = [
`best ${genre} songs`,
`new ${genre} music`,
`popular ${genre} tracks`,
`classic ${genre} hits`
];
const allTracks = [];
const artistCount = {};
for (const query of queries) {
const results = await searchTracks(query, 30);
for (const track of results) {
const artist = track.artist.toLowerCase();
// Max 2 tracks per artist for variety
if ((artistCount[artist] || 0) < 2) {
allTracks.push(track);
artistCount[artist] = (artistCount[artist] || 0) + 1;
}
}
}
// Shuffle and trim
const shuffled = allTracks.sort(() => Math.random() - 0.5);
return shuffled.slice(0, trackCount);
}
const playlist = await generateGenrePlaylist('electronic', 20);
console.log(`Generated playlist with ${playlist.length} tracks`);
Another common pattern is building playlists around a seed artist. You find related artists and pull tracks from each one to create a discovery-focused listening experience.
Python:
def get_related_artists(artist_id):
"""Get artists similar to the given artist."""
response = requests.get(
f"{BASE_URL}/artists/{artist_id}/related",
headers={"Authorization": f"Bearer {API_KEY}"}
)
response.raise_for_status()
return response.json()["artists"]
def generate_artist_radio(seed_artist_name, track_count=20):
"""Build a playlist around a seed artist and related artists."""
# Find the seed artist
search_results = search_tracks(seed_artist_name, limit=5)
if not search_results:
return []
seed_artist_id = search_results[0]["artistId"]
related = get_related_artists(seed_artist_id)
playlist_tracks = []
# Add top tracks from the seed artist
seed_tracks = search_tracks(f"{seed_artist_name} top tracks", limit=5)
playlist_tracks.extend(seed_tracks[:3])
# Add tracks from related artists
for artist in related[:8]:
artist_tracks = search_tracks(f"{artist['name']} popular", limit=5)
playlist_tracks.extend(artist_tracks[:2])
random.shuffle(playlist_tracks)
return playlist_tracks[:track_count]
radio_playlist = generate_artist_radio("Daft Punk", track_count=15)
Once you have assembled your track list, the next step is creating an actual playlist on the user's streaming platform. MusicAPI handles the platform-specific API calls behind the scenes.
Python:
def create_playlist(user_id, name, description="", platform="spotify"):
"""Create a new empty playlist on the specified platform."""
response = requests.post(
f"{BASE_URL}/playlists",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"userId": user_id,
"name": name,
"description": description,
"platform": platform,
"public": True
}
)
response.raise_for_status()
return response.json()["playlist"]
new_playlist = create_playlist(
user_id="user_123",
name="Weekend Electronic Mix",
description="Auto-generated electronic playlist for the weekend"
)
print(f"Created playlist: {new_playlist['id']}")
JavaScript:
async function createPlaylist(userId, name, description = '', platform = 'spotify') {
const response = await axios.post(`${BASE_URL}/playlists`, {
userId,
name,
description,
platform,
public: true
}, {
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
});
return response.data.playlist;
}
const newPlaylist = await createPlaylist(
'user_123',
'Weekend Electronic Mix',
'Auto-generated electronic playlist for the weekend'
);
console.log(`Created playlist: ${newPlaylist.id}`);
With the playlist created, add tracks to it using the playlist tracks endpoint:
Python:
def add_tracks_to_playlist(playlist_id, track_ids):
"""Add a list of tracks to an existing playlist."""
response = requests.post(
f"{BASE_URL}/playlists/{playlist_id}/tracks",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={"trackIds": track_ids}
)
response.raise_for_status()
return response.json()
# Add generated tracks to the playlist
track_ids = [track["platformId"] for track in playlist]
result = add_tracks_to_playlist(new_playlist["id"], track_ids)
print(f"Added {result['addedCount']} tracks to playlist")
JavaScript:
async function addTracksToPlaylist(playlistId, trackIds) {
const response = await axios.post(
`${BASE_URL}/playlists/${playlistId}/tracks`,
{ trackIds },
{
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
}
);
return response.data;
}
const trackIds = playlist.map(track => track.platformId);
const result = await addTracksToPlaylist(newPlaylist.id, trackIds);
console.log(`Added ${result.addedCount} tracks to playlist`);
One of MusicAPI's most powerful features for building a playlist generator is cross-platform track matching. If a user has playlists on Spotify but wants to listen on Apple Music, you can match tracks between services automatically.
Python:
def match_track_cross_platform(track_id, source_platform, target_platform):
"""Find the equivalent track on a different platform."""
response = requests.get(
f"{BASE_URL}/tracks/{track_id}/match",
headers={"Authorization": f"Bearer {API_KEY}"},
params={
"sourcePlatform": source_platform,
"targetPlatform": target_platform
}
)
response.raise_for_status()
match = response.json()
return match.get("matchedTrack")
def sync_playlist_to_platform(playlist_tracks, source_platform, target_platform):
"""Sync a full playlist from one platform to another."""
matched_tracks = []
unmatched = []
for track in playlist_tracks:
matched = match_track_cross_platform(
track["platformId"], source_platform, target_platform
)
if matched:
matched_tracks.append(matched)
else:
unmatched.append(track)
return matched_tracks, unmatched
matched, missing = sync_playlist_to_platform(
playlist, "spotify", "apple_music"
)
print(f"Matched: {len(matched)}, Missing: {len(missing)}")
Not every track exists on every platform. A production-grade playlist generator needs to handle missing tracks without breaking the user experience.
Python:
def sync_with_fallback(playlist_tracks, source_platform, target_platform):
"""Sync playlist with search-based fallback for unmatched tracks."""
synced = []
failed = []
for track in playlist_tracks:
# Try direct match first
matched = match_track_cross_platform(
track["platformId"], source_platform, target_platform
)
if matched:
synced.append(matched)
continue
# Fallback: search by name and artist on target platform
query = f"{track['name']} {track['artist']}"
search_results = search_tracks(query, limit=3)
target_results = [
t for t in search_results
if t["platform"] == target_platform
]
if target_results:
synced.append(target_results[0])
else:
failed.append(track)
return synced, failed
Here is a complete Python script that ties everything together into a functional playlist generator:
Python:
import requests
import random
API_KEY = "your_musicapi_key"
BASE_URL = "https://api.musicapi.com/v1"
def search_tracks(query, limit=20):
response = requests.get(
f"{BASE_URL}/search",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"q": query, "type": "track", "limit": limit}
)
response.raise_for_status()
return response.json()["tracks"]
def create_playlist(user_id, name, description, platform):
response = requests.post(
f"{BASE_URL}/playlists",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"userId": user_id,
"name": name,
"description": description,
"platform": platform
}
)
response.raise_for_status()
return response.json()["playlist"]
def add_tracks_to_playlist(playlist_id, track_ids):
response = requests.post(
f"{BASE_URL}/playlists/{playlist_id}/tracks",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={"trackIds": track_ids}
)
response.raise_for_status()
return response.json()
def build_playlist(genre, user_id, platform="spotify", count=25):
"""End-to-end playlist generation pipeline."""
print(f"Searching for {genre} tracks...")
queries = [f"best {genre}", f"new {genre}", f"top {genre} hits"]
all_tracks = []
seen = set()
for q in queries:
for track in search_tracks(q, limit=30):
key = f"{track['name'].lower()}_{track['artist'].lower()}"
if key not in seen:
all_tracks.append(track)
seen.add(key)
random.shuffle(all_tracks)
selected = all_tracks[:count]
print(f"Found {len(selected)} unique tracks. Creating playlist...")
playlist = create_playlist(
user_id=user_id,
name=f"{genre.title()} Mix — Auto Generated",
description=f"A curated {genre} playlist generated with MusicAPI",
platform=platform
)
track_ids = [t["platformId"] for t in selected]
result = add_tracks_to_playlist(playlist["id"], track_ids)
print(f"Playlist created with {result['addedCount']} tracks!")
return playlist
# Run the generator
my_playlist = build_playlist(
genre="lo-fi hip hop",
user_id="user_123",
platform="spotify",
count=20
)
JavaScript:
const axios = require('axios');
const API_KEY = 'your_musicapi_key';
const BASE_URL = 'https://api.musicapi.com/v1';
const headers = { Authorization: `Bearer ${API_KEY}` };
async function buildPlaylist(genre, userId, platform = 'spotify', count = 25) {
console.log(`Searching for ${genre} tracks...`);
const queries = [`best ${genre}`, `new ${genre}`, `top ${genre} hits`];
const allTracks = [];
const seen = new Set();
for (const q of queries) {
const response = await axios.get(`${BASE_URL}/search`, {
headers,
params: { q, type: 'track', limit: 30 }
});
for (const track of response.data.tracks) {
const key = `${track.name.toLowerCase()}_${track.artist.toLowerCase()}`;
if (!seen.has(key)) {
allTracks.push(track);
seen.add(key);
}
}
}
const shuffled = allTracks.sort(() => Math.random() - 0.5).slice(0, count);
console.log(`Found ${shuffled.length} unique tracks. Creating playlist...`);
const { data: { playlist } } = await axios.post(`${BASE_URL}/playlists`, {
userId,
name: `${genre.charAt(0).toUpperCase() + genre.slice(1)} Mix — Auto Generated`,
description: `A curated ${genre} playlist generated with MusicAPI`,
platform
}, { headers: { ...headers, 'Content-Type': 'application/json' } });
const trackIds = shuffled.map(t => t.platformId);
const { data: result } = await axios.post(
`${BASE_URL}/playlists/${playlist.id}/tracks`,
{ trackIds },
{ headers: { ...headers, 'Content-Type': 'application/json' } }
);
console.log(`Playlist created with ${result.addedCount} tracks!`);
return playlist;
}
buildPlaylist('lo-fi hip hop', 'user_123', 'spotify', 20);
Now that you have a working playlist generator, here are some ideas to take it further:
MusicAPI handles the complex platform integrations so you can focus on building great playlist experiences. Check out the full API documentation for additional endpoints covering user libraries, playback history, and audio features.
Ready to build your own playlist generator? Sign up for MusicAPI and start building today — the free tier includes enough requests to prototype and test your application.