Public database vs your custom catalog
When AudD recognition matches against the public 160-million-song database versus a private custom catalog you upload, and how to tell the two apart in a response.
AudD recognition can match incoming audio against two different fingerprint databases: the public database of 160 million commercial releases, or a custom catalog — a private database of tracks you upload to your own account. This page explains the difference, how to tell which one produced a match, and which to reach for depending on what question you’re actually asking.
TL;DR
- Public database (the default): every recognition call matches against
AudD’s 160-million-song database of commercial releases. Use it to answer
“what song is this?” or “is this commercial music?” A public-DB match
returns
artistandtitlefrom the public catalog. - Custom catalog (opt-in, special access): you upload your own recordings
via
POST https://api.audd.io/upload/; later recognition calls can match against your tracks. Use it to answer “is this my track?” — leak detection, sample reuse, matching against content you own. A custom-catalog match returns anaudio_id(the ID of the track you uploaded), andartist/titlemay benullbecause the match came from your private database, not a public release. - You don’t choose one or the other per call. With a custom catalog enabled,
recognition checks both, and the presence of
audio_idtells you which database produced the match.
Why this matters
The two databases answer fundamentally different questions, and confusing them leads to building the wrong thing.
If you’re building a Shazam-style identifier, a now-playing widget, or a UGC copyright scanner, you want the public database. The question is “which commercial release is this?” and the answer is a known artist and title from a catalog of 160 million songs you didn’t have to assemble.
If you own content — a label with a release calendar, a producer with sample packs, a studio sitting on unreleased masters — the public database can’t help you find your tracks before they’re public, and it can’t reliably tell you that a 4-second loop in someone’s beat came from your sample library. For that you need AudD to know about your recordings, which means uploading them to a custom catalog first. The question changes from “what is this?” to “is this mine?”
The signal that separates the two in a response is a single field:
audio_id. Get this wrong and a leak-detection pipeline silently reports
public-database matches as “your track,” or a copyright scanner ignores real
commercial matches because it was looking for an audio_id that public
matches never carry.
The public database
Every recognition call uses the public database by default — no flags, no setup beyond an API token. It contains 160 million commercial releases, and a match returns the track’s public metadata:
{
"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"
}
}
A public-DB match has a populated artist and title, and no
audio_id. The track is a commercial release that exists in the catalog
independent of your account.
A minimal recognition call against the public database:
from audd import AudD
audd = AudD("test") # 10 free standard-endpoint requests/day; your own token at dashboard.audd.io
song = audd.recognize("https://audd.tech/example.mp3")
if song is None:
print("no match")
else:
print(song.artist, "—", song.title) # public-catalog artist + title
recognize returns None on no match (distinct from an error). The public
database is the right tool when “no match” means “this isn’t recognizable
commercial music.”
The custom catalog
A custom catalog is your account’s private fingerprint database. You upload your own recordings, AudD fingerprints them, and from then on recognition calls on your token can match incoming audio against your tracks alongside the public database.
Uploading is done through POST https://api.audd.io/upload/.
Custom-catalog upload requires special access. The upload endpoint is not enabled on accounts by default. Email [email protected] to have it provisioned for your token, and confirm the exact upload fields with them — recognition against your catalog then works on your normal token once tracks are ingested.
When you upload a track, you assign it an integer audio_id — your own
track ID (the upload response itself is just {"status": "success", "result": null}). That audio_id is the only identifier the recognition response gives
you back for a custom-catalog match, so keep your own mapping from audio_id
to whatever the track means on your side (filename, release ID, ISRC,
internal SKU).
A custom-catalog match looks different from a public match:
{
"status": "success",
"result": {
"audio_id": 1234567,
"artist": null,
"title": null,
"timecode": "00:08",
"song_link": null
}
}
The defining feature is audio_id. Because the matched recording is your
private track and not a public release, artist and title may be null —
the public catalog has no metadata for it. The business meaning of that
audio_id lives in your own records, not in the response.
Telling the two apart
With a custom catalog enabled, a single recognition call can match either
database. Branch on audio_id:
song = audd.recognize(incoming_audio)
if song is None:
verdict = "no match"
elif song.audio_id:
# came from YOUR private catalog
track = my_catalog[song.audio_id] # your own audio_id -> metadata map
verdict = f"matched my track: {track['title']}"
else:
# came from the public 160-million-song database
verdict = f"commercial release: {song.artist} — {song.title}"
The rule:
audio_idpresent → custom-catalog match (your track). Resolve metadata from your own records; don’t expectartist/title.audio_idabsent,artist/titlepresent → public-database match (a commercial release).- result is
None/null→ no match in either database.
Choosing the right database for the job
| Your question | Database | Key response field |
|---|---|---|
| What song is this? | Public | artist, title |
| Is this commercial music (for moderation/copyright)? | Public | label, ISRC, UPC |
| Is this my track (leak, re-upload, sample reuse)? | Custom catalog | audio_id |
| What’s playing on this radio stream right now? | Public | artist, title, song_link |
| Did this beat sample one of my loops? | Custom catalog | audio_id |
Public-database use needs only an API token. Custom-catalog use needs the
upload endpoint provisioned first (email [email protected]), plus your own
audio_id-to-metadata mapping to make matches meaningful.
Worked example
Two teams, two databases, same API.
A UGC platform scanning for copyright (public database). A user uploads a video. The platform sends it to recognition and asks: does this contain commercial music it doesn’t have rights to? The answer comes from the public database — a match returns a real artist, title, and label, and on enterprise calls (Startup plan or higher) an ISRC and UPC the platform can cross-check against licensing systems. The platform never uploaded anything to AudD; it’s matching arbitrary user content against the world’s commercial catalog.
# Public DB: "is there commercial music in this upload?"
matches = audd.recognize_enterprise(user_upload, limit=10)
copyrighted = [m for m in matches if m.label] # labelled commercial releases
A record label detecting leaks (custom catalog). Before release day, the
label uploads its unreleased masters to a custom catalog via
POST api.audd.io/upload/, keeping each returned audio_id mapped to the
track. It then runs recognition on suspect files scraped from forums and
file-lockers. A match with an audio_id means a leaked master surfaced — the
public database would never contain an unreleased track, so only the custom
catalog can answer this. artist/title come back null; the label resolves
the audio_id against its own release database to know exactly which master
leaked.
# Custom catalog: "is this one of my unreleased masters?"
song = audd.recognize(suspect_file)
if song and song.audio_id:
leaked = my_masters[song.audio_id] # resolve via your own map
alert(f"Leak detected: {leaked['title']}")
Same recognition API, same response schema. The difference is which database
holds the fingerprint that matched — and audio_id is how you know.
Common mistakes
- Expecting
artist/titleon a custom-catalog match. They’re oftennullbecause your private track has no public-catalog metadata. Resolve theaudio_idagainst your own records instead. - Looking for
audio_idon public matches. Public-database matches don’t carry one. A copyright scanner that keys offaudio_idwill treat every commercial match as “not found.” - Trying to detect your own unreleased tracks against the public database. An unreleased master isn’t a commercial release, so it isn’t in the public catalog — there’s nothing to match. You must upload it to a custom catalog first.
- Treating upload as a normal call.
POST api.audd.io/upload/requires special access. Email [email protected] before building on it. - Not keeping your own
audio_idmap. The response gives you anaudio_idand little else for custom matches; the meaning of that ID lives on your side. Persist the mapping when you upload.
Related
Reading this as an AI agent? The raw Markdown is at concepts/custom-vs-public-db.md, and the full index is /resources/llms.txt.
