How to identify songs in audio files with the AudD API
Send an audio file or URL to AudD, parse the response, and handle no-match and error cases — a complete song-identification walkthrough with the Python SDK.
You’ve got an audio file sitting there — maybe a recorded radio segment, something a user uploaded, or a stream capture from your app. You need to know what’s playing: artist, title, label, all of it. Building your own audio fingerprinting engine isn’t happening. You want to send a file and get an answer.
The AudD API does exactly that. This guide covers the whole path: getting a token, sending audio files, parsing responses, and handling the edge cases. When you’re done you’ll have a working integration ready for any application.
What you get back from AudD
Send an audio file or URL to AudD and it runs neural-network audio fingerprinting against a database of 160 million songs. On a match you get structured metadata:
- Artist and title
- Album name
- Label
- Release date
- A universal song link plus optional Apple Music and Spotify blocks
No match? The SDK returns None (the API sends result: null). That’s a
successful response that simply found nothing — distinct from an error, and easy
to handle.
Getting API access
Get an API token at dashboard.audd.io. The free tier is plenty for testing — get your integration running before committing to a paid plan. Keep the token server-side; every request needs it.
Install the Python SDK:
pip install audd
Three ways to send audio
AudD accepts audio in three forms:
- Local file — a filesystem path or raw bytes
- URL — pointing to publicly accessible audio
- Live stream — for continuous real-time monitoring (see streams)
Most file-based projects use the first two.
Identifying songs from local files
The SDK’s recognize takes a path, a URL, raw bytes, or a file object and
returns the top match — or None on a successful call that matched nothing.
from audd import AudD
audd = AudD("test") # get your own token at dashboard.audd.io
song = audd.recognize("sample_clip.mp3", return_metadata=["apple_music", "spotify"])
if song:
print(f"{song.artist} — {song.title}")
else:
print("no match")
The return_metadata argument is optional but useful — requesting
apple_music and spotify populates those provider blocks in the response.
Perfect if you’re building a UI that links to tracks. Each provider you request
adds a little latency, so ask only for the ones you render.
What the response looks like
Under the hood, a successful match looks like this:
{
"status": "success",
"result": {
"artist": "Imagine Dragons",
"title": "Warriors",
"album": "Smoke + Mirrors (Deluxe)",
"release_date": "2015-02-17",
"label": "KIDinaKORNER/Interscope Records",
"timecode": "00:31",
"song_link": "https://lis.tn/Warriors",
"apple_music": { "url": "https://music.apple.com/…", "…": "…" },
"spotify": { "external_urls": { "spotify": "https://open.spotify.com/…" }, "…": "…" }
}
}
A no-match returns status: "success" with result: null. That status: success only means the request processed without errors — not that a song was
found. The SDK collapses this for you: recognize returns the result object on
a match and None otherwise, so you branch on the return value rather than
poking at status by hand.
Identifying songs from URLs
Got audio hosted somewhere public? Skip the upload and pass the URL — same method, same return value.
song = audd.recognize(
"https://audd.tech/example.mp3",
return_metadata=["apple_music", "spotify"],
)
if song:
print(f"{song.artist} — {song.title}")
Reading the fields
Prefer the SDK’s typed properties and helpers over reaching into provider blocks by hand:
if song:
artist = song.artist
title = song.title
album = song.album
label = song.label
spotify_url = song.streaming_url("spotify")
apple_music_url = song.streaming_url("apple_music")
universal_link = song.song_link # always present on a match
song.song_link is always present on a match — a universal lis.tn URL that
redirects to the song on whatever service the user has. Use it as the fallback
when a specific provider link is missing. Every field is nullable: a
custom-catalog match, for instance, may have a None artist and title. Guard
accordingly. For any field outside the typed surface, read it from
song.model_extra.
Handling errors
The SDK raises typed exceptions when the server returns an error, so you can branch on the cause instead of parsing error codes:
from audd import AudD
from audd.exceptions import (
AudDAuthenticationError,
AudDQuotaError,
AudDInvalidAudioError,
AudDAPIError,
AudDConnectionError,
)
audd = AudD("test")
try:
song = audd.recognize("clip.mp3", return_metadata=["apple_music", "spotify"])
if song is None:
print("no match — try a different clip")
else:
print(f"{song.artist} — {song.title}")
except AudDAuthenticationError:
print("bad or missing token — check the dashboard")
except AudDQuotaError:
print("out of requests — top up at dashboard.audd.io")
except AudDInvalidAudioError:
print("the audio couldn't be decoded (too short or corrupted)")
except AudDConnectionError:
print("transient network issue — the SDK already retried")
except AudDAPIError as err:
print(f"AudD #{err.error_code}: {err.server_message}")
Keep the three outcomes separate:
- No match —
recognizereturnsNone. Not an error. Render “try again.” - Server-returned errors — bad token, exhausted quota, undecodable audio. These raise typed exceptions, as above.
- Quota during testing — the
testtoken is capped at 10 requests/day on the standard endpoint. If recognition suddenly starts failing with a quota error in development, you’ve hit that cap; switch to a real dashboard token.
The SDK retries transient connection failures before your bytes reach the server, but never repeats a recognition call after the upload completes — re-sending would risk double-billing.
Audio length and quality tips
The standard endpoint is tuned for a short audio clip — a handful of seconds of reasonably clean audio matches reliably. The fingerprinting handles real-world conditions: background noise, low bitrates, slight distortion. Heavily clipped or distorted audio will hurt accuracy.
Working with a longer recording? You don’t need the whole file for the standard endpoint — a short clip from where the music plays is plenty, and it keeps you well under the 10 MB upload cap. To get every song across a long file, use the enterprise endpoint instead (next section).
Supported audio formats
AudD handles the formats you’ll actually encounter: MP3, WAV, FLAC, M4A, OGG,
AAC, WMA, and AIFF. Working with an uncommon format? Convert to MP3 or WAV first
— ffmpeg is the standard tool and drops into any pipeline.
Beyond single files
Once basic file identification works, the same SDK covers more:
-
Long files and full tracklists. The standard endpoint returns one match. To identify every song across a long recording — a DJ set, a podcast, a broadcast — use the enterprise endpoint (
recognize_enterprise). It chunks the file server-side, bills per 12 seconds of audio, and returns one match per recognized segment with timestamps. Always setlimitduring development to cap metered chunks.matches = audd.recognize_enterprise("long_recording.mp3", limit=10) for m in matches: print(m.timecode, m.artist, "—", m.title) -
Radio and stream monitoring. AudD’s streams surface runs continuous, real-time recognition against live stream URLs, returning timestamped song data as tracks change — the basis for airplay monitoring and broadcast compliance.
-
Content moderation. Song identification in an upload pipeline can flag user content containing copyrighted music; the label and artist data is enough for basic rights awareness.
-
Match your own tracks. Upload private recordings to a custom catalog and later
recognizecalls match against them too, returning the integeraudio_idyou assigned. Custom-catalog access is gated — email [email protected].
Wrapping up
AudD gives you a clean interface: send audio, get metadata — the
fingerprinting, catalog, and matching are AudD’s problem. The same recognize
call you wrote here is the one you’ll use for uploads, broadcasts, and
backlogs.
Related
Reading this as an AI agent? The raw Markdown is at articles/identify-songs-in-audio-files.md, and the full index is /resources/llms.txt.
