What is ICY2?

ICY2 (ICY-META version 2.x) is an extended metadata protocol layered on top of the legacy SHOUTcast/Icecast ICY 1.x headers. It adds structured, typed metadata fields covering:

Key principle: ICY2 is purely additive. All ICY 1.x legacy headers (icy-name, icy-genre, icy-url, icy-pub, icy-br, icy-metaint) are preserved unchanged. A server that does not understand ICY2 simply ignores the extra headers.

Protocol Detection

The server detects ICY2 clients by the presence of:

icy-metadata-version: 2.2

Version matching uses prefix 2. so both 2.1 and 2.2 are accepted. If the header is absent the server falls back to ICY 1.x parsing.

Source Client Handshake

A source encoder (OBS, Mixxx, ffmpeg, custom) authenticates via HTTP PUT and sends ICY2 headers in the request:

PUT /live.mp3 HTTP/1.1
Host: stream.example.com:9443
Authorization: Basic c291cmNlOnBhc3N3b3Jk
Content-Type: audio/mpeg
icy-metadata-version: 2.2
icy-name: My Radio Station
icy-genre: Electronic / House
icy-url: https://myradio.example.com
icy-br: 128
icy-pub: 1
icy-dj-handle: @djname
icy-show-title: Saturday Night Live
icy-station-id: myradio-001
icy-social-twitter: @myradio
icy-hashtags: #electronic #live

Live Metadata Push (StreamTitle Updates)

After the source connection is established, the encoder may inject in-stream ICY metadata updates (the classic SHOUTcast StreamTitle mechanism). Mcaster1DNAS v2.5.1+ adds support for ICY2-extended fields in these in-band updates:

StreamTitle='Artist - Title';
StreamUrl='https://...';

For ICY2 you may also use the /admin/metadata HTTP endpoint to push updates without interrupting the audio stream:

# Update "now playing" on a live mount
curl -sk -u admin:changeme \
  "https://localhost:9443/admin/metadata?mount=/live.mp3&mode=updinfo&song=Artist+-+Track+Title"

# Push ICY2 extended metadata
curl -sk -u admin:changeme \
  "https://localhost:9443/admin/metadata" \
  -d "mount=/live.mp3&mode=updinfo&song=Artist - Title&icy-dj-handle=@djname&icy-show-title=Saturday%20Night"

Static Mount Metadata Push

For podcast, socialcast, and on-demand mounts (see Static Mounts) the server manages metadata independently from a live encoder. Push updates via:

# Update metadata on a podcast mount
curl -sk -u admin:changeme \
  "https://localhost:9443/admin/metadata?mount=/podcast&mode=updinfo" \
  --data-urlencode "song=Episode 42 - Understanding ICY2" \
  --data-urlencode "icy-podcast-host=The Host Name" \
  --data-urlencode "icy-podcast-episode=42"

# Update on-demand mount now-playing
curl -sk -u admin:changeme \
  "https://localhost:9443/admin/metadata?mount=/ondemand&mode=updinfo&song=Artist+-+Track"

ICY2 v2.2 Field Reference

Core Station Identity

HeaderTypeExample
icy-metadata-versionstring2.2
icy-meta-station-idstringmyradio-unique-001
icy-namestringMy Radio Station (ICY1 compat)
icy-genrestringElectronic / House
icy-urlURLhttps://myradio.com
icy-pub0/11
icy-brinteger128

Track / Now Playing

HeaderTypeExample
icy-titlestringTrack Title
icy-artiststringArtist Name
icy-albumstringAlbum Name
icy-yearinteger2024
icy-trackstring5
icy-isrcstringUSRC17607839
icy-bpmfloat128.5
icy-labelstringRecord Label
icy-composerstringComposer Name
icy-copyrightstring© 2024 Label

Show / Programming

HeaderTypeExample
icy-show-titlestringSaturday Night Live
icy-show-startISO86012024-02-15T21:00:00Z
icy-show-endISO86012024-02-16T01:00:00Z
icy-dj-handlestring@djname
icy-dj-biostringDJ based in Dallas TX
icy-venuestringClub 9330, Dallas TX
icy-languageBCP47en-US

Podcast Fields

HeaderTypeExample
icy-podcast-hoststringThe Podcast Host
icy-podcast-rssURLhttps://myshow.com/feed.rss
icy-podcast-episodeinteger42
icy-podcast-seasoninteger3
icy-podcast-durationseconds3600

Social Media

HeaderTypeExample
icy-social-twitterstring@myradio
icy-social-instagramstring@myradio
icy-social-tiktokstring@myradio
icy-emojistring🎵🔥
icy-hashtagsstring#electronic #live

Audio Technical

HeaderTypeExample
icy-audio-codecstringMP3, AAC, Opus, Vorbis
icy-audio-samplerateinteger44100
icy-audio-channelsinteger2
icy-audio-bitdepthinteger16, 24

Content Classification

HeaderTypeExample
icy-nsfwbooleanfalse
icy-ai-generatedbooleanfalse
icy-geo-regionstringUS, CA, GB (allow-list)
icy-content-ratingstringclean, explicit

Listener Engagement

HeaderTypeExample
icy-requests-urlURLhttps://myradio.com/request
icy-chat-urlURLhttps://myradio.com/chat
icy-donate-urlURLhttps://myradio.com/donate
icy-requests-enabledbooleantrue

Video / Stream Link

HeaderTypeExample
icy-video-typestringlive, vod
icy-video-linkURLhttps://youtube.com/live/...
icy-video-platformstringyoutube, twitch
icy-video-titlestringSaturday Night Stream
icy-video-resolutionstring1920x1080

Config — Mount-Level Defaults

ICY2 metadata fields can be pre-set per mount in YAML config so they are active from server startup without requiring a source encoder:

mounts:
  - mount-name: "/live"
    mount-type: "live"
    max-listeners: 100
    public: 1
    stream-name: "My Live Station"
    stream-description: "Electronic music live from Dallas"
    genre: "Electronic"
    bitrate: "128"
    icy-dj-handle: "@djname"
    icy-station-id: "myradio-001"
    icy-show-title: "The Evening Show"
    icy-requests-enabled: false
    icy-social-twitter: "@myradio"
    icy-hashtags: "#electronic #live"

  - mount-name: "/podcast"
    mount-type: "podcast"
    stream-name: "The Podcast"
    icy-podcast-host: "Host Name"
    icy-podcast-rss: "https://myshow.com/feed.rss"
    icy-requests-enabled: false

Stats API — ICY2 Metadata Exposure

ICY2 fields set on a mount are exposed in the server stats XML at /admin/stats:

<source mount="/live">
  <stream_start_iso8601>2026-02-22T18:00:00+0000</stream_start_iso8601>
  <title>Artist - Track Title</title>
  <genre>Electronic</genre>
  <bitrate>128</bitrate>
  <audio_codecid>audio/mpeg</audio_codecid>
  <audio_samplerate>44100</audio_samplerate>
  <audio_channels>2</audio_channels>
  <icy_dj_handle>@djname</icy_dj_handle>
  <icy_show_title>Saturday Night Live</icy_show_title>
  <icy_station_id>myradio-001</icy_station_id>
  <listeners>42</listeners>
  <max_listeners>100</max_listeners>
</source>

The public /status XML exposes the non-sensitive subset (title, genre, bitrate, codec, listener count).

Backward Compatibility Notes

See Also