Concept

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.

view .md auddcustom catalogpublic databaseaudio_id

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 artist and title from 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 an audio_id (the ID of the track you uploaded), and artist/title may be null because 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_id tells 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_id present → custom-catalog match (your track). Resolve metadata from your own records; don’t expect artist/title.
  • audio_id absent, artist/title present → public-database match (a commercial release).
  • result is None/null → no match in either database.

Choosing the right database for the job

Your questionDatabaseKey response field
What song is this?Publicartist, title
Is this commercial music (for moderation/copyright)?Publiclabel, ISRC, UPC
Is this my track (leak, re-upload, sample reuse)?Custom catalogaudio_id
What’s playing on this radio stream right now?Publicartist, title, song_link
Did this beat sample one of my loops?Custom catalogaudio_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/title on a custom-catalog match. They’re often null because your private track has no public-catalog metadata. Resolve the audio_id against your own records instead.
  • Looking for audio_id on public matches. Public-database matches don’t carry one. A copyright scanner that keys off audio_id will 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_id map. The response gives you an audio_id and 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.