---
title: "AudD for radio broadcasters"
description: "How radio stations and broadcasters use AudD to log airplay 24/7, build compliance reports, drive now-playing displays, and verify music-versus-ad separation."
slug: "/resources/for/radio-broadcasters"
section: "for"
keywords: [audd, radio, airplay logging, broadcast monitoring, now playing, music recognition api]
---

# AudD for radio broadcasters

If you run one station or a fleet of them, you need to know what aired and
when — for reporting, for a now-playing display, and for your own records.
AudD is a music-recognition HTTP API that listens to a live stream
continuously, fingerprints the audio against a 160-million-song database, and
tells you each track it recognizes as it plays. That one feed drives all four
jobs on this page: airplay logging, compliance reporting, a now-playing
display, and music-versus-ad verification.

## What you can do

### Log airplay across many stations, 24/7

You want a running log of every song that airs on every station, around the
clock, without a person watching a player. AudD's streams API does this by
ingesting each station's live audio server-side and reporting what it
recognizes.

- Register each station once with `addStream`, giving it a stable integer
  `radio_id` that maps to your own station registry. AudD then monitors that
  stream continuously — you run the receiver, not a per-station poller.
- Point a stream at a direct stream URL (HLS, Icecast, `m3u`/`m3u8`) or at a
  shortcut for `twitch:<channel>`, `youtube:<video_id>`, or
  `youtube-ch:<channel_id>`.
- Receive every recognized song on a single account-wide callback URL set with
  `setCallbackUrl`. One handler ingests matches from all stations; the
  callback's `radio_id` tells you which station played the track.
- Manage the fleet with `getStreams` (the source of truth for what you're
  monitoring), `setStreamUrl` to re-point a station whose URL changed, and
  `deleteStream` to drop one.

> **The `test` token does not work on streams.** The public `test` token is
> limited to the standard endpoint, 10 requests/day. Streams need your own
> token from the dashboard.

### Produce compliance and reporting data — what aired and when

Reporting bodies and licensing arrangements want a record of what played and
for how long. The default streams callback fires *after* a song finishes and
carries the total play length, which is exactly the shape airplay reporting
needs.

- Keep the default callback timing (do **not** set `callbacks=before`) so each
  callback includes `play_length` — seconds the track actually aired.
- Store one row per recognized play: `radio_id`, the callback `timestamp`,
  `artist`, `title`, `album`, `label`, `song_link`, and `play_length`. From
  that raw log you can aggregate spins per track, per station, per day with a
  `GROUP BY`.
- Read `isrc` and `upc` off each result when your account is on a Startup plan
  or higher — the identifiers that downstream reporting systems key on. Other
  fields AudD returns that the SDK does not surface as typed properties are
  available on each result's `extras` map.
- Make redelivery idempotent. If your endpoint returns non-200, AudD queues the
  callback and replays it later; an upsert on a unique key keeps a replay from
  double-counting a play.

### Drive a now-playing display for a website or app

You want to show listeners the song that is on air right now, on your site, in
an app, or on a stream overlay. For a live display you want the match the
moment a song starts, not after it ends.

- Set `callbacks="before"` so AudD delivers the recognition at song start.
- Consume matches by hosting a callback URL, or — when you can't host a public
  receiver (a browser, a laptop behind NAT) — by longpolling `GET /longpoll/`.
  Longpoll is an alternative way to read the same stream, not a separate
  feature; see the concept link below.
- Render artist, title, album, and the universal `song_link` (a `lis.tn` URL)
  in a small widget you embed on a page or drop into a browser source.

### Verify music-versus-ad separation

You want to confirm that music segments and non-music segments (ads, talk,
station IDs) are landing where they should. AudD distinguishes a recognized
song from "nothing recognizable" cleanly, which you can use as a music/non-music
signal.

- During spoken or non-music audio, the stream produces no song match —
  there's no track to fingerprint. A stretch of callbacks with no recognized
  music lines up with an ad break or a talk segment.
- Stream notifications are your health and content signal. Notification code
  `650` means AudD can't connect to the stream URL; `651` means the stream is
  white noise / silence only. Track which `radio_id`s raise these to catch a
  dead feed or a station that's gone quiet.
- For an after-the-fact pass over a recorded broadcast hour rather than a live
  stream, send the file to the enterprise endpoint, which chunks it
  server-side and returns each recognized song with its position in the file.

## Where to start

- **[Monitor radio airplay for your music catalog](/resources/recipes/radio-airplay-monitor)** —
  the end-to-end recipe: register many stations with `addStream`, receive every
  play on one callback handler, store it, and aggregate into a spins-per-track
  chart. Start here for logging and reporting.
- **[Build a now-playing widget for a livestream](/resources/recipes/now-playing-widget)** —
  the live-display path: `callbacks=before`, a callback receiver or longpoll,
  and a copy-paste HTML overlay.
- **[Callbacks vs. longpoll](/resources/concepts/callback-vs-longpoll)** —
  how to decide between hosting a callback URL and longpolling the same stream,
  depending on whether you can expose a public endpoint.
- **[Standard, enterprise, or streams: how to choose](/resources/concepts/standard-vs-enterprise-vs-streams)** —
  the decision rule for live monitoring (streams) versus a pass over a recorded
  broadcast file (enterprise).

## Code teaser

Register the account callback once, then add a stream per station. Every
recognized song from every station arrives at the one callback URL, tagged with
the `radio_id` you assigned.

```python
from audd import AudD

audd = AudD()  # reads AUDD_API_TOKEN; get a token at dashboard.audd.io

# Set the account-wide callback URL once, before adding stations.
audd.streams.set_callback_url("https://your-app.example.com/audd-callback")

# One stream per station; radio_id maps to your own station registry.
STATIONS = {
    101: "https://npr-ice.streamguys1.com/live.mp3",
    102: "https://ice1.somafm.com/groovesalad-128-mp3",
}
for radio_id, url in STATIONS.items():
    audd.streams.add(url=url, radio_id=radio_id)
    # default callbacks: AudD POSTs AFTER each song, with play_length
```

A "song finished" callback (the reporting default) carries the play length and
the station it came from:

```json
{
  "status": "success",
  "result": {
    "radio_id": 101,
    "timestamp": "2020-04-13 10:31:43",
    "play_length": 111,
    "results": [
      {
        "artist": "Alan Walker, A$AP Rocky",
        "title": "Live Fast (PUBGM)",
        "album": "Live Fast (PUBGM)",
        "label": "MER Recordings",
        "song_link": "https://lis.tn/LiveFastPUBGM"
      }
    ]
  }
}
```

`radio_id` is your station handle, `timestamp` is when the play was recognized,
`play_length` is the seconds the track aired, and `results[0]` is the
recognized track. Read `isrc`/`upc` off the result's `extras` map on Startup
plan or higher.

---

**Related**

- [Monitor radio airplay for your music catalog](/resources/recipes/radio-airplay-monitor)
- [Build a now-playing widget for a livestream](/resources/recipes/now-playing-widget)
- [Callbacks vs. longpoll](/resources/concepts/callback-vs-longpoll)
- [Standard, enterprise, or streams: how to choose](/resources/concepts/standard-vs-enterprise-vs-streams)
- [SDK docs](https://docs.audd.io/sdks)
- [API reference](https://docs.audd.io)