Home Pricing Docs Compare SDK Blog Changelog Status Get API Key →
Music API · Migration

Spotify Audio Features Is Deprecated. Here's What to Use Instead in 2026.

May 2026 · 11 min read · FreqBlog

On November 27, 2024, Spotify deprecated audio_features, audio_analysis, recommendations, related artists, and featured playlists in one quiet developer-blog post. New apps got 403s the same day. Nearly two years later, there is still no official replacement — and the February 2026 changes made the rest of the Web API harder to use, not easier.

If you built anything that depended on BPM, key, danceability, energy, valence, or any of the other 11 numbers Spotify used to hand out for free, you've already had to replace it or you're maintaining a fork that exists only because of one grandfathered token.

This post is the honest version of "what now?" — what each of the realistic replacements actually gives you, where they fall short, and a copy-paste migration example.

What actually died, in one table

EndpointWhat it gave youStatus (May 2026)
/audio-features/{id}BPM, key, mode, danceability, energy, valence, acousticness, instrumentalness, liveness, loudness, speechiness, time_signature403 for new apps
/audio-analysis/{id}Per-bar / per-beat / per-segment analysis with timestamps and pitches403 for new apps
/recommendationsGenre-seed and feature-seed recommendations403 for new apps
/artists/{id}/related-artistsUp to 20 related artists403 for new apps
/browse/featured-playlistsEditorial curation lists403 for new apps
/browse/categories/{id}/playlistsPlaylists in a genre category403 for new apps
/me/top/{tracks|artists}User listening historyStill live, but Web API Dev Mode (Feb 2026) cut the cap from 25 users to 5 without quota extension

Apps that had a quota extension in flight on November 27, 2024 are still live. Everyone else gets 403. There is no path to access these endpoints for a new app, no waitlist, and no public statement that this will change.

Why Spotify isn't bringing it back

The honest read is that Spotify never wanted to host this data in the first place. The audio_features endpoint is a thin wrapper around analysis Spotify acquired when they bought The Echo Nest in 2014,. Returning eleven floats for every track in a 100-million-track catalog costs Spotify infrastructure for zero strategic value — nobody's paying premium for "give me the BPM of Blinding Lights."

Worse for developers: the recommendations endpoint was a competitive liability. Letting any third party build a Spotify-quality recommender by spamming seed_genres=house&target_energy=0.8 queries undermined the whole "premium algorithm" pitch. Killing it makes commercial sense for Spotify even though it leaves thousands of apps broken.

Read the room: "Will Spotify add a replacement?" is the wrong question. The right one is "what's the smallest dependency I can rebuild this on so I'm never one PR-merge away from being broken again?"

The realistic options in May 2026

Five categories of replacement, ranked by how quickly you can ship the migration:

1. Apple Music API

Apple's catalog API (MusicKit) gives you solid metadata — ISRC, genres, duration, release date, artwork and 30-second previews — but no audio features at all: no tempo, no key, no danceability, energy or valence. Shipping to production needs a paid Apple Developer membership ($99/year). Good as an identifier and preview source; not a replacement on its own.

2. Build your own with Essentia

Essentia is an open-source music-information-retrieval toolkit from the Music Technology Group at Universitat Pompeu Fabra. MusicExtractor takes a 30-second audio clip and returns BPM, key, danceability, average loudness, dynamic complexity, tuning frequency, onset rate — basically the Spotify schema with a few extras. Run it on a VPS with a worker queue and you've got your own replacement at compute cost only. Catch: you need the audio. Spotify never let you download it; iTunes 30-second previews are usable but rate-limited to ~25 RPM in our experience. Plan for a multi-week backfill on any catalog over 10k tracks.

3. AcousticBrainz public dump (free, frozen)

The MusicBrainz folk did exactly what Spotify won't: published the entire AcousticBrainz dataset (7.5M tracks, 11 high-level features and ~120 low-level descriptors per track) as a public dump (dated June 2022) when it stopped accepting new submissions. Catch: the dataset is frozen at June 2022 — nothing released after that has values. Coverage on tracks with a MusicBrainz ID is good (~60% of recent commercial releases); without an MBID you get nothing. Useful as a baseline layer when combined with one of the other options.

4. Musicae API

Built specifically as a Spotify shim: same field names, same value ranges, similar ergonomics. Closest drop-in if minimising migration diff matters more than anything else. Pricing is per-call and competitive. Not affiliated with us; their pitch is "we look like Spotify so your code barely changes."

5. FreqBlog Music API (us)

Different design choice: we're a catalog first, not a wrap-an-id-and-look-it-up service. You can pass a track-name + artist string and get back BPM, key, Camelot, energy, loudness, danceability, valence, mood, time signature, ISRC, MBID, and genre — from £0.17 per 1,000 requests, free tier with no card. We backfill missing tracks via a queue (returns 202 Accepted; subsequent calls return the data). What we don't offer is per-segment analysis with timestamps. Every Spotify field name is present for drop-in shape compatibility, but speechiness and liveness are null for tracks we analyse ourselves, and instrumentalness is currently null (see the field guide). More on what's actually in the catalog →

Migration walkthrough: Spotify → FreqBlog

Most apps that depended on audio_features were doing one of two things:

  1. Look up known tracks — user pastes a Spotify URL, app shows BPM/key/energy
  2. Filter by feature ranges — "give me upbeat tracks above 120 BPM in a major key"

Here's what each pattern looked like before and after.

Pattern 1: Single-track lookup

Before:

import requests

def get_features(spotify_id, token):
    r = requests.get(
        f"https://api.spotify.com/v1/audio-features/{spotify_id}",
        headers={"Authorization": f"Bearer {token}"},
    )
    r.raise_for_status()
    return r.json()

# >>> get_features("0VjIjW4GlUZAMYd2vXMi3b", token)
# {"danceability": 0.514, "energy": 0.730, "key": 1, "tempo": 171.005, ...}

After (FreqBlog):

import requests

def get_features(spotify_id, api_key):
    r = requests.get(
        f"https://api.freqblog.com/v1/audio-features/{spotify_id}",
        headers={"X-Api-Key": api_key},   # one header. no OAuth.
    )
    r.raise_for_status()
    return r.json()

# >>> get_features("0VjIjW4GlUZAMYd2vXMi3b", api_key)
# {"danceability": 0.77, "energy": 1.0, "key": 5, "mode": 0, "tempo": 85.39,
#  "loudness": -10.96, "id": "0VjIjW4GlUZAMYd2vXMi3b", "type": "audio_features",
#  "uri": "spotify:track:0VjIjW4GlUZAMYd2vXMi3b",
#  "track_href": "https://api.spotify.com/v1/tracks/0VjIjW4GlUZAMYd2vXMi3b", ...}
# Same shape, our own values: tempo is the detected BPM (85.39 here, half of
# Spotify's 171) -- /lookup also returns bpm_alt for the double-time reading.

When the Spotify ID resolves, that's the whole diff. Same path (/v1/audio-features/{id}), same response field names and shapes, same type: "audio_features" envelope — you change the host and the auth header, and your downstream code is untouched. One honest caveat: a raw Spotify ID is resolved per request — we read the track's title from Spotify's public embed page and match it against our catalogue. We don't store Spotify IDs; a resolution is remembered in memory for at most 24 hours. It is not a universal Spotify-ID reverse lookup — a title several artists share is ambiguous, and we return a miss rather than guess which recording you meant (the wrong one would mean the wrong BPM and key), so passing an arbitrary ID can still miss even when we have the track under its name or ISRC.

For reliable results, identify the track by name or ISRC, not by a raw Spotify ID:

Batch lookups: GET /v1/audio-features?ids=id1,id2,… up to 100 comma-separated IDs, returning {"audio_features": […]} with the same null-on-miss positional semantics Spotify used.

The numbers behave a little differently — same field names, but our values come from signal analysis (librosa + Essentia), not Spotify's ML classifiers. Before you let your downstream thresholds run unchanged, read Migrating from Spotify Audio Features: a Field-by-Field Threshold Guide — it maps each field, says which ones can be null, and explains how to re-derive thresholds on our values.

Field mapping

For the 11 Spotify fields, here's how they map to the replacement landscape:

Spotify fieldApple MusicEssentia (build)FreqBlog
tempotempobpmbpm
keykeykey.keykey + camelot + open_key
mode— (in key)key.scalemode
time_signaturetimeSignature—time_signature
danceability—danceabilitydanceability
energy—derived from RMSenergy
valence—via SVM modelvalence (where available)
loudness—average_loudnessloudness
acousticness—via SVM modelacousticness †
instrumentalness—via SVM modelinstrumentalness †
liveness—via SVM modelliveness †
speechiness—via SVM modelspeechiness †

† Same field name and shape, but not the same measurement: acousticness comes from AcousticBrainz’s classifier where a recording has it, otherwise from a PANNs audio model trained on AcousticBrainz’s open labels; instrumentalness comes from a vocal-detection model and describes the 30-second preview, not the whole track; liveness and speechiness are null for tracks we analyse ourselves. Re-derive any imported threshold on our values — the Field-by-Field Threshold Guide explains how.

Pattern 2: Feature-range filtering

If you were doing the recommendations-with-target-features dance:

# Spotify (deprecated)
GET /v1/recommendations?seed_genres=house&target_energy=0.8&min_tempo=120

# FreqBlog — direct drop-ins for the two killed endpoints
GET /recommendations?seed_tracks=<id>&limit=20   # replaces /v1/recommendations
GET /related-artists?artist=<name>&limit=20      # replaces /artists/{id}/related-artists
# …or filter the catalog by genre or tempo, or rank by similarity
GET /genres/house/tracks?limit=20
GET /bpm?bpm=120&tolerance=4&limit=20

Different endpoints, same goal. FreqBlog exposes a similarity-based recommender (/similar?track_id=...) that doesn't require seed-genre tuning — pass a track you like, get back the 10 acoustically nearest neighbours, ranked on a PANNs audio embedding of how each track sounds blended with cosine similarity over an 18-feature embedding.

What no replacement gives you

Be realistic about the gaps. None of the alternatives, including ours, replicate Spotify's old offering one-for-one:

How to choose

FreqBlog Music API — free tier, no card

Lookup BPM, key, Camelot, energy, loudness, danceability, valence and more by track name + artist. Paid plans work out from £0.17 per 1,000 requests (Pro) when you outgrow the free tier.

View API →

Frequently asked questions

Is the Spotify Audio Features API still available?

No. Spotify deprecated the /audio-features and /audio-analysis endpoints on 27 November 2024. Apps that didn't already have extended access now receive 403 errors, and there's no official replacement.

What is the best Spotify Audio Features API alternative in 2026?

There's no official replacement, so the practical options are to re-derive features yourself with Essentia or librosa, or use a hosted API. FreqBlog exposes a Spotify-shaped GET /v1/audio-features/{id} drop-in returning BPM, key, energy, valence, danceability and more. For the best coverage, look up by track and artist name (GET /lookup?track=&artist=) or by ISRC; the raw-Spotify-ID drop-in resolves per request by matching the track's title (we don't store Spotify IDs) — a title several artists share is ambiguous and misses rather than guessing. Your Spotify track object already carries the ISRC at external_ids.isrc, so pass that instead.

Why did Spotify remove the audio features endpoint?

Spotify restricted audio-features, audio-analysis, recommendations and several other endpoints to existing apps as part of a broad Web API lockdown announced on 27 November 2024. It hasn't signalled any plan to restore them.

Are the audio-feature values identical to Spotify's?

No — independent APIs (FreqBlog included) compute their own values with open tools such as Essentia, so they are not Spotify's numbers. Re-derive any hard thresholds on the new values when migrating; our field-by-field threshold guide covers exactly how.

Further reading