Docs
Every function, where each field goes in each format, all 104 ID3v2 frames, the 148 genres and the byte layout of every tag.
Introduction
audio-tag reads a file's tags into a metadata object that is the same for every format, and also gives you each format's own structures: ID3v2 frames, MP4 atoms, Vorbis comments, RIFF and AIFF chunks. Writing takes the same metadata shape and changes only what you pass.
- Runs anywhere. The core uses only
Uint8Array, so it works the same in browsers, Node, Deno, Bun and workers. It has no dependencies. - Exact round trips. A tag read and written back unchanged gives identical bytes, including unknown, encrypted and oddly encoded frames.
- Strict writer, tolerant reader. Problems are reported as warnings;
strict: trueturns them into errors.
Install
npm install audio-tagpnpm add audio-tagyarn add audio-tagbun add audio-tagThere are three entry points. Each one includes everything from audio-tag.
| Import | Works with | Runs in |
|---|---|---|
audio-tag | Bytes (Uint8Array) | Any JavaScript runtime |
audio-tag/browser | Blob and File | Browsers, Deno, Bun, workers |
audio-tag/node | Paths on disk | Node |
Offline docs: the package includes this website, with the docs and the playground. Open your installed copy with
npx audio-tag --open(oryarn audio-tag --open,bunx audio-tag --open). It serves on port 5173; add--port 8080to use another one.
Usage
The "any file" functions detect the format and call the right reader or writer. Pick your runtime:
import { readFromBlob, writeToBlob } from 'audio-tag/browser'
// reads only the tag regions of large files
const { format, metadata } = await readFromBlob(file)
console.log(format, metadata.title, metadata.artist, metadata.pictures?.[0])
const updated = await writeToBlob(file, { metadata: { title: 'New title', genre: ['Rock'] } })
// a File with the same name and type; the audio is never copied into memoryimport { readFile, writeFile, readID3FromFile, writeID3ToFile, removeID3FromFile } from 'audio-tag/node'
const { metadata } = await readFile('song.m4a') // the format is detected
await writeFile('song.m4a', { metadata: { album: 'Album', track: { no: 1, of: 12 } } })
const { id3v2, id3v1, lyrics3, warnings } = await readID3FromFile('song.mp3')
await writeID3ToFile('song.mp3', { metadata: { title: 'x' } }, { version: 3 })
// in place when the tag still fits, otherwise through an atomic temp-file rename
await removeID3FromFile('song.mp3', { id3v1: true })import { read, write } from 'audio-tag'
const result = read(bytes)
if (result.format === 'flac') console.log(result.streamInfo)
const { bytes: out, inPlace } = write(bytes, { metadata: { title: 'x' } })Note: data that is no recognised audio format (a JPEG, a text file, a bare ID3v1 tag, empty input) throws an
UnknownFormatError(format-unknown) and is never changed. Use the ID3 functions for a bare ID3v1 tag. A bare ID3v2 tag counts as MPEG audio ('mpeg') and is read as one.
Functions
Every format has its own functions, and one set handles any file. Use a format's own functions when you know the format, or want its own result type and options. They refuse other formats with an error that says so.
| Bytes | Blob / File | Files on disk | |
|---|---|---|---|
| Any file | read / write | readFromBlob / writeToBlob | readFile / writeFile |
| ID3 | readID3File / writeID3File | readID3FromBlob / writeID3ToBlob | readID3FromFile / writeID3ToFile / removeID3FromFile |
| MP4 | readMP4File / writeMP4File | readMP4FromBlob / writeMP4ToBlob | readMP4FromFile / writeMP4ToFile |
| FLAC | readFLACFile / writeFLACFile | readFLACFromBlob / writeFLACToBlob | readFLACFromFile / writeFLACToFile |
| Ogg | readOggFile / writeOggFile | readOggFromBlob / writeOggToBlob | readOggFromFile / writeOggToFile |
| AIFF | readAIFFFile / writeAIFFFile | readAIFFFromBlob / writeAIFFToBlob | readAIFFFromFile / writeAIFFToFile |
| WAV | readRIFFFile / writeRIFFFile | readRIFFFromBlob / writeRIFFToBlob | readRIFFFromFile / writeRIFFToFile |
To branch on the format yourself, call detectFormat(bytes). It returns 'mpeg', 'mp4', 'flac', 'ogg', 'aiff', 'riff' or 'unknown'.
Metadata
metadata is the same for every format. Each format maps the fields to its own frames, atoms or comments, and a field the format has no place for is rejected on write.
| Field | Type | Notes |
|---|---|---|
title, subtitle, album, albumArtist, grouping | string | |
artist, composer, lyricist, genre, language | string[] | Several values. ID3v1 genre numbers are resolved to names. |
track, disc | { no?, of? } | |
bpm | number | |
length | number | Milliseconds. For FLAC, Ogg, AIFF and WAV it comes from the audio headers. |
recordingTime, releaseTime, originalReleaseTime | string | ISO 8601 subset, such as "2024" or "2024-05-01". yearOf() gives the year. |
comments, lyrics | { language, description, text }[] | |
pictures | Picture[] | { type, mimeType, description, data }; type 3 is the front cover. |
ratings, playCount | ID3 only. | |
compilation | boolean | |
sort | { title?, artist?, album?, albumArtist?, composer? } | Sort orders. |
userText, userUrls | Record<string, string> | ID3 TXXX and WXXX, and their counterparts in other formats. |
Also available: setSubtitle, conductor, remixer, publisher, copyright, encodedBy, encoderSettings, isrc, mood, key, encodingTime and taggingTime.
Writing
A write changes only the fields you pass. undefined leaves a field alone and null removes it:
const cover = { type: 3, mimeType: 'image/jpeg', description: '', data: jpegBytes }
const out = await writeToBlob(file, {
metadata: {
title: 'New title', // set
comments: null, // remove
pictures: [cover], // replace all pictures
},
})Besides metadata, each format takes its own input: id3v2, id3v1 and lyrics3 for ID3 files (id3v2 is also the ID3 chunk of AIFF and WAV files), and mp4, flac, ogg, aiff and riff for theirs. Options that do not apply to the file, such as version for an MP4 file, are refused instead of ignored.
| Option | Formats | Effect |
|---|---|---|
strict | All | Warnings become errors. |
version | ID3, AIFF, WAV | ID3v2 version to write (2, 3 or 4). Default: the file's version, or 4. |
id3v1 | ID3 | 'keep' (default), 'always' or 'never'. |
padding | ID3, MP4, FLAC, AIFF, WAV | Free space to leave when the tags are rewritten, so later edits fit in place. For AIFF and WAV it pads the tag in the ID3 chunk. Ogg files ignore it. |
Tip: the byte-level
write()returnsinPlace: truewhen the file length and the audio position did not change, so only the tag bytes need to be saved.
Results by format
read() returns a result narrowed by format. Every result has metadata, layout (the byte offsets the playground's byte map draws) and warnings, plus the format's own view:
| format | Own view |
|---|---|
'mpeg' | id3v2 (the effective tag: all ID3v2 tags in the file merged), id3v1 and lyrics3. metadata takes ID3v2 first, then Lyrics3, then ID3v1. |
'mp4' | mp4: the iTunes items, the QuickTime metadata and the user-data text. metadata takes them in that order. |
'flac' | flac: the Vorbis comment block and the picture blocks. streamInfo: sample rate, channels, length and more. |
'ogg' | ogg: the codec ('vorbis', 'opus' or 'flac'), the comment and its pictures. stream: the header packets and pages. |
'aiff' | aiff: the text chunks, the Comments chunk and the ID3 chunk's tag. common: channels, sample frames, sample size and rate. |
'riff' | riff: the INFO list and the ID3 chunk's tag. audio: the format chunk, and the sizes the length comes from. |
Errors and warnings
Reading never fails on small problems: each one becomes a { code, message } entry in warnings. Errors carry a code too.
| Error | When |
|---|---|
TagReadError | A file can't be read, or a warning came up with strict: true. |
TagWriteError | A write was refused. MP4WriteError, FLACWriteError, OggWriteError, AIFFWriteError and RIFFWriteError extend it. |
UnknownFormatError | format-unknown: the data is no supported audio format. |
NotImplementedError | An Ogg codec without comment support, such as Speex or Theora. |
Warning: the per-format functions refuse other formats (
format-mp4from the ID3 functions,format-not-flac,format-not-riffand so on). Check withdetectFormat()first, or useread()andwrite().
Formats
MP3 · ID3
ID3v1 and v1.1, ID3v2.2, 2.3 and 2.4, and Lyrics3 v1 and v2.00. The library covers unsynchronisation, synchsafe sizes, zlib frame compression, encryption and grouping hooks, CRC-32, tag restrictions, SEEK, appended tags with footers, every frame layout of every version, and conversion between versions. It passes all 274 cases of the official ID3v1 test suite.
MP4 · M4A
.m4a, .m4b, .mp4 and .mov files keep their tags in metadata atoms, not ID3. When the new metadata fits in the file's free space, the file is rewritten in place. Otherwise every chunk offset (stco/co64) is moved, so the audio stays playable. Ratings and play counts are rejected.
FLAC
Tags live in a Vorbis comment block (TITLE=..., repeated for several values) and picture blocks. Field names follow MusicBrainz Picard, as RFC 9639 suggests. Unchanged blocks keep their bytes, and a write uses the old padding, so it is usually in place.
Ogg
Vorbis, Opus and FLAC-in-Ogg comment headers, with the same field names as FLAC. Covers are METADATA_BLOCK_PICTURE fields. A write rewrites only the header pages, with new CRCs. A cover that needs more pages renumbers the following pages, which rewrites the whole file.
AIFF · AIFF-C
Rich metadata goes in an ID3 chunk, created at the end of the file when missing, so the sound data does not move. The NAME, AUTH, (c) , ANNO and COMT chunks are read as fallbacks, and existing NAME/AUTH/(c) chunks are kept in step (ASCII only, as the spec requires).
WAV
The same idea as AIFF: an id3 chunk for rich metadata, and the LIST/INFO list (INAM, IART, IPRD and others) as a fallback, kept in step. Several values are joined with "; ", and INFO text is ISO 8859-1 unless a CSET chunk says otherwise.
Note: some taggers put ID3 tags in front of FLAC, Ogg, AIFF or WAV files. They are kept on write and noted on read.
Where the specs disagree
The specifications contradict themselves in a few places. Each decision is marked with a // SPEC: comment in the code:
- The Lyrics3v2 page's prose says 1064 bytes and 6-digit field sizes, but its own example uses 1065 bytes and 5-digit sizes. The example wins.
- The v2.3
LINKframe lists a 3-byte frame ID; the reader accepts 3 or 4 bytes. - Genres 126 to 147 are only named by the official test suite.
- Apple's QuickTime spec defines only
mdtametadata. The iTunes item list follows ExifTool, mutagen, AtomicParsley and Picard. - The spec gives no unit for v2.3
RVAD/EQUAvalues, so they are not converted to v2.4RVA2/EQU2. - RFC 9639 defines no Vorbis comment field names, so they come from MusicBrainz Picard, as the RFC suggests.
- No AIFF spec defines the
ID3chunk; it is implemented as ExifTool documents it. - RIFF INFO text is ISO 8859-1 by the spec, but many writers put UTF-8 there. Valid UTF-8 is read as UTF-8, with a warning.
- RFC 3533 gives a page on which no packet ends a granule position of -1, while the Vorbis spec says header pages have 0. Header pages get 0, or -1 when no packet ends on them.
Field mapping
Where each metadata field is written in each format. AIFF and WAV files keep every field in their ID3 chunk, as the ID3v2 columns show; the WAV INFO and AIFF text columns are the extra copies kept in step when the file already has those chunks. MP4 freeform items are shown as ----:NAME; their full key is ----:com.apple.iTunes:NAME.
| Field | ID3v2.4 | ID3v2.3 | ID3v2.2 | MP4 | FLAC · Ogg | WAV INFO | AIFF text |
|---|---|---|---|---|---|---|---|
title | TIT2 | TIT2 | TT2 | ©nam | TITLE | INAM | NAME |
subtitle | TIT3 | TIT3 | TT3 | ----:SUBTITLE | SUBTITLE | n/a | n/a |
grouping | TIT1 | TIT1 | TT1 | ©grp | GROUPING | n/a | n/a |
artist | TPE1 | TPE1 | TP1 | ©ART | ARTIST | IART | AUTH |
albumArtist | TPE2 | TPE2 | TP2 | aART | ALBUMARTIST | n/a | n/a |
album | TALB | TALB | TAL | ©alb | ALBUM | IPRD | n/a |
setSubtitle | TSST | TXXX:TSST | TXX:TSST | ----:DISCSUBTITLE | DISCSUBTITLE | n/a | n/a |
composer | TCOM | TCOM | TCM | ©wrt | COMPOSER | IMUS | n/a |
lyricist | TEXT | TEXT | TXT | ----:LYRICIST | LYRICIST | n/a | n/a |
conductor | TPE3 | TPE3 | TP3 | ©con | CONDUCTOR | n/a | n/a |
remixer | TPE4 | TPE4 | TP4 | ----:REMIXER | REMIXER | n/a | n/a |
publisher | TPUB | TPUB | TPB | ----:LABEL | LABEL | n/a | n/a |
copyright | TCOP | TCOP | TCR | cprt | COPYRIGHT | ICOP | (c) |
encodedBy | TENC | TENC | TEN | ©enc | ENCODEDBY | IENC | n/a |
encoderSettings | TSSE | TSSE | TSS | ©too | ENCODERSETTINGS | ISFT | n/a |
isrc | TSRC | TSRC | TRC | ----:ISRC | ISRC | n/a | n/a |
language | TLAN | TLAN | TLA | ----:LANGUAGE | LANGUAGE | ILNG | n/a |
mood | TMOO | TXXX:TMOO | TXX:TMOO | ----:MOOD | MOOD | n/a | n/a |
key | TKEY | TKEY | TKE | ----:initialkey | KEY | n/a | n/a |
bpm | TBPM | TBPM | TBP | tmpo | BPM | n/a | n/a |
length | TLEN | TLEN | TLE | n/a | n/a | n/a | n/a |
track | TRCK | TRCK | TRK | trkn | TRACKNUMBER TRACKTOTAL | ITRK | n/a |
disc | TPOS | TPOS | TPA | disk | DISCNUMBER DISCTOTAL | n/a | n/a |
genre | TCON | TCON | TCO | ©gen | GENRE | IGNR | n/a |
recordingTime | TDRC | TYER TDAT | TYE TDA | ©day | DATE | ICRD | n/a |
releaseTime | TDRL | TXXX:TDRL | TXX:TDRL | ----:RELEASEDATE | RELEASEDATE | n/a | n/a |
originalReleaseTime | TDOR | TORY | TOR | n/a | ORIGINALDATE | n/a | n/a |
encodingTime | TDEN | TXXX:TDEN | TXX:TDEN | n/a | n/a | n/a | n/a |
taggingTime | TDTG | TXXX:TDTG | TXX:TDTG | n/a | n/a | n/a | n/a |
comments | COMM | COMM | COM | ©cmt | COMMENT | ICMT | n/a |
lyrics | USLT | USLT | ULT | ©lyr | LYRICS | n/a | n/a |
pictures | APIC | APIC | PIC | covr | PICTURE block · METADATA_BLOCK_PICTURE | n/a | n/a |
ratings | POPM | POPM | POP | n/a | n/a | n/a | n/a |
playCount | PCNT | PCNT | CNT | n/a | n/a | n/a | n/a |
compilation | TCMP | TCMP | TCP | cpil | COMPILATION | n/a | n/a |
sort | TSOT TSOP TSOA TSO2 TSOC | TSOT TSOP TSOA TSO2 TSOC | TST TSP TSA TS2 TSC | sonm soar soal soaa soco | TITLESORT ARTISTSORT ALBUMSORT ALBUMARTISTSORT COMPOSERSORT | n/a | n/a |
userText | TXXX:<name> | TXXX:<name> | TXX:<name> | ----:<name> | <NAME> | n/a | n/a |
userUrls | WXXX:<name> | WXXX:<name> | WXX:<name> | ----:<name> | n/a | n/a | n/a |
ID3v2 frames
Every frame of ID3v2.2, v2.3 and v2.4 is read, written and validated, along with the chapter and accessibility addenda and 8 common unofficial frames (RGAD, XRVA, and iTunes' TCMP and sort-order frames). Frames the library does not know are kept byte for byte.
| Frame | v2.2 | v2.3 | v2.4 | Layout | Source |
|---|---|---|---|---|---|
| Content group description | TT1 §4.2.1 | TIT1 §4.2.1 | TIT1 §4.2.1 | text | spec |
| Title/songname/content description | TT2 §4.2.1 | TIT2 §4.2.1 | TIT2 §4.2.1 | text | spec |
| Subtitle/Description refinement | TT3 §4.2.1 | TIT3 §4.2.1 | TIT3 §4.2.1 | text | spec |
| Album/Movie/Show title | TAL §4.2.1 | TALB §4.2.1 | TALB §4.2.1 | text | spec |
| Original album/movie/show title | TOT §4.2.1 | TOAL §4.2.1 | TOAL §4.2.1 | text | spec |
| Track number/Position in set | TRK §4.2.1 | TRCK §4.2.1 | TRCK §4.2.1 | text | spec |
| Part of a set | TPA §4.2.1 | TPOS §4.2.1 | TPOS §4.2.1 | text | spec |
| Set subtitle | n/a | n/a | TSST §4.2.1 | text | spec |
| ISRC (international standard recording code) | TRC §4.2.1 | TSRC §4.2.1 | TSRC §4.2.1 | text | spec |
| Lead performer(s)/Soloist(s) | TP1 §4.2.1 | TPE1 §4.2.1 | TPE1 §4.2.2 | text | spec |
| Band/orchestra/accompaniment | TP2 §4.2.1 | TPE2 §4.2.1 | TPE2 §4.2.2 | text | spec |
| Conductor/performer refinement | TP3 §4.2.1 | TPE3 §4.2.1 | TPE3 §4.2.2 | text | spec |
| Interpreted, remixed, or otherwise modified by | TP4 §4.2.1 | TPE4 §4.2.1 | TPE4 §4.2.2 | text | spec |
| Original artist(s)/performer(s) | TOA §4.2.1 | TOPE §4.2.1 | TOPE §4.2.2 | text | spec |
| Lyricist/Text writer | TXT §4.2.1 | TEXT §4.2.1 | TEXT §4.2.2 | text | spec |
| Original lyricist(s)/text writer(s) | TOL §4.2.1 | TOLY §4.2.1 | TOLY §4.2.2 | text | spec |
| Composer | TCM §4.2.1 | TCOM §4.2.1 | TCOM §4.2.2 | text | spec |
| Musician credits list | n/a | n/a | TMCL §4.2.2 | text | spec |
| Involved people list | n/a | n/a | TIPL §4.2.2 | text | spec |
| Encoded by | TEN §4.2.1 | TENC §4.2.1 | TENC §4.2.2 | text | spec |
| BPM (beats per minute) | TBP §4.2.1 | TBPM §4.2.1 | TBPM §4.2.3 | text | spec |
| Length | TLE §4.2.1 | TLEN §4.2.1 | TLEN §4.2.3 | text | spec |
| Initial key | TKE §4.2.1 | TKEY §4.2.1 | TKEY §4.2.3 | text | spec |
| Language(s) | TLA §4.2.1 | TLAN §4.2.1 | TLAN §4.2.3 | text | spec |
| Content type | TCO §4.2.1 | TCON §4.2.1 | TCON §4.2.3 | text | spec |
| File type | TFT §4.2.1 | TFLT §4.2.1 | TFLT §4.2.3 | text | spec |
| Media type | TMT §4.2.1 | TMED §4.2.1 | TMED §4.2.3 | text | spec |
| Mood | n/a | n/a | TMOO §4.2.3 | text | spec |
| Copyright message | TCR §4.2.1 | TCOP §4.2.1 | TCOP §4.2.4 | text | spec |
| Produced notice | n/a | n/a | TPRO §4.2.4 | text | spec |
| Publisher | TPB §4.2.1 | TPUB §4.2.1 | TPUB §4.2.4 | text | spec |
| File owner/licensee | n/a | TOWN §4.2.1 | TOWN §4.2.4 | text | spec |
| Internet radio station name | n/a | TRSN §4.2.1 | TRSN §4.2.4 | text | spec |
| Internet radio station owner | n/a | TRSO §4.2.1 | TRSO §4.2.4 | text | spec |
| Original filename | TOF §4.2.1 | TOFN §4.2.1 | TOFN §4.2.5 | text | spec |
| Playlist delay | TDY §4.2.1 | TDLY §4.2.1 | TDLY §4.2.5 | text | spec |
| Encoding time | n/a | n/a | TDEN §4.2.5 | text | spec |
| Original release time | n/a | n/a | TDOR §4.2.5 | text | spec |
| Recording time | n/a | n/a | TDRC §4.2.5 | text | spec |
| Release time | n/a | n/a | TDRL §4.2.5 | text | spec |
| Tagging time | n/a | n/a | TDTG §4.2.5 | text | spec |
| Software/Hardware and settings used for encoding | TSS §4.2.1 | TSSE §4.2.1 | TSSE §4.2.5 | text | spec |
| Album sort order | n/a | n/a | TSOA §4.2.5 | text | spec |
| Performer sort order | n/a | n/a | TSOP §4.2.5 | text | spec |
| Title sort order | n/a | n/a | TSOT §4.2.5 | text | spec |
| Year | TYE §4.2.1 | TYER §4.2.1 | n/a | text | spec |
| Date | TDA §4.2.1 | TDAT §4.2.1 | n/a | text | spec |
| Time | TIM §4.2.1 | TIME §4.2.1 | n/a | text | spec |
| Original release year | TOR §4.2.1 | TORY §4.2.1 | n/a | text | spec |
| Recording dates | TRD §4.2.1 | TRDA §4.2.1 | n/a | text | spec |
| Size | TSI §4.2.1 | TSIZ §4.2.1 | n/a | text | spec |
| User defined text information frame | TXX §4.2.2 | TXXX §4.2.2 | TXXX §4.2.6 | user-text | spec |
| Commercial information | WCM §4.3.1 | WCOM §4.3.1 | WCOM §4.3.1 | url | spec |
| Copyright/Legal information | WCP §4.3.1 | WCOP §4.3.1 | WCOP §4.3.1 | url | spec |
| Official audio file webpage | WAF §4.3.1 | WOAF §4.3.1 | WOAF §4.3.1 | url | spec |
| Official artist/performer webpage | WAR §4.3.1 | WOAR §4.3.1 | WOAR §4.3.1 | url | spec |
| Official audio source webpage | WAS §4.3.1 | WOAS §4.3.1 | WOAS §4.3.1 | url | spec |
| Official Internet radio station homepage | n/a | WORS §4.3.1 | WORS §4.3.1 | url | spec |
| Payment | n/a | WPAY §4.3.1 | WPAY §4.3.1 | url | spec |
| Publishers official webpage | WPB §4.3.1 | WPUB §4.3.1 | WPUB §4.3.1 | url | spec |
| User defined URL link frame | WXX §4.3.2 | WXXX §4.3.2 | WXXX §4.3.2 | user-url | spec |
| Involved people list | IPL §4.4 | IPLS §4.4 | n/a | involved-people | spec |
| Unique file identifier | UFI §4.1 | UFID §4.1 | UFID §4.1 | ufid | spec |
| Music CD identifier | MCI §4.5 | MCDI §4.5 | MCDI §4.4 | mcdi | spec |
| Event timing codes | ETC §4.6 | ETCO §4.6 | ETCO §4.5 | etco | spec |
| MPEG location lookup table | MLL §4.7 | MLLT §4.7 | MLLT §4.6 | mllt | spec |
| Synchronised tempo codes | STC §4.8 | SYTC §4.8 | SYTC §4.7 | sytc | spec |
| Unsynchronised lyrics/text transcription | ULT §4.9 | USLT §4.9 | USLT §4.8 | uslt | spec |
| Synchronised lyrics/text | SLT §4.10 | SYLT §4.10 | SYLT §4.9 | sylt | spec |
| Comments | COM §4.11 | COMM §4.11 | COMM §4.10 | comment | spec |
| Relative volume adjustment | RVA §4.12 | RVAD §4.12 | n/a | rvad | spec |
| Relative volume adjustment (2) | n/a | n/a | RVA2 §4.11 | rva2 | spec |
| Equalisation | EQU §4.13 | EQUA §4.13 | n/a | equa | spec |
| Equalisation (2) | n/a | n/a | EQU2 §4.12 | equ2 | spec |
| Reverb | REV §4.14 | RVRB §4.14 | RVRB §4.13 | rvrb | spec |
| Attached picture | PIC §4.15 | APIC §4.15 | APIC §4.14 | picture | spec |
| General encapsulated object | GEO §4.16 | GEOB §4.16 | GEOB §4.15 | geob | spec |
| Play counter | CNT §4.17 | PCNT §4.17 | PCNT §4.16 | pcnt | spec |
| Popularimeter | POP §4.18 | POPM §4.18 | POPM §4.17 | popm | spec |
| Recommended buffer size | BUF §4.19 | RBUF §4.19 | RBUF §4.18 | rbuf | spec |
| Encrypted meta frame | CRM §4.20 | n/a | n/a | crm | spec |
| Audio encryption | CRA §4.21 | AENC §4.20 | AENC §4.19 | aenc | spec |
| Linked information | LNK §4.22 | LINK §4.21 | LINK §4.20 | link | spec |
| Position synchronisation frame | n/a | POSS §4.22 | POSS §4.21 | poss | spec |
| Terms of use | n/a | USER §4.23 | USER §4.22 | user | spec |
| Ownership frame | n/a | OWNE §4.24 | OWNE §4.23 | owne | spec |
| Commercial frame | n/a | COMR §4.25 | COMR §4.24 | comr | spec |
| Encryption method registration | n/a | ENCR §4.26 | ENCR §4.25 | encr | spec |
| Group identification registration | n/a | GRID §4.27 | GRID §4.26 | grid | spec |
| Private frame | n/a | PRIV §4.28 | PRIV §4.27 | priv | spec |
| Signature frame | n/a | n/a | SIGN §4.28 | sign | spec |
| Seek frame | n/a | n/a | SEEK §4.29 | seek | spec |
| Audio seek point index | n/a | n/a | ASPI §4.30 | aspi | spec |
| Chapter | n/a | CHAP §3.1 | CHAP §3.1 | chap | chapters addendum |
| Table of contents | n/a | CTOC §3.2 | CTOC §3.2 | ctoc | chapters addendum |
| Audio-text | n/a | ATXT §4 | ATXT §4 | atxt | accessibility addendum |
| iTunes compilation flag | TCP | TCMP | TCMP | text | unofficial |
| iTunes album artist sort order | TS2 | TSO2 | TSO2 | text | unofficial |
| iTunes composer sort order | TSC | TSOC | TSOC | text | unofficial |
| iTunes title sort order | TST | TSOT | TSOT | text | unofficial |
| iTunes performer sort order | TSP | TSOP | TSOP | text | unofficial |
| iTunes album sort order | TSA | TSOA | TSOA | text | unofficial |
| Experimental RVA2 | n/a | XRVA | n/a | rva2 | unofficial |
| Replay Gain Adjustment | n/a | RGAD | RGAD | rgad | unofficial |
ID3v1 genres
| Index | Genre | Defined by |
|---|---|---|
| 0 | Blues | ID3v1 (v2.4 Appendix A) |
| 1 | Classic Rock | ID3v1 (v2.4 Appendix A) |
| 2 | Country | ID3v1 (v2.4 Appendix A) |
| 3 | Dance | ID3v1 (v2.4 Appendix A) |
| 4 | Disco | ID3v1 (v2.4 Appendix A) |
| 5 | Funk | ID3v1 (v2.4 Appendix A) |
| 6 | Grunge | ID3v1 (v2.4 Appendix A) |
| 7 | Hip-Hop | ID3v1 (v2.4 Appendix A) |
| 8 | Jazz | ID3v1 (v2.4 Appendix A) |
| 9 | Metal | ID3v1 (v2.4 Appendix A) |
| 10 | New Age | ID3v1 (v2.4 Appendix A) |
| 11 | Oldies | ID3v1 (v2.4 Appendix A) |
| 12 | Other | ID3v1 (v2.4 Appendix A) |
| 13 | Pop | ID3v1 (v2.4 Appendix A) |
| 14 | R&B | ID3v1 (v2.4 Appendix A) |
| 15 | Rap | ID3v1 (v2.4 Appendix A) |
| 16 | Reggae | ID3v1 (v2.4 Appendix A) |
| 17 | Rock | ID3v1 (v2.4 Appendix A) |
| 18 | Techno | ID3v1 (v2.4 Appendix A) |
| 19 | Industrial | ID3v1 (v2.4 Appendix A) |
| 20 | Alternative | ID3v1 (v2.4 Appendix A) |
| 21 | Ska | ID3v1 (v2.4 Appendix A) |
| 22 | Death Metal | ID3v1 (v2.4 Appendix A) |
| 23 | Pranks | ID3v1 (v2.4 Appendix A) |
| 24 | Soundtrack | ID3v1 (v2.4 Appendix A) |
| 25 | Euro-Techno | ID3v1 (v2.4 Appendix A) |
| 26 | Ambient | ID3v1 (v2.4 Appendix A) |
| 27 | Trip-Hop | ID3v1 (v2.4 Appendix A) |
| 28 | Vocal | ID3v1 (v2.4 Appendix A) |
| 29 | Jazz+Funk | ID3v1 (v2.4 Appendix A) |
| 30 | Fusion | ID3v1 (v2.4 Appendix A) |
| 31 | Trance | ID3v1 (v2.4 Appendix A) |
| 32 | Classical | ID3v1 (v2.4 Appendix A) |
| 33 | Instrumental | ID3v1 (v2.4 Appendix A) |
| 34 | Acid | ID3v1 (v2.4 Appendix A) |
| 35 | House | ID3v1 (v2.4 Appendix A) |
| 36 | Game | ID3v1 (v2.4 Appendix A) |
| 37 | Sound Clip | ID3v1 (v2.4 Appendix A) |
| 38 | Gospel | ID3v1 (v2.4 Appendix A) |
| 39 | Noise | ID3v1 (v2.4 Appendix A) |
| 40 | AlternRock | ID3v1 (v2.4 Appendix A) |
| 41 | Bass | ID3v1 (v2.4 Appendix A) |
| 42 | Soul | ID3v1 (v2.4 Appendix A) |
| 43 | Punk | ID3v1 (v2.4 Appendix A) |
| 44 | Space | ID3v1 (v2.4 Appendix A) |
| 45 | Meditative | ID3v1 (v2.4 Appendix A) |
| 46 | Instrumental Pop | ID3v1 (v2.4 Appendix A) |
| 47 | Instrumental Rock | ID3v1 (v2.4 Appendix A) |
| 48 | Ethnic | ID3v1 (v2.4 Appendix A) |
| 49 | Gothic | ID3v1 (v2.4 Appendix A) |
| 50 | Darkwave | ID3v1 (v2.4 Appendix A) |
| 51 | Techno-Industrial | ID3v1 (v2.4 Appendix A) |
| 52 | Electronic | ID3v1 (v2.4 Appendix A) |
| 53 | Pop-Folk | ID3v1 (v2.4 Appendix A) |
| 54 | Eurodance | ID3v1 (v2.4 Appendix A) |
| 55 | Dream | ID3v1 (v2.4 Appendix A) |
| 56 | Southern Rock | ID3v1 (v2.4 Appendix A) |
| 57 | Comedy | ID3v1 (v2.4 Appendix A) |
| 58 | Cult | ID3v1 (v2.4 Appendix A) |
| 59 | Gangsta | ID3v1 (v2.4 Appendix A) |
| 60 | Top 40 | ID3v1 (v2.4 Appendix A) |
| 61 | Christian Rap | ID3v1 (v2.4 Appendix A) |
| 62 | Pop/Funk | ID3v1 (v2.4 Appendix A) |
| 63 | Jungle | ID3v1 (v2.4 Appendix A) |
| 64 | Native American | ID3v1 (v2.4 Appendix A) |
| 65 | Cabaret | ID3v1 (v2.4 Appendix A) |
| 66 | New Wave | ID3v1 (v2.4 Appendix A) |
| 67 | Psychedelic | ID3v1 (v2.4 Appendix A) |
| 68 | Rave | ID3v1 (v2.4 Appendix A) |
| 69 | Showtunes | ID3v1 (v2.4 Appendix A) |
| 70 | Trailer | ID3v1 (v2.4 Appendix A) |
| 71 | Lo-Fi | ID3v1 (v2.4 Appendix A) |
| 72 | Tribal | ID3v1 (v2.4 Appendix A) |
| 73 | Acid Punk | ID3v1 (v2.4 Appendix A) |
| 74 | Acid Jazz | ID3v1 (v2.4 Appendix A) |
| 75 | Polka | ID3v1 (v2.4 Appendix A) |
| 76 | Retro | ID3v1 (v2.4 Appendix A) |
| 77 | Musical | ID3v1 (v2.4 Appendix A) |
| 78 | Rock & Roll | ID3v1 (v2.4 Appendix A) |
| 79 | Hard Rock | ID3v1 (v2.4 Appendix A) |
| 80 | Folk | Winamp extension (v2.3 Appendix A) |
| 81 | Folk-Rock | Winamp extension (v2.3 Appendix A) |
| 82 | National Folk | Winamp extension (v2.3 Appendix A) |
| 83 | Swing | Winamp extension (v2.3 Appendix A) |
| 84 | Fast Fusion | Winamp extension (v2.3 Appendix A) |
| 85 | Bebob | Winamp extension (v2.3 Appendix A) |
| 86 | Latin | Winamp extension (v2.3 Appendix A) |
| 87 | Revival | Winamp extension (v2.3 Appendix A) |
| 88 | Celtic | Winamp extension (v2.3 Appendix A) |
| 89 | Bluegrass | Winamp extension (v2.3 Appendix A) |
| 90 | Avantgarde | Winamp extension (v2.3 Appendix A) |
| 91 | Gothic Rock | Winamp extension (v2.3 Appendix A) |
| 92 | Progressive Rock | Winamp extension (v2.3 Appendix A) |
| 93 | Psychedelic Rock | Winamp extension (v2.3 Appendix A) |
| 94 | Symphonic Rock | Winamp extension (v2.3 Appendix A) |
| 95 | Slow Rock | Winamp extension (v2.3 Appendix A) |
| 96 | Big Band | Winamp extension (v2.3 Appendix A) |
| 97 | Chorus | Winamp extension (v2.3 Appendix A) |
| 98 | Easy Listening | Winamp extension (v2.3 Appendix A) |
| 99 | Acoustic | Winamp extension (v2.3 Appendix A) |
| 100 | Humour | Winamp extension (v2.3 Appendix A) |
| 101 | Speech | Winamp extension (v2.3 Appendix A) |
| 102 | Chanson | Winamp extension (v2.3 Appendix A) |
| 103 | Opera | Winamp extension (v2.3 Appendix A) |
| 104 | Chamber Music | Winamp extension (v2.3 Appendix A) |
| 105 | Sonata | Winamp extension (v2.3 Appendix A) |
| 106 | Symphony | Winamp extension (v2.3 Appendix A) |
| 107 | Booty Bass | Winamp extension (v2.3 Appendix A) |
| 108 | Primus | Winamp extension (v2.3 Appendix A) |
| 109 | Porn Groove | Winamp extension (v2.3 Appendix A) |
| 110 | Satire | Winamp extension (v2.3 Appendix A) |
| 111 | Slow Jam | Winamp extension (v2.3 Appendix A) |
| 112 | Club | Winamp extension (v2.3 Appendix A) |
| 113 | Tango | Winamp extension (v2.3 Appendix A) |
| 114 | Samba | Winamp extension (v2.3 Appendix A) |
| 115 | Folklore | Winamp extension (v2.3 Appendix A) |
| 116 | Ballad | Winamp extension (v2.3 Appendix A) |
| 117 | Power Ballad | Winamp extension (v2.3 Appendix A) |
| 118 | Rhythmic Soul | Winamp extension (v2.3 Appendix A) |
| 119 | Freestyle | Winamp extension (v2.3 Appendix A) |
| 120 | Duet | Winamp extension (v2.3 Appendix A) |
| 121 | Punk Rock | Winamp extension (v2.3 Appendix A) |
| 122 | Drum Solo | Winamp extension (v2.3 Appendix A) |
| 123 | Acapella | Winamp extension (v2.3 Appendix A) |
| 124 | Euro-House | Winamp extension (v2.3 Appendix A) |
| 125 | Dance Hall | Winamp extension (v2.3 Appendix A) |
| 126 | Goa | Winamp, named only in the ID3v1 test suite |
| 127 | Drum & Bass | Winamp, named only in the ID3v1 test suite |
| 128 | Club-House | Winamp, named only in the ID3v1 test suite |
| 129 | Hardcore | Winamp, named only in the ID3v1 test suite |
| 130 | Terror | Winamp, named only in the ID3v1 test suite |
| 131 | Indie | Winamp, named only in the ID3v1 test suite |
| 132 | BritPop | Winamp, named only in the ID3v1 test suite |
| 133 | Negerpunk | Winamp, named only in the ID3v1 test suite |
| 134 | Polsk Punk | Winamp, named only in the ID3v1 test suite |
| 135 | Beat | Winamp, named only in the ID3v1 test suite |
| 136 | Christian | Winamp, named only in the ID3v1 test suite |
| 137 | Heavy Metal | Winamp, named only in the ID3v1 test suite |
| 138 | Black Metal | Winamp, named only in the ID3v1 test suite |
| 139 | Crossover | Winamp, named only in the ID3v1 test suite |
| 140 | Contemporary | Winamp, named only in the ID3v1 test suite |
| 141 | Christian Rock | Winamp, named only in the ID3v1 test suite |
| 142 | Merengue | Winamp, named only in the ID3v1 test suite |
| 143 | Salsa | Winamp, named only in the ID3v1 test suite |
| 144 | Thrash Metal | Winamp, named only in the ID3v1 test suite |
| 145 | Anime | Winamp, named only in the ID3v1 test suite |
| 146 | JPop | Winamp, named only in the ID3v1 test suite |
| 147 | Synthpop | Winamp, named only in the ID3v1 test suite |
How tags are built
The byte layout of every structure the library reads and writes, as the specs define it. Sizes are in bytes; BE and LE mean big- and little-endian. The playground's byte map shows these regions in your own files.
ID3v2
| Offset | Size | Field | Value |
|---|---|---|---|
| 0 | 3 | Identifier | "ID3" (an appended v2.4 tag ends with a footer that starts "3DI") |
| 3 | 2 | Version | Major (2, 3 or 4), then revision |
| 5 | 1 | Flags | v2.2: unsynchronisation, compression. v2.3: unsynchronisation, extended header, experimental. v2.4: those and footer. |
| 6 | 4 | Size | Synchsafe: 7 bits per byte, the top bit always 0. Excludes the header (and footer). |
Frame headers: v2.2 is ID (3) · size (3); v2.3 is ID (4) · size (4, plain BE) · flags (2); v2.4 is ID (4) · size (4, synchsafe) · flags (2).
| Frame | Body |
|---|---|
Text (T***) | Encoding (1) · text. v2.4 separates several values with a NUL. |
TXXX | Encoding (1) · description · NUL · value |
COMM, USLT | Encoding (1) · language (3, ISO 639-2) · description · NUL · text |
APIC | Encoding (1) · MIME type · NUL · picture type (1) · description · NUL · image data |
W*** | URL in ISO-8859-1 |
Text encodings: $00 ISO-8859-1, $01 UTF-16 with BOM, and in v2.4 also $02 UTF-16BE and $03 UTF-8.
ID3v1 · Lyrics3
| Offset | Size | Field |
|---|---|---|
| 0 | 3 | "TAG" |
| 3 | 30 | Title |
| 33 | 30 | Artist |
| 63 | 30 | Album |
| 93 | 4 | Year |
| 97 | 30 | Comment. In v1.1: comment (28) · NUL · track number (1) |
| 127 | 1 | Genre index (0 to 147; 255 = none). See the genre list. |
Lyrics3 sits just before the ID3v1 tag: v1 is "LYRICSBEGIN" · lyrics · "LYRICSEND"; v2.00 is "LYRICSBEGIN" · fields (3-letter ID, 5-digit size, data) · size of the tag (6 digits) · "LYRICS200".
MP4
Every atom is size (4, BE, including the header) · type (4) · data. The iTunes items live in moov/udta/meta/ilst (handler mdir), one atom per item, each with a data atom: type (4) · locale (4) · value. Freeform items (----) add mean and name atoms. When the metadata grows and no free space is left, every chunk offset in stco (32-bit) and co64 (64-bit) is updated so the audio is still found.
FLAC · Vorbis
A FLAC file starts with "fLaC", then metadata blocks (header: last-block flag (1 bit) · type (7 bits) · length (24 bits, BE)), then the audio frames. A Vorbis comment is vendor length (4, LE) · vendor · number of fields (4, LE) · each field: length (4, LE) · NAME=value in UTF-8.
Ogg
Each page is "OggS" · version · header type · granule position (8, LE) · serial (4) · sequence (4) · CRC-32 (4) · number of segments · segment table, then the data. The comment packet is the codec's second header packet: 0x03 "vorbis" for Vorbis, "OpusTags" for Opus, a VORBIS_COMMENT block for FLAC in Ogg.
WAV
"RIFF" · size (4, LE) · "WAVE" · chunks: ID (4) · size (4, LE) · data, plus a pad byte when the size is odd. fmt holds the format, data the audio, LIST (type INFO) the text tags, id3 a whole ID3v2 tag.
AIFF
"FORM" · size (4, BE) · "AIFF" or "AIFC" · chunks: ID (4) · size (4, BE) · data, plus a pad byte when the size is odd. COMM holds channels, sample frames, sample size and rate, SSND the audio, NAME/AUTH/(c) /ANNO/COMT the text, ID3 a whole ID3v2 tag.
Low-level ID3 API
Build, validate, convert and serialize ID3v2 tags frame by frame. Every frame type is a member of a discriminated union (frame.type), with fields named as in the spec.
import { createTag, createFrame, TextEncoding, validateID3v2, writeID3v2, readID3v2, convertID3v2 } from 'audio-tag'
const tag = createTag(4, [
createFrame('text', 'TIT2', { encoding: TextEncoding.UTF8, values: ['Title'] }),
])
const issues = validateID3v2(tag) // [] when valid; each issue cites its section
const { bytes } = writeID3v2(tag, { padding: 1024 })
const parsed = readID3v2(bytes) // { tag, warnings, totalSize }
const { tag: v23 } = convertID3v2(tag, 3) // TDRC -> TYER/TDAT/TIME, UTF-8 -> UTF-16Bundle sizes
Each bundle loads on its own, raw and gzipped as served. Importing only the functions you need lets a bundler drop the other formats; npm run size measures single imports against their budgets.
| File | Size | gzip |
|---|---|---|
dist/browser.min.js | 194.8 KB | 67.7 KB |
dist/cjs/browser.cjs | 324.0 KB | 85.7 KB |
dist/cjs/browser.min.cjs | 195.5 KB | 68.0 KB |
dist/cjs/index.cjs | 320.9 KB | 84.3 KB |
dist/cjs/index.min.cjs | 194.1 KB | 67.0 KB |
dist/cjs/node.cjs | 325.5 KB | 86.0 KB |
dist/cjs/node.min.cjs | 199.6 KB | 69.4 KB |
dist/index.min.js | 193.4 KB | 66.8 KB |
dist/node.min.js | 195.7 KB | 68.0 KB |
| ESM modules (tsc) (76 files) | 456.8 KB | |
| Type declarations (79 files) | 265.5 KB | |
| Source maps (161 files) | 8252.0 KB | |
| Everything in dist/ (325 files) | 11117.8 KB |
Build info
Each build writes dist/build-info.json: the version, the git commit, the build time and the byte sizes above. This page shows version 0.1.0, built 2026-10-10.