The Principal Dev – Masterclass for Tech Leads

The Principal Dev – Masterclass for Tech Leads28-29 May

Join

tinytag

tinytag is a Python library for reading audio file metadata

Build Status PyPI Version PyPI Downloads

Install

python3 -m pip install tinytag

Features

[!IMPORTANT]
Support for changing/writing metadata will not be added. Use another library such as Mutagen for this.

Usage

tinytag only provides the minimum needed for reading metadata, and presents it in a simple format. It can determine track number, total tracks, title, artist, album, year, duration and more.

from tinytag import TinyTag
tag: TinyTag = TinyTag.get('/some/music.mp3')

print(f'This track is by {tag.artist}.')
print(f'It is {tag.duration:.2f} seconds long.')

[!WARNING]
The ignore_errors parameter of TinyTag.get() is obsolete as of tinytag 2.0.0, and will be removed in the future.

Alternatively you can use tinytag directly on the command line:

$ python3 -m tinytag /some/music.mp3
{
  "filename": "/some/music.mp3",
  "filesize": 3243226,
  "mime_type": "audio/mpeg",
  "duration": 173.52,
  "channels": 2,
  "bitrate": 128,
  "samplerate": 44100,
  "artist": [
    "artist name"
  ],
  "album": [
    "album name"
  ],
  "title": [
    "track name"
  ],
  "track": [
    "4"
  ],
  "genre": [
    "Jazz"
  ],
  "year": [
    "2010"
  ],
  "comment": [
    "Some comment here"
  ]
}

Check python3 -m tinytag --help for all CLI options, for example other output formats.

Supported Files

To receive a tuple of file extensions tinytag supports, use the SUPPORTED_FILE_EXTENSIONS constant:

TinyTag.SUPPORTED_FILE_EXTENSIONS

Alternatively, check if a file is supported by providing its path:

is_supported = TinyTag.is_supported('/some/music.mp3')

Common Metadata

tinytag provides some common attributes, which always contain a single value. These are helpful when you need quick access to common metadata.

File/Audio Properties

tag.filename: str | None         # file name
tag.filesize: int                # file size in bytes
tag.bitdepth: int | None         # audio bit depth (for lossless audio)
tag.bitrate: float | None        # audio bitrate in kbps
tag.channels: int | None         # number of audio channels
tag.duration: float | None       # audio duration in seconds
tag.mime_type: str | None        # audio MIME type (added in tinytag 2.3.0) 
tag.samplerate: int | None       # audio samples per second

[!WARNING]
The tag.audio_offset attribute is obsolete as of tinytag 2.0.0, and will be removed in the future.

Metadata Fields

tag.album: str | None            # album name
tag.albumartist: str | None      # album artist name
tag.artist: str | None           # artist name
tag.comment: str | None          # file comment
tag.composer: str | None         # composer name
tag.disc: int | None             # disc number
tag.disc_total: int | None       # total number of discs
tag.genre: str | None            # genre
tag.title: str | None            # title
tag.track: int | None            # track number
tag.track_total: int | None      # total number of tracks
tag.year: str | None             # year/date

Audio MIME Types

At present, tinytag may return the audio MIME types documented in this section. When available, a codecs parameter as described in the RFC 6381 standard is included.

For standard codec values, see:

No official standards exists for codecs values for the audio/aiff and audio/x-ms-wma MIME types. The most appropriate value provided by the format is used.

audio/aiff
audio/aiff; codecs="<FourCC>"    # AIFF-C compression type, e.g. "alaw"
audio/flac
audio/mp4
audio/mp4; codecs="alac"
audio/mp4; codecs="mp4a.oo[.A]"  # E.g. "mp4a.40.2" for AAC-LC
audio/mpeg
audio/ogg
audio/ogg; codecs="flac"
audio/ogg; codecs="opus"
audio/ogg; codecs="speex"
audio/ogg; codecs="vorbis"
audio/wav
audio/wav; codecs="<1..>"        # WAVE format tag, e.g. "1" for PCM
audio/x-ms-wma
audio/x-ms-wma; codecs="<1..>"   # WAVE format tag, e.g. "353" for WMA v2

Additional Metadata

For additional values of the same field type, uncommon metadata fields, or metadata specific to certain file formats, use other:

tag.other: OtherFields           # a dictionary of additional fields

[!WARNING]
The other dictionary has replaced the extra dictionary in tinytag 2.0.0. The latter will be removed in a future release.

The following other field names are standardized in tinytag, and optionally present when files provide such metadata:

barcode
bpm
catalog_number
conductor
copyright
director
encoded_by
encoder_settings
grouping
initial_key
isrc
language
license
lyricist
lyrics
media
movement
movement_name
movement_total
publisher
set_subtitle
show_movement
url
work
xmp

Additional other field names not documented above may be present, but are format-specific and may change or disappear in future tinytag releases. If tinytag does not expose metadata you need, or you wish to standardize more field names, open a feature request on GitHub for discussion.

other values are always provided as strings, and are not guaranteed to be valid. Should e.g. the bpm value in the file contain non-numeric characters, tinytag will provide the string as-is. It is your responsibility to handle possible exceptions, e.g. when converting the value to an integer.

Multiple values of the same field type are provided if a file contains them. Values are always provided as a list, even when only a single value exists.

Example:

from tinytag import OtherFields, TinyTag

tag: TinyTag = TinyTag.get('/some/music.mp3')
other_fields: OtherFields = tag.other
catalog_numbers: list[str] | None = other_fields.get('catalog_number')

if catalog_numbers:
    catalog_number: str = catalog_numbers[0]
    print(catalog_number)

print(catalog_numbers)

Output:

> 10
> ['10']

When a file contains multiple values for a common metadata field (e.g. artist), the primary value is accessed through the common attribute (tag.artist), and any additional values through the other dictionary (tag.other['artist']).

Example:

from tinytag import TinyTag

tag: TinyTag = TinyTag.get('/some/music.mp3')
artist: str | None = tag.artist
additional_artists: list[str] | None = tag.other.get('artist')

print(artist)
print(additional_artists)

Output:

> main artist
> ['another artist', 'yet another artist']

All Metadata

If you need to receive all available metadata as key-value pairs in a flat dictionary, use the as_dict() method. This combines the common attributes and other dictionary, which can be more convenient in some cases.

from tinytag import TinyTag

tag: TinyTag = TinyTag.get('/some/music.mp3')
metadata: dict = tag.as_dict()

Images

Additionally, you can also read embedded images by passing a image=True keyword argument to TinyTag.get().

If you need to receive an image of a specific kind, including its description, use images:

tag.images: Images             # available embedded images

The following common image attributes are available, providing the first located Image object of each kind:

tag.images.front_cover: Image  # front cover
tag.images.back_cover: Image   # back cover
tag.images.media: Image        # media (e.g. CD label)

When present, any additional images are available in an images.other dictionary, using the following standardized key names:

generic
icon
alt_icon
front_cover
back_cover
media
leaflet
lead_artist
artist
conductor
band
composer
lyricist
recording_location
during_recording
during_performance
screen_capture
bright_colored_fish
illustration
band_logo
publisher_logo
unknown

Provided values are always lists containing at least one Image object.

The Image object provides the following attributes:

image.data: bytes               # image data
image.size: int                 # image size in bytes (added in tinytag 2.3.0) 
image.name: str                 # image name/kind
image.mime_type: str | None     # image MIME type
image.description: str | None   # image description

To receive any available image, prioritizing the front cover, use images.any:

from tinytag import Image, TinyTag

tag: TinyTag = TinyTag.get('/some/music.ogg', image=True)
image: Image | None = tag.images.any

if image is not None:
    data: bytes = image.data
    size: int = image.size
    name: str = image.name
    mime_type: str | None = image.mime_type
    description: str | None = image.description

    print(len(data))
    print(size)
    print(name)
    print(mime_type)
    print(description)

Output:

> 74452
> 74452
> front_cover
> image/jpeg
> some image description

[!WARNING]
tag.images.any has replaced tag.get_image() in tinytag 2.0.0. tag.get_image() will be removed in the future.

To receive a common image, e.g. front_cover:

from tinytag import Image, Images, TinyTag

tag: TinyTag = TinyTag.get('/some/music.ogg', image=True)
images: Images = tag.images
cover_image: Image = images.front_cover

if cover_image is not None:
    data: bytes = cover_image.data
    description: str | None = cover_image.description

To receive an additional image, e.g. bright_colored_fish:

from tinytag import Image, OtherImages, TinyTag

tag: TinyTag = TinyTag.get('/some/music.ogg', image=True)
other_images: OtherImages = tag.images.other
fish_images: list[Image] | None = other_images.get('bright_colored_fish')

if fish_images:
    image = fish_images[0]  # Use first image
    data = image.data
    description = image.description

Magic Header Detection

By default, tinytag will determine the file type by 1. checking the file name extension, and 2. reading and inspecting the file header, i.e. magic header detection.

In case you want to disable magic header detection, e.g. to minimize read operations when many non-audio files exist in a folder, pass a header_detection argument with a value of False (added in tinytag 2.3.0).

tag: TinyTag = TinyTag.get('invalid_file.jpg', header_detection=False)

Encoding

To open files using a specific encoding, you can use the encoding parameter. This parameter is however only used for formats where the encoding is not explicitly specified.

tag: TinyTag = TinyTag.get('a_file_with_gbk_encoding.mp3', encoding='gbk')

File-like Objects

To use a file-like object (e.g. BytesIO) instead of a file path, pass a file_obj keyword argument:

tag: TinyTag = TinyTag.get(file_obj=your_file_obj)

Exceptions

TinyTagException        # Base class for exceptions
ParseError              # Parsing an audio file failed
UnsupportedFormatError  # File format is not supported

Changelog

2.2.1 (2026-03-15)

2.2.0 (2025-12-15)

2.1.2 (2025-08-14)

2.1.1 (2025-04-23)

2.1.0 (2025-02-23)

2.0.0 (2024-11-03)

1.10.1 (2023-10-26)

1.10.0 (2023-10-18)

1.9.0 (2023-04-23)

1.8.1 (2022-03-12) [still mathiascode-edition]

1.8.0 (2022-03-05) [mathiascode-edition]

1.7.0. (2021-12-14)

1.6.0 (2021-08-28) [aw-edition]

1.5.0 (2020-11-05)

1.4.0 (2020-04-23)

1.3.0 (2020-03-09)

1.2.2 (2019-04-13)

1.2.1 (2019-04-13)

1.2.0 (2019-04-13)

1.1.0 (2019-04-13)

1.0.1 (2019-04-13)

1.0.0 (2018-12-12)

0.19.0 (2018-02-11)

0.18.0 (2017-04-29)

0.17.0 (2016-10-02)

0.16.0 (2016-08-06)

0.15.2 (2016-08-06)

0.15.0 (2016-08-06)

0.14.0 (2016-06-05):

Join libs.tech

...and unlock some superpowers

GitHub

We won't share your data with anyone else.