Skip to content
DocumentationAPI Reference

Search & Discovery

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 tracks
const 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.

FilterDescriptionExample
artist:Filter by artist nameartist:radiohead
album:Filter by album namealbum:ok computer
track:Filter by track nametrack:creep
year:Filter by release yearyear:1997
genre:Filter by genregenre:rock
isrc:Filter by ISRC codeisrc: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 2023
const newTracks = await client.search.query({
q: "year:2023",
type: ["track"],
limit: 50,
});
// Find rock playlists
const rockPlaylists = await client.search.query({
q: "genre:rock",
type: ["playlist"],
});
// Combine multiple filters
const specific = await client.search.query({
q: "artist:the beatles track:yesterday year:1965",
type: ["track"],
});
// Tracks from the 90s
const 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 search
const results = await client.search.query({
q: "daft punk",
type: ["track", "artist", "album"],
market: "US",
});
// Search with pagination using async iterator
async 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 genres
const 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 targets
const 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 seeds
const { genres } = await client.recommendations.listAvailableGenreSeeds();
// Returns genres like: ["acoustic", "alt-rock", "ambient", "blues", ...]
console.log(genres);

Discover newly released albums:

// Get new releases
const 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 releases
for 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 playlists
const 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 categories
for await (const category of client.browse.categories.list({
country: "US",
locale: "en_US",
})) {
console.log(`${category.id}: ${category.name}`);
}
// Get a specific category
const category = await client.browse.categories.retrieve("workout", {
country: "US",
});
console.log(category.name);
// Get playlists for a category
const 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 track
async 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 mood
async 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 artist
async 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 features
async 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 examples
const similar = await findSimilarTracks("0VjIjW4GlUZAMYd2vXMi3b"); // Blinding Lights
const chillTracks = await discoverByMood("chill", ["ambient", "electronic"]);
const weekndRadio = await artistRadio("1Xyo4u8uXC1ZmMpatF05PJ"); // The Weeknd
const 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");
}