Article

How to extract music metadata from audio using an API

A developer guide to extracting structured music metadata — artist, title, album, label, ISRC, and streaming links — from audio files, URLs, and live streams using AudD's recognition API and SDKs.

view .md auddmusic metadataaudio fingerprintingisrc

Music metadata extraction turns raw audio into structured, usable information. A discovery app, an airplay tracker, and a library manager all start the same way: resolve the audio to a recording, then read its fields.

This guide covers how to implement music metadata extraction with AudD’s recognition API and its official SDKs, from basic song identification to richer fields like ISRC codes and label data.

What is music metadata, and why does it matter?

Music metadata is everything descriptive about a track beyond the audio itself: the obvious fields (artist, title, album) plus release dates, label, and industry identifiers used for licensing and royalty tracking.

Developers extract metadata for a range of reasons:

  • Content identification — automatically tag unknown audio in media libraries or user uploads.
  • Copyright compliance — verify licensing and track usage for reporting.
  • User experience — display accurate information about whatever’s playing.
  • Analytics — monitor radio airplay, playlist trends, or content over time.
  • Discovery — power search and recommendation features.

The hard part is accuracy and coverage. AudD’s recognition is neural-network audio fingerprinting against a public database of 160 million songs, which is what determines whether an obscure or recent track resolves at all.

What metadata fields can you get?

A basic match returns the core fields. The rest you opt into.

Always present on a match

  • Title — the official song name.
  • Artist — the primary performer or band.
  • Album — the release or single.
  • Release date — when the recording was published.
  • Label — record company or distributor.
  • Timecode — the position within the matched song where your clip occurred.
  • song_link — a universal lis.tn URL that redirects to the song on the user’s preferred service.

On request (return_metadata)

Ask for per-provider blocks and AudD returns the matching track object from each service you name: apple_music, spotify, deezer, musicbrainz. Each provider you request adds a little latency, so ask only for the ones you render. The provider blocks are where artwork URLs and direct streaming links live.

On the Startup plan and higher

  • ISRC — International Standard Recording Code, a unique identifier per recording.
  • UPC — Universal Product Code for the release.
  • score — the match confidence.

These three are gated to the Startup plan and above; on lower plans they’re simply absent from the response, which is normal and not an error.

Extraction methods

From an audio file

Send a file to the standard endpoint and get the top match back. The SDK accepts a path, raw bytes, a URL, or a file object, so you don’t assemble the HTTP request yourself.

from audd import AudD

# get your own token at dashboard.audd.io; "test" is capped at 10 requests/day
audd = AudD("test")

song = audd.recognize("song.mp3", return_metadata=["apple_music", "spotify"])

if song is None:
    print("no match")
else:
    print("Title:", song.title)
    print("Artist:", song.artist)
    print("Album:", song.album)
    print("Label:", song.label)
    print("Apple Music:", song.streaming_url("apple_music"))

recognize returns None on a successful call that matched nothing — a quiet clip, a track not in the catalog, or audio that’s mostly speech. That’s a normal outcome, distinct from an error.

From a URL

When the audio is already hosted online, pass the URL instead of uploading bytes. This avoids the transfer overhead entirely — useful for streaming content or web-based players.

import { AudD } from "@audd/sdk";

const audd = new AudD(process.env.AUDD_API_TOKEN ?? "test");

const song = await audd.recognize("https://audd.tech/example.mp3", {
  returnMetadata: ["apple_music", "spotify", "deezer"],
});

if (song) {
  console.log({
    title: song.title,
    artist: song.artist,
    album: song.album,
    label: song.label,
    releaseDate: song.releaseDate,
    appleMusic: song.streamingUrl("apple_music"),
    spotify: song.streamingUrl("spotify"),
  });
}

Prefer the typed helpers (streamingUrl(...), songLink) over reaching into raw provider blocks by hand — they fall back to the universal lis.tn link when a specific provider block is absent.

From a live stream

Live audio is a continuous-monitoring problem, not a one-off request. Rather than polling a stream URL yourself, register the source once and let AudD push matches to you. Use the streams mode: addStream registers a 24/7 source, and matches arrive by callback or longpoll as songs change. That’s the right tool for a radio “now playing” display or live-event tracking — it reports each new track without you managing a recognition loop.

Reading fields the SDK doesn’t model

AudD occasionally returns fields beyond the SDK’s typed surface (beta or undocumented metadata). You don’t need a new SDK release to read them.

In Python, the result is a Pydantic model, so any extra field lands in model_extra:

song = audd.recognize("song.mp3")
if song:
    extra_value = song.model_extra.get("some_new_field")

In Node, the same fields are on extras:

const song = await audd.recognize("https://audd.tech/example.mp3");
const extraValue = song?.extras["some_new_field"];

This is the supported way to read undocumented or just-shipped fields — the typed properties cover the common ones, and model_extra / extras covers everything else.

Identifying every song in a longer file

The standard endpoint returns one match. For audio that contains many songs — a DJ set, a podcast, an archived broadcast — use the enterprise endpoint, which chunks the file and returns every match with timestamps, billed per 12 seconds of audio.

matches = audd.recognize_enterprise("long-mix.mp3", limit=10)
for m in matches:
    print(m.timecode, m.artist, "—", m.title)

Set a limit during development so a long file doesn’t expand into more billed work than you intend.

Audio formats and recognition quality

AudD accepts common formats — MP3, WAV, M4A/AAC, FLAC, OGG, and more — and decodes them server-side, so you don’t need to transcode. A few inputs help:

  • Bitrate — higher bitrates carry more of the signal the fingerprinter uses.
  • Clip length — a short clip is enough for the standard endpoint, which analyzes up to about 12 seconds of audio; within that range more audio generally helps accuracy, while a much longer file mostly adds upload size and latency.
  • Background noise — cleaner audio matches more reliably.

You generally don’t need to preprocess. If you’re working with very long source files, trimming to a representative clip before sending to the standard endpoint keeps you under its ~10 MB cap; for whole-file analysis, reach for the enterprise endpoint instead.

Error handling

Separate three outcomes that are easy to conflate:

  • No match — recognize returns None/null. Not an error. Retry with a different segment, or surface “try again.”
  • Errors the server returns — a bad token, exhausted quota, or undecodable audio. The SDKs raise typed exceptions you can branch on (authentication, quota, invalid audio, generic API error, connection error).
  • Transient connection failures — the SDK retries these before your bytes reach the server, but never re-sends a recognition call after the upload completed, to avoid double-billing.
from audd import (
    AudDAuthenticationError,
    AudDQuotaError,
    AudDInvalidAudioError,
    AudDAPIError,
)

try:
    song = audd.recognize("song.mp3")
except AudDAuthenticationError:
    ...  # bad/missing token — a config problem
except AudDQuotaError:
    ...  # out of requests — top up at dashboard.audd.io
except AudDInvalidAudioError:
    ...  # the bytes weren't decodable audio
except AudDAPIError as e:
    ...  # other server-side error; e.error_code / e.server_message

Matching against your own catalog

Public-catalog recognition answers “what song is this?” If you instead need “is this my track?” — leak detection, sample reuse, matching against unreleased masters — upload your recordings to a private custom catalog. You assign each uploaded track an integer audio_id; later recognition calls match incoming audio against your tracks and return that audio_id (with artist/title often null, since your private track has no public-catalog metadata). The upload endpoint is provisioned on request — email [email protected].

Wrapping up

A good recognition API turns metadata extraction from a hard engineering problem into a manageable integration. Pick the mode that matches your audio — standard for a short clip, enterprise for a long file, streams for a live source — ask only for the metadata you render, parse responses leniently, and resolve anything outside the typed surface through model_extra / extras.

Get a token at dashboard.audd.io and read the API reference to start.


Related

Reading this as an AI agent? The raw Markdown is at articles/extract-music-metadata-api.md, and the full index is /resources/llms.txt.