Status: Implementation in Progress — Mcaster1DNAS v2.6.x (February 2026).
v2.1 fields are production-ready. v2.2 additions listed here are being rolled in incrementally.
See also the implementation guide at
ICY2 Protocol.
Specification Version: 2.2 |
Release Date: February 2026 |
Supersedes: ICY-META v2.1 (Feb 15, 2026)
Author: David St John (Saint John) — MediaCast1/Mcaster1DNAS |
CSSI Spec: ICY2-META-SPECS.md / https://casterclub.com/specs/icy-2
Overview
ICY-META v2.2 is an extended metadata protocol for streaming media servers, providing rich
metadata support beyond the legacy ICY 1.x protocol. It maintains backward compatibility while
adding modern features for podcasts, video streams, social media integration, track-level metadata,
station programming, listener engagement, audio technical parameters, broadcast distribution, and
content verification.
Design Principles
- Backward Compatible — ICY2 clients can connect to ICY1 servers; ICY1 clients can connect to ICY2 servers
- Zero Configuration — Auto-detection via version header, no server config changes needed
- HTTP-Based — Pure HTTP header communication, works over HTTP and HTTPS
- Extensible — Version numbering allows future enhancements (2.2, 2.3, etc.)
- Optional — All fields are optional; only send what’s relevant
Protocol Detection
Version Header
The presence of the icy-metadata-version header indicates ICY2 support:
icy-metadata-version: 2.1
Server Behavior:
- If header present with value
2.x → Parse as ICY2
- If header absent or invalid → Fall back to ICY 1.x legacy parsing
- Version check uses prefix matching (
2. matches 2.0, 2.1, 2.2, etc.)
Client Handshake
ICY2-compliant source clients send this header with their source PUT/POST request:
PUT /mountpoint.mp3 HTTP/1.1
Host: server.example.com:9443
icy-metadata-version: 2.2
icy-meta-station-id: unique-station-identifier
icy-name: My Station Name
icy-genre: Electronic
icy-br: 128
icy-pub: 1
Authorization: Basic c291cmNlOnBhc3N3b3Jk
Content-Type: audio/mpeg
[audio data]
v2.1 clients sending icy-station-id (without meta) instead of
icy-meta-station-id are fully supported. Legacy ICY 1.x fields (icy-name,
icy-genre, icy-br, icy-pub) are always parsed regardless of ICY2
version and must always be included for directory and player compatibility.
ICY 1.x Legacy Headers
These are the original SHOUTcast/Icecast ICY protocol headers. They are never modified, never removed,
and are always parsed independently of any ICY2 logic. ICY2 fields are additional — these remain
exactly as they have always been for full backwards compatibility.
| Header | Type | Description |
icy-name | String | Station or stream display name |
icy-genre | String | Genre or content type |
icy-url | URL | Station homepage or site |
icy-pub | Boolean | Public listing flag (1 = yes) |
icy-br | Integer | Bitrate in kbps |
icy-metaint | Integer | Interval in bytes between metadata blocks |
Legacy auth fields (also unchanged):
| Field | Description |
adminpassword | Admin interface password |
password | Source encoder password |
user | Optional username (SHOUTcast v2 / Icecast2) |
ICY2 v2.1 Header Forms (Backwards Compatible)
These are the original ICY2 v2.1 header names as implemented in the server’s C source
(icy2_meta_parse_headers()). They use the icy- prefix without meta.
The server continues to accept these from any client that connected using the v2.1 format.
| v2.1 Header (icy- prefix) | v2.2 Header (icy-meta- prefix) | Stats Key |
icy-station-id | icy-meta-station-id | icy2-station-id |
icy-podcast-host | icy-meta-podcast-host | icy2-podcast-host |
icy-podcast-rss | icy-meta-podcast-rss | icy2-podcast-rss |
icy-podcast-episode | icy-meta-podcast-episode | icy2-podcast-episode |
icy-duration | icy-meta-duration | icy2-duration |
icy-language | icy-meta-language | icy2-language |
icy-video-type | icy-meta-videotype | icy2-video-type |
icy-video-link | icy-meta-videolink | icy2-video-link |
icy-video-title | icy-meta-videotitle | icy2-video-title |
icy-video-platform | icy-meta-videoplatform | icy2-video-platform |
icy-video-resolution | icy-meta-videoresolution | icy2-video-resolution |
icy-dj-handle | icy-meta-dj-handle | icy2-dj-handle |
icy-social-twitter | icy-meta-social-twitter | icy2-social-twitter |
icy-social-ig | icy-meta-social-ig | icy2-social-instagram |
icy-social-tiktok | icy-meta-social-tiktok | icy2-social-tiktok |
icy-emoji | icy-meta-emoji | icy2-emoji |
icy-hashtags | icy-meta-hashtag-array | icy2-hashtags |
icy-auth-token | icy-meta-auth-token | icy2-auth-token |
icy-nsfw | icy-meta-nsfw | icy2-nsfw |
icy-ai-generated | icy-meta-ai-generator | icy2-ai-generated |
icy-geo-region | icy-meta-geo-region | icy2-geo-region |
icy-certificate-verify | icy-meta-certificate | icy2-certificate |
icy-verification-status | icy-meta-verification-status | icy2-verification-status |
The C parser tries icy-meta-X first, then falls back to icy-X for each field — both always work.
Field Reference (v2.2)
Station Identity
| Header | Type | Stats Key | Notes |
icy-meta-station-id | String | icy2-station-id | Permanent unique station identifier |
icy-meta-station-logo | URL | icy2-station-logo | Station logo/branding image |
icy-meta-certissuer-id | String | icy2-certissuer-id | Certificate authority ID |
icy-meta-cert-rootca | String | icy2-cert-rootca | Root CA hash |
icy-meta-certificate | String | icy2-certificate | Base64 PEM certificate |
icy-meta-ssh-pubkey | String | icy2-ssh-pubkey | SSH public key for auth |
icy-meta-verification-status | Enum | icy2-verification-status | unverified/pending/verified/gold |
Programming / Show
| Header | Type | Stats Key | Notes |
icy-meta-show-title | String | icy2-show-title | Current program title |
icy-meta-show-start | ISO8601 | icy2-show-start | Current show start time |
icy-meta-show-end | ISO8601 | icy2-show-end | Current show end time |
icy-meta-next-show | String | icy2-next-show | Next scheduled program |
icy-meta-next-show-time | ISO8601 | icy2-next-show-time | Next show start time |
icy-meta-schedule-url | URL | icy2-schedule-url | Full program schedule URL |
icy-meta-autodj | Boolean | icy2-autodj | 1=automation active, 0=live |
icy-meta-playlist-name | String | icy2-playlist-name | Current playlist or automation source |
DJ / Host
| Header | Type | Stats Key | Notes |
icy-meta-dj-handle | String | icy2-dj-handle | Social handle (e.g., @djsynthwave) |
icy-meta-dj-bio | String | icy2-dj-bio | Short biography or tagline, max 280 chars |
icy-meta-dj-genre | String | icy2-dj-genre | Comma-separated genres, max 5 |
icy-meta-dj-showrating | Enum | icy2-dj-showrating | all-ages, teen, mature, explicit |
Track Metadata
| Header | Type | Stats Key | Notes |
icy-meta-track-artwork | URL | icy2-track-artwork | Album/track art URL — primary player display |
icy-meta-track-album | String | icy2-track-album | Album or release name |
icy-meta-track-year | Integer | icy2-track-year | Release year |
icy-meta-track-label | String | icy2-track-label | Record label |
icy-meta-track-bpm | Integer | icy2-track-bpm | Beats per minute |
icy-meta-track-key | String | icy2-track-key | Musical key (e.g., 8B, Am) |
icy-meta-track-genre | String | icy2-track-genre | Per-track genre |
icy-meta-track-mbid | UUID | icy2-track-mbid | MusicBrainz Recording ID |
icy-meta-track-isrc | String | icy2-track-isrc | International Standard Recording Code |
Podcast
| Header | Type | Stats Key | Notes |
icy-meta-podcast-host | String | icy2-podcast-host | Podcast creator/host name |
icy-meta-podcast-rating | Enum | icy2-podcast-rating | all-ages, teen, mature, explicit |
icy-meta-podcast-rss | URL | icy2-podcast-rss | RSS feed URL |
icy-meta-podcast-episode | String | icy2-podcast-episode | Episode title or ID |
icy-meta-duration | Integer | icy2-duration | Content runtime in seconds (all types) |
icy-meta-language | String | icy2-language | ISO 639-1 language tag |
Video
| Header | Type | Stats Key | Notes |
icy-meta-videotype | Enum | icy2-video-type | live, short, clip, trailer, ad |
icy-meta-videorating | Enum | icy2-video-rating | all-ages, teen, mature, explicit |
icy-meta-videolink | URL | icy2-video-link | Video content URL |
icy-meta-videotitle | String | icy2-video-title | Video title |
icy-meta-videoposter | URL | icy2-video-poster | Thumbnail/preview image |
icy-meta-videochannel | String | icy2-video-channel | Creator/channel handle |
icy-meta-videoplatform | Enum | icy2-video-platform | youtube, tiktok, twitch, kick, rumble, vimeo |
icy-meta-videostart | ISO8601 | icy2-video-start | Scheduled video start time |
icy-meta-videolive | Boolean | icy2-video-live | 1=currently live |
icy-meta-videocodec | String | icy2-video-codec | h264, vp9, av1 |
icy-meta-videofps | Integer | icy2-video-fps | Frames per second |
icy-meta-videoresolution | String | icy2-video-resolution | e.g., 1080p, 4K |
icy-meta-videonsfw | Boolean | icy2-video-nsfw | Video-specific NSFW flag |
Audio Technical
| Header | Type | Stats Key | Notes |
icy-meta-audio-codec | Enum | icy2-audio-codec | mp3, aac, aac-he, ogg, opus, flac |
icy-meta-samplerate | Integer | icy2-samplerate | Sample rate in Hz |
icy-meta-channels | Integer | icy2-channels | 1=mono, 2=stereo, 6=5.1 |
icy-meta-loudness | Float | icy2-loudness | LUFS integrated loudness (EBU R128) |
icy-meta-encoder | String | icy2-encoder | Encoder name and version |
Social
| Header | Type | Stats Key | Notes |
icy-meta-creator-handle | String | icy2-creator-handle | Platform-agnostic public identity |
icy-meta-social-twitter | String | icy2-social-twitter | Twitter/X handle |
icy-meta-social-twitch | String | icy2-social-twitch | Twitch handle |
icy-meta-social-ig | String | icy2-social-instagram | Instagram username |
icy-meta-social-tiktok | String | icy2-social-tiktok | TikTok profile name |
icy-meta-social-youtube | URL | icy2-social-youtube | YouTube channel URL |
icy-meta-social-facebook-page | URL | icy2-social-facebook | Facebook page URL |
icy-meta-social-linkedin | URL | icy2-social-linkedin | LinkedIn profile URL |
icy-meta-social-linktree | URL | icy2-social-linktree | Unified profile link |
icy-meta-emoji | String | icy2-emoji | Mood/emotion indicators |
icy-meta-hashtag-array | JSON | icy2-hashtags | JSON array of hashtag strings |
Listener Engagement
| Header | Type | Stats Key | Notes |
icy-meta-request-enabled | Boolean | icy2-request-enabled | 1=requests open |
icy-meta-request-url | URL | icy2-request-url | Song request / dedication form |
icy-meta-chat-url | URL | icy2-chat-url | Live listener chat URL |
icy-meta-tip-url | URL | icy2-tip-url | Listener donation/tip URL |
icy-meta-events-url | URL | icy2-events-url | Upcoming events page |
Broadcast Distribution
| Header | Type | Stats Key | Notes |
icy-meta-crosspost-platforms | String | icy2-crosspost-platforms | Comma-sep active platforms (e.g., youtube,twitch) |
icy-meta-stream-session-id | String | icy2-stream-session-id | Unique ID for this broadcast session |
icy-meta-cdn-region | String | icy2-cdn-region | CDN distribution region (e.g., us-east, eu-west) |
icy-meta-relay-origin | URL | icy2-relay-origin | Origin server URL if this is a relay mount |
Station Notices
| Header | Type | Stats Key | Notes |
icy-meta-notice | String | icy2-notice | General listener notice/announcement |
icy-meta-notice-url | URL | icy2-notice-url | Click-through URL for notice |
icy-meta-notice-expires | ISO8601 | icy2-notice-expires | Datetime after which notice is hidden |
Access & Authentication
| Header | Type | Stats Key | Notes |
icy-meta-auth-token | JWT | icy2-auth-token | Bearer JWT or custom token |
Content Flags & Compliance
| Header | Type | Stats Key | Notes |
icy-meta-nsfw | Boolean | icy2-nsfw | Binary NSFW filter flag for directory filtering |
icy-meta-ai-generator | Boolean | icy2-ai-generated | AI-generated content transparency flag |
icy-meta-geo-region | String | icy2-geo-region | Target region (ISO 3166-1, e.g., US, EU, GLOBAL) |
icy-meta-license-type | Enum | icy2-license-type | cc-by, cc0, pro-licensed, all-rights-reserved |
icy-meta-royalty-free | Boolean | icy2-royalty-free | 1=royalty-free content |
icy-meta-license-territory | String | icy2-license-territory | Comma-sep ISO country codes, or GLOBAL |
Server Implementation
Detection Logic
// Check for ICY2 version header
const char *version = httpp_getvar(parser, "icy-metadata-version");
if (version && strncmp(version, "2.", 2) == 0) {
// Parse as ICY2
icy2_metadata *meta = icy2_meta_new();
icy2_meta_parse_headers(meta, parser);
icy2_meta_copy_to_stats(meta, source->stats);
icy2_meta_free(meta);
} else {
// Fall back to ICY 1.x legacy parsing
parse_legacy_icy_headers(parser);
}
Parser Implementation Notes
The v2.2 parser accepts both icy-meta-X (spec-compliant) and legacy icy-X (v2.1 clients)
header forms during the migration period. Try icy-meta-X first; fall back to icy-X:
/* Example: station-id -- try spec-compliant prefix first, fall back for v2.1 clients */
str = httpp_getvar(parser, "icy-meta-station-id");
if (!str) str = httpp_getvar(parser, "icy-station-id");
if (str) meta->station_id = icy2_strdup_safe(str);
Version History
| Version | Release Date | Status | Key Features |
| 2.1 | February 15, 2026 | ✅ Released | Core station ID, podcast, video, social, content flags |
| 2.2 | February 2026 | 🚧 In Progress | Track metadata, artwork, show scheduling, audio technical, notices, engagement, distribution, PKI, licensing |
| 2.3 | Q3 2026 | 💡 Proposed | Dynamic updates, multi-language, subscriber metadata, interactivity |
Client Best Practices
- Always include
icy-metadata-version — this triggers ICY2 parsing
- Use consistent
station-id — helps with stream tracking and analytics
- Provide social media handles — enhances discoverability
- Set appropriate content flags — NSFW, AI-generated for transparency
- Include video metadata if streaming video alongside audio
- Use emoji sparingly — 2–5 emoji max for UI enhancement
- Validate URLs — ensure all URL fields are properly formatted
- Keep hashtags relevant — 3–10 hashtags, space or comma-separated
License & Attribution
Copyright © 2026 David St John (Saint John) — MediaCast1 / Mcaster1DNAS Project.
Released under the Creative Commons Attribution 4.0 International License (CC BY 4.0).
Implementation in Mcaster1DNAS is licensed under GNU GPL v2.