track
Songs and audio tracks
Find tracks, artists, albums, and playlists using the Spotify Search API
The Search API is one of the most powerful features of Spotify’s Web API, allowing you to find any content in Spotify’s catalog. This guide covers searching, filtering, and building discovery features.
The search endpoint accepts a query string and returns results across multiple content types.
import Spotted from "spotted-ts";
const client = new Spotted();
// Search for tracksconst results = await client.search.query({ q: "bohemian rhapsody", type: ["track"], limit: 20,});
console.log(results.tracks.items[0].name); // "Bohemian Rhapsody"track
Songs and audio tracks
artist
Musicians and bands
album
Albums and compilations
playlist
User and editorial playlists
show
Podcasts
episode
Podcast episodes
audiobook
Audiobooks
Search across multiple content types in a single request:
const results = await client.search.query({ q: "taylor swift", type: ["artist", "album", "track"],});
console.log("Artists:", results.artists.items.length);console.log("Albums:", results.albums.items.length);console.log("Tracks:", results.tracks.items.length);Spotify supports field filters to narrow down search results.
| Filter | Description | Example |
|---|---|---|
artist: | Filter by artist name | artist:radiohead |
album: | Filter by album name | album:ok computer |
track: | Filter by track name | track:creep |
year: | Filter by release year | year:1997 |
genre: | Filter by genre | genre:rock |
isrc: | Filter by ISRC code | isrc:USRC11700120 |
// Find all tracks by Radiohead from the album "OK Computer"const results = await client.search.query({ q: "artist:radiohead album:ok computer", type: ["track"],});
// Find tracks released in 2023const newTracks = await client.search.query({ q: "year:2023", type: ["track"], limit: 50,});
// Find rock playlistsconst rockPlaylists = await client.search.query({ q: "genre:rock", type: ["playlist"],});
// Combine multiple filtersconst specific = await client.search.query({ q: "artist:the beatles track:yesterday year:1965", type: ["track"],});// Tracks from the 90sconst ninetiesTracks = await client.search.query({ q: "year:1990-1999", type: ["track"],});
// Recent releases (2020 onwards)const recentTracks = await client.search.query({ q: "year:2020-2024", type: ["track"],});// Find tracks starting with "love"const loveSongs = await client.search.query({ q: "track:love*", type: ["track"],});Here’s how to build a search feature with pagination using the SDK:
import Spotted from "spotted-ts";
const client = new Spotted();
// Simple searchconst results = await client.search.query({ q: "daft punk", type: ["track", "artist", "album"], market: "US",});
// Search with pagination using async iteratorasync function getAllTracks(query, maxResults = 100) { const allTracks = [];
for await (const track of client.search.query({ q: query, type: ["track"], })) { allTracks.push(track); if (allTracks.length >= maxResults) break; }
return allTracks;}
// Get all matching tracks (up to 100)const allTracks = await getAllTracks("daft punk");console.log(`Found ${allTracks.length} tracks`);Generate personalized track recommendations based on seed artists, tracks, or genres:
import Spotted from "spotted-ts";
const client = new Spotted();
// Get recommendations based on artists and genresconst recs = await client.recommendations.list({ seed_artists: "4NHQUGzhtTLFvgF5SZesLK", // Tame Impala seed_genres: "psychedelic rock", limit: 10,});
console.log("Recommended tracks:");recs.tracks.forEach((track) => { console.log(`${track.name} by ${track.artists[0].name}`);});
// Get upbeat dance recommendations with audio feature targetsconst danceRecs = await client.recommendations.list({ seed_genres: "dance,electronic", target_energy: 0.8, target_danceability: 0.9, target_valence: 0.7, // Happy vibes limit: 20,});// Get all available genre seedsconst { genres } = await client.recommendations.listAvailableGenreSeeds();
// Returns genres like: ["acoustic", "alt-rock", "ambient", "blues", ...]console.log(genres);Discover newly released albums:
// Get new releasesconst newReleases = await client.browse.listNewReleases({ country: "US", limit: 50,});
newReleases.albums.items.forEach((album) => { console.log(`${album.name} by ${album.artists[0].name}`);});
// Or iterate through all new releasesfor await (const album of client.browse.listNewReleases({ country: "US" })) { console.log(`${album.name} by ${album.artists[0].name}`);}Get Spotify’s curated featured playlists:
// Get current featured playlistsconst featured = await client.browse.listFeaturedPlaylists({ country: "US", locale: "en_US", limit: 20,});
console.log(featured.message); // e.g., "Good morning"featured.playlists.items.forEach((playlist) => { console.log(playlist.name);});
// Get playlists for a specific time (ISO 8601 format)const fridayNight = await client.browse.listFeaturedPlaylists({ timestamp: "2024-01-19T21:00:00",});Explore Spotify’s browse categories:
// Get all categoriesfor await (const category of client.browse.categories.list({ country: "US", locale: "en_US",})) { console.log(`${category.id}: ${category.name}`);}
// Get a specific categoryconst category = await client.browse.categories.retrieve("workout", { country: "US",});console.log(category.name);
// Get playlists for a categoryconst workoutPlaylists = await client.browse.categories.listPlaylists( "workout", { country: "US", limit: 20, },);
workoutPlaylists.playlists.items.forEach((playlist) => { console.log(playlist.name);});Here’s a full example combining search and discovery features using the SDK:
import Spotted from "spotted-ts";
const client = new Spotted();
// Find similar tracks to a given trackasync function findSimilarTracks(trackId, limit = 20) { // Get the track's audio features const features = await client.audioFeatures.retrieve(trackId);
// Get recommendations based on the track and its features return client.recommendations.list({ seed_tracks: trackId, target_energy: features.energy, target_danceability: features.danceability, target_valence: features.valence, limit, });}
// Discover tracks by moodasync function discoverByMood(mood, genres = ["pop"]) { const moodSettings = { happy: { target_valence: 0.8, target_energy: 0.7 }, sad: { target_valence: 0.2, target_energy: 0.3 }, energetic: { target_energy: 0.9, target_danceability: 0.8 }, chill: { target_energy: 0.3, target_acousticness: 0.7 }, focus: { target_instrumentalness: 0.8, target_energy: 0.5 }, };
const settings = moodSettings[mood] || {};
return client.recommendations.list({ seed_genres: genres.slice(0, 5).join(","), limit: 30, ...settings, });}
// Build a "radio" based on an artistasync function artistRadio(artistId) { // Get artist's top tracks const { tracks: topTracks } = await client.artists.getTopTracks(artistId, { market: "US", });
// Get related artists const { artists: related } = await client.artists.getRelatedArtists(artistId);
// Use top track and related artists as seeds const seedTracks = topTracks.slice(0, 2).map((t) => t.id); const seedArtists = related.slice(0, 3).map((a) => a.id);
return client.recommendations.list({ seed_tracks: seedTracks.join(","), seed_artists: seedArtists.join(","), limit: 50, });}
// Search and enrich with audio featuresasync function searchWithFeatures(query) { const searchResults = await client.search.query({ q: query, type: ["track"], limit: 10, });
const tracks = searchResults.tracks.items; if (tracks.length === 0) return [];
// Get audio features for all tracks const ids = tracks.map((t) => t.id).join(","); const { audio_features } = await client.audioFeatures.bulkRetrieve({ ids });
return tracks.map((track, i) => ({ ...track, audioFeatures: audio_features[i], }));}
// Usage examplesconst similar = await findSimilarTracks("0VjIjW4GlUZAMYd2vXMi3b"); // Blinding Lightsconst chillTracks = await discoverByMood("chill", ["ambient", "electronic"]);const weekndRadio = await artistRadio("1Xyo4u8uXC1ZmMpatF05PJ"); // The Weekndconst tracksWithFeatures = await searchWithFeatures("summer vibes");async function fetchWithRetry(url, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { const response = await fetch(url, options);
if (response.status === 429) { const retryAfter = parseInt(response.headers.get("Retry-After") || "1"); console.log(`Rate limited. Waiting ${retryAfter} seconds...`); await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000)); continue; }
return response; }
throw new Error("Max retries exceeded");}