Gamdl
Glomatico's Apple Music Downloader
Gamdl is a command-line app for downloading Apple Music songs, albums, playlists, music videos, and uploaded videos. It combines an interactive terminal interface with configurable codecs, metadata tagging, and library organization.
Join our Discord server: https://discord.gg/aBjMEZ9tnq
Contents
- ✨ Features
- 📋 Prerequisites
- 📦 Installation
- 🚀 First Run
- 🚀 Usage
- ⚙️ Configuration
- 🏷️ Tags and Path Templates
- 🔄 Migrating from Gamdl 3.x
- 🐍 Python API
- 🛠️ Troubleshooting
- 🤝 Contributing
- 📄 License
✨ Features
- 🎵 Music downloads — Songs, albums, playlists, artists, and your personal Apple Music library.
- 🎬 Video downloads — Music videos and uploaded/post videos, with quality and stream selection.
- 🎧 Multiple codecs — AAC, ALAC, Dolby Atmos, H.264, H.265, and more, when available for the selected media.
- 📝 Lyrics and metadata — Embedded tags, artwork, and optional lyrics and playlist files.
- 🖥️ Interactive interface — Full-screen selection menus and live download progress.
- 🗂️ Library tools — Customizable paths, an optional SQLite media index, and an offline organizer.
📋 Prerequisites
- Python 3.10 or newer. A Rust toolchain is also needed if your platform must build Gamdl's native extension from source.
- An Apple Music account. An active subscription is generally required to access subscription playback streams.
- An authentication method: Wrapper, browser cookies, or a Media User Token.
- A compatible DRM backend for protected streams. Install the appropriate optional dependency as described below.
Codec and resolution availability varies by track, account, authentication method, and DRM capabilities.
📦 Installation
Recommended: Install Gamdl with the Widevine extra from PyPI. It includes a built-in Widevine L3 device, so you don't need to provide a separate device file for standard downloads:
python -m pip install "gamdl[widevine]"
If you prefer PlayReady, install its extra instead:
python -m pip install "gamdl[playready]"
PlayReady does not include a device. You must supply your own compatible .prd file using --device-path or auth.device_path in your configuration. For videos above 1080p, see Video Codec and Resolution.
The base package can also be installed with python -m pip install gamdl, but protected streams require a supported DRM setup or a compatible wrapper. After installation, check the CLI with:
gamdl --help
If a prebuilt wheel is not available for your platform, installing from source requires Rust and the native build dependencies.
🚀 First Run
After installing Gamdl, you can start a download right away:
gamdl rip "https://music.apple.com/us/album/never-gonna-give-you-up-2022-remaster/1624945511?i=1624945512"
If this is your first run, Gamdl will guide you through any settings you haven't configured yet:
- Authentication: Choose Wrapper, Cookies, or Media User Token. Follow the on-screen instructions to connect your Apple Music account. See Authentication for details about each method.
- Output directory: Choose where your downloads will be saved. Gamdl suggests your operating system's Music folder; press Enter to accept it or enter a different path.
Once setup is complete, Gamdl begins downloading and displays progress in the terminal. It saves your choices in ~/.gamdl/config.yml, so these prompts won't appear again unless you clear the corresponding settings.
You can change authentication later with gamdl auth, or override the download folder for one command with --output-dir PATH. For scripts and other non-interactive environments, configure authentication and the output directory beforehand; the setup wizards require an interactive terminal.
🚀 Usage
Gamdl uses subcommands. Run gamdl --help for the command list or gamdl <command> --help to see its options.
Download URLs (rip)
Download an Apple Music song, album, playlist, music video, or artist URL:
gamdl rip "https://music.apple.com/us/album/never-gonna-give-you-up-2022-remaster/1624945511?i=1624945512"
Multiple URLs can be downloaded in one invocation:
gamdl rip "<first Apple Music URL>" "<second Apple Music URL>"
Catalog and library sharing links, including Apple Music Classical links, are supported where their corresponding media can be resolved. For artist links, Gamdl opens the artist browser or you can specify categories automatically:
gamdl rip "<artist URL>" --artist-auto-select main-albums,music-videos
Add --select to choose album or playlist tracks interactively instead of using the default automatic selection.
ISRC Input
Download a song or music video using its 12-character International Standard Recording Code (ISRC) without looking up an Apple Music sharing URL:
gamdl rip isrc:USUM71703085
isrc: queries both the song and music-video catalogs using Apple's filter[isrc] API. An ISRC can identify multiple catalog entries; if the lookup returns more than one match, Gamdl opens its existing selection interface so you can choose which to download. A single match is downloaded directly. Multiple matches require an interactive terminal.
The lookup uses the current authenticated storefront. Apple's response may reference alternate releases in meta.filters.isrc; for now Gamdl resolves only the returned data matches, not every alternate release ID. Empty results mean no matching resource was returned in that storefront.
Browse Your Library (library)
Browse your saved albums, playlists, songs, and music videos:
gamdl library
For automatic category selection without opening the browser:
gamdl library --library-auto-select albums,playlists
Search (search)
Search the Apple Music catalog and interactively select results:
gamdl search "Thriller" --type song
Switch between the authenticated Apple Music catalog search (default) and Apple's public iTunes Search API:
gamdl search "Caravan Palace" --search-api itunes
gamdl search "Caravan Palace" --search-api apple-music
Set the backend in YAML to make iTunes the default:
search:
api: itunes
Override it for a single command with --search-api. iTunes search supports songs,
music videos and albums, but not uploaded videos or playlists. Its public Search API
returns up to 200 results per category; Gamdl displays those in local pages
without relying on undocumented iTunes pagination. Selected items are then
resolved using authoritative Apple Music catalog metadata before download.
Apple documents an approximate iTunes Search API limit of 20 requests/minute;
changing backends doesn't remove throttling limits. Selecting an album expands
its tracks through the existing Apple Music album resolver:
gamdl search "Thriller" --search-api itunes --type album
Apple Music search also offers Playlists (editorial and external curators)
and User playlists (public, user-shared playlists). The latter are
identified by the catalog's playlistType: user-shared field; Apple's search
index may not return any for a particular term/storefront. Selecting a
playlist expands its tracks for download, just like opening a playlist link:
gamdl search "Michael Jackson" --type playlist
gamdl search "Michael Jackson" --type user-playlist
The Apple Music search endpoint does not accept uploaded-videos as a
search type (HTTP 400). Downloading a supported uploaded-video URL directly
with gamdl rip remains available.
Use --feeling-lucky with --type to select the first result automatically:
gamdl search "Thriller" --type song --feeling-lucky
Authentication (auth)
Authentication is configured automatically during the first run if you haven't selected a method yet. To change your method later, run:
gamdl auth
The wizard validates your selected method and saves it to the YAML configuration.
Wrapper
Connect to a running Wrapper v2 service. Gamdl can use its authenticated session and compatible playback/decryption features. The default wrapper URL is http://127.0.0.1.
Cookies
Export your cookies from Apple Music in Netscape cookies.txt format while signed in. The file must contain the media-user-token cookie. You can use a browser extension such as Export Cookies for Firefox or Get cookies.txt LOCALLY for Chromium.
Media User Token
Provide your Apple Music media-user-token directly through the wizard. Treat the token and your cookies file as passwords; never post them in issues or logs.
Advanced authentication settings are described under Configuration.
Maintain the Media Database (database)
The optional SQLite index stores information about downloaded files. You can inspect, scan, and prune its records:
gamdl database info
gamdl database scan --dry-run
gamdl database scan
gamdl database prune --dry-run
scan discovers supported local files using their embedded catalog IDs. prune removes database records for missing files, not media files; it asks for confirmation unless --yes is supplied.
Organize Existing Files (organize)
Organize local media using its embedded tags and your configured filename templates:
gamdl organize --dry-run
gamdl organize
The organizer can update database paths and relative M3U playlist references. It avoids overwriting occupied destinations. Review the dry run first, especially when changing templates.
When media paths change, organize repairs their references inside existing .m3u8 playlists without changing playlist names or metadata headers. For an already-organized library, use gamdl organize --playlists-only (or add --dry-run to preview path repairs).
Sync Apple Music Playlists (sync playlists)
Reconcile existing local .m3u8 playlists with their Apple Music catalog IDs, including new, removed, and reordered tracks:
gamdl sync playlists --dry-run
gamdl sync playlists --dry-run --verbose
gamdl sync playlists
gamdl sync playlists --no-download
gamdl sync playlists --playlist 'Playlists/Apple Music/Oliver Tree_ essenciais.m3u8'
Gamdl matches tracks by catalog ID using the local SQLite index and embedded media tags. The default output shows a concise table of only playlists that need attention; use --verbose to show all playlists and individual added/removed tracks. After fetching complete playlist listings, synchronization reports the number of unique missing tracks, then downloads them with the same per-track progress bars as rip and an overall completed/total bar. It respects download.concurrent_downloads (parallel tracks) and download.segment_concurrency (media segment requests per track), reusing shared tracks across playlists. Missing tracks are downloaded with your configured codec settings unless --no-download is used. Removed playlist entries never delete local media. Duplicate occurrences and ordered entries are preserved. Failed downloads or incomplete Apple Music responses leave each affected playlist unchanged; other playlists may still succeed. The command does not rename playlist files or alter existing metadata headers. Large removals require --yes after inspecting --dry-run.
Interactive Controls
| Key | Action |
|---|---|
| Arrow keys | Navigate options |
| Space | Toggle an item in a multi-select menu |
| Ctrl + A | Select all items where supported |
| Enter | Confirm or open the selected item |
⚙️ Configuration
Gamdl stores its configuration in a .gamdl folder inside your home directory (your user profile folder on Windows). For example:
Windows: C:\Users\<username>\.gamdl\config.yml
Linux: /home/<username>/.gamdl/config.yml
macOS: /Users/<username>/.gamdl/config.yml
Gamdl creates a configuration file automatically on first use when needed. To find its location, create one manually, or inspect the effective settings, use:
gamdl config path
gamdl config init
gamdl config show
gamdl config validate
CLI options override YAML values for the current command. You can specify another file with the top-level --config PATH option, or use --no-config to ignore your saved settings. Do not run config init --force unless you want to replace your existing file.
Option headings below show the YAML key / CLI flag where both exist. Options without a YAML key are marked as CLI-only.
Authentication Settings
Authentication Method (auth.mode / --auth-mode)
Choose wrapper, cookies, or media-user-token. The default is null, which opens the setup wizard when authentication is required.
Credentials and Wrapper Connection
auth.cookies_path / --cookies-path specifies the cookies file. auth.media_user_token / --media-user-token supplies a token directly. auth.wrapper_url / --wrapper-url sets the wrapper's HTTP address; auth.wrapper_decrypt_host / --wrapper-decrypt-host and auth.wrapper_decrypt_port / --wrapper-decrypt-port configure its decryption endpoint (default port 10020).
Avoid passing secrets on the command line when possible, as they may be recorded in shell history.
DRM Backend (auth.drm_backend / --drm-backend)
Choose widevine (default) or playready. For a custom provisioned device, use auth.device_path / --device-path. Widevine uses the bundled L3 device by default, while PlayReady requires a compatible .prd device file. For higher-security playback, provide an appropriately provisioned device. Protected media must also have suitable DRM signaling and licenses.
Storefront and Language (auth.storefront / --storefront, auth.language / --language)
Set the Apple Music storefront with a two-letter country code such as br, and the metadata language with a tag such as pt-BR. The storefront is normally detected from your account; the default language is en-US.
Song Downloads
Codec Priority (download.song_codec_priority / --song-codec-priority)
Select codecs in preference order. Gamdl tries the preferred formats based on the streams actually available for each track. Default: aac (AAC via HLS, compatible with Wrapper or Widevine/PlayReady).
download:
song_codec_priority:
- alac
- atmos
- aac
gamdl rip "<song URL>" --song-codec-priority alac,atmos,aac
Supported song codec identifiers are aac, aac-he, aac-binaural, aac-downmix, aac-he-binaural, aac-he-downmix, aac-web, aac-he-web, atmos, ac3, alac, alac-lossless, and alac-hires.
aacuses HLS and works with Wrapper or Widevine/PlayReady.aac-webuses the separate web-playback stream, which requires Widevine/PlayReady even when Wrapper is connected.alacautomatically chooses the highest-quality ALAC available: Hi-Res (above 48 kHz) first, then standard Lossless (up to 48 kHz). Within a tier it favors higher sample rates, then bit depths, then bitrates. Wrapper streams take precedence over Apple Music asset streams at the same tier. The actual downloaded codec is still recorded asalac-hiresoralac-lossless, notalac.alac-losslessandalac-hiresremain available when you want to request a specific tier. The tiers are identified from HLS audio-group metadata.
Song Codec Specifications
These are typical Apple Music profiles, not guaranteed specifications. Actual bitrates, sample rates, and available streams depend on the track and its HLS manifest; Gamdl discovers the available variants instead of enforcing these values.
| Codec | Typical bitrate | Audio characteristics |
|---|---|---|
aac |
256 kbps | AAC, up to 48 kHz; HLS |
aac-he |
64 kbps | HE-AAC, up to 48 kHz; HLS |
aac-binaural |
256 kbps | AAC binaural mix; HLS |
aac-downmix |
256 kbps | AAC downmix; HLS |
aac-he-binaural |
64 kbps | HE-AAC binaural mix; HLS |
aac-he-downmix |
64 kbps | HE-AAC downmix; HLS |
aac-web |
256 kbps | AAC, typically 44.1 kHz; web playback |
aac-he-web |
64 kbps | HE-AAC, typically 44.1 kHz; web playback |
atmos |
768 kbps | Dolby Atmos (E-AC-3 JOC); HLS |
ac3 |
640 kbps | Dolby Digital (AC-3); HLS |
alac |
Variable (lossless) | Best available ALAC tier; typically up to 24-bit/192 kHz |
alac-lossless |
Variable (lossless) | ALAC at 48 kHz or below; HLS |
alac-hires |
Variable (lossless) | ALAC above 48 kHz; HLS |
ALAC is lossless, so its bitrate varies with the audio. The alac option selects a concrete tier, not a new encoded format. --ask-song-codec opens an interactive stream selector; ask is not a codec identifier.
Gamdl warns after authentication when Apple Music reports account content restrictions, which may prevent some tracks from downloading. It also warns when ALAC is selected without Wrapper, because Apple Music may refuse Widevine/PlayReady licenses for lossless streams. These are informational warnings, not download blockers; interactive ALAC selection displays the warning when that codec is chosen.
Exact Codec (download.song_codec / --song-codec)
Request one specific codec instead of a fallback list. The default is null. Use --ask-song-codec (CLI-only) to choose a stream interactively; it requires a terminal.
For example, gamdl rip "<song URL>" --song-codec alac requests the best available ALAC tier without specifying a fallback to another format.
Lyrics (output.lyrics_file_format, output.embedded_lyrics_format)
Choose the lyrics representation independently for external sidecars and embedded metadata:
output:
lyrics_file_format: lrc
embedded_lyrics_format: text
Use --lyrics-file-format and --embedded-lyrics-format to override these settings. Both accept lrc, srt, ttml, text, and enhanced-lrc.
| Format | External extension | Behavior |
|---|---|---|
lrc |
.lrc |
Standard line timestamps |
enhanced-lrc |
.lrc |
Word/syllable timestamps when available; otherwise standard line LRC |
srt |
.srt |
Subtitle cues from lines with start and end timestamps |
ttml |
.ttml |
Original Apple Music TTML |
text |
.txt |
Plain lyrics without timing |
External files are strict: if the selected format cannot be produced, Gamdl reports the lyrics sidecar as unavailable rather than silently saving a different type. The only exception is enhanced-lrc degrading to line LRC when syllable timing is missing. Existing media is reused when only a sidecar needs to be created or refreshed; an existing sidecar with a different extension is not mistaken for the requested format.
Embedded lyrics use the standard ©lyr text metadata atom, even when formatted as LRC, SRT or TTML. If the requested embedded representation is unavailable, Gamdl falls back to line LRC when synchronized, then plain text. Some players display embedded timestamps or XML as literal text instead of synchronized lyrics, so text remains the default.
Sidecars are enabled by default (no_lyrics_file: false). Set output.no_lyrics_file: true or use --no-lyrics-file to disable external lyrics; to omit embedded lyrics, add lyrics to output.exclude_tags or use --exclude-tags lyrics. --no-tag also disables embedded lyrics. These controls are independent of the format settings.
Music Videos and Uploaded Videos
Codec Priority (download.music_video_codec_priority / --music-video-codec-priority)
Set the order for video codecs: h264 or h265. Default: h264, then h265.
download:
music_video_codec_priority:
- h265
- h264
gamdl rip "<music video URL>" --music-video-codec-priority h265,h264
Video Codec and Resolution (download.music_video_codec / --music-video-codec, download.max_height / --max-height)
Select an exact video codec, or keep null to use the priority list. The maximum requested height defaults to 1080 pixels; higher resolutions depend on stream availability and your DRM capabilities. Use --ask-music-video-streams (CLI-only) to select audio and video streams interactively.
Videos above 1080p require a Widevine L1 or PlayReady SL3000 (SL3K) device. The bundled Widevine device is L3 and does not meet that requirement. Provide an appropriately provisioned device with --device-path (or auth.device_path) if you increase --max-height beyond 1080. Gamdl warns when it detects an insufficient device security level; the warning does not prevent downloading, and a higher security level alone does not guarantee a compatible license or stream.
Historically, Apple Music has offered the following music-video resolutions:
| Codec | Typical resolutions |
|---|---|
h264 (AVC) |
240p, 360p, 480p, 540p, 720p, 1080p |
h265 (HEVC) |
Up to 2160p, including 1440p and 2160p variants |
These are examples, not a fixed list enforced by Gamdl. Gamdl selects from the resolutions and bitrates advertised in the video's HLS manifest, respecting --max-height. The default 1080p limit excludes higher resolutions until you raise it.
Music Video Audio Selection
For music videos, Gamdl automatically selects the highest-bitrate AAC track available. If no AAC rendition is available, it falls back to the highest-bitrate HE-AAC track. It never automatically selects Dolby Atmos or AC-3, even if those are marked as the default audio tracks in the HLS manifest.
Audio may come from a different audio group than the chosen video variant. When needed, Gamdl reads audio playlist metadata to estimate bitrate without downloading media segments. If an audio bitrate cannot be determined, the playlist's default designation and stereo group are used as tiebreakers. If neither AAC nor HE-AAC is available, automatic selection reports an unavailable stream rather than choosing a surround codec. To select an audio stream manually (including Atmos or AC-3), use --ask-music-video-streams.
Music Video Container (output.music_video_container / --music-video-container)
Music videos are saved as .m4v files by default, with M4V branding. Select mp4 to save .mp4 files with mp42 branding instead; audio and video are still muxed losslessly. This setting does not affect songs or uploaded videos.
output:
music_video_container: mp4
gamdl rip "<music video URL>" --music-video-container mp4
Uploaded Video Quality (download.uploaded_video_quality / --uploaded-video-quality)
Choose an uploaded video's asset variant when you need to override automatic quality selection. Use --ask-uploaded-video-quality (CLI-only) for an interactive choice.
The available identifiers, in the default preference order, are:
| Identifier | Apple Music asset variant |
|---|---|
1080pHdVideo |
1080p HD |
720pHdVideo |
720p HD |
sdVideoWithPlusAudio |
Standard definition with enhanced audio |
sdVideo |
Standard definition |
sd480pVideo |
480p SD |
provisionalUploadVideo |
Provisional upload |
These are Apple Music asset names, not guaranteed resolutions or bitrates. Gamdl uses the best available variant in this order unless you select a specific one.
Download Behavior
Download Concurrency (download.segment_concurrency / --segment-concurrency, download.concurrent_downloads / --concurrent-downloads)
segment_concurrency controls parallel media-segment HTTP requests for an individual track (default: 8); it does not directly limit Apple Music metadata or playback API requests. concurrent_downloads controls how many media items download simultaneously (default: 2). Higher parallelism can indirectly result in overlapping API calls.
Existing Files (download.overwrite / --overwrite)
Existing files are skipped by default (download.overwrite: false). Use the --overwrite flag or set download.overwrite: true to replace them. --no-overwrite overrides a YAML true value for one command. Songs use their configured filename directly; music videos can receive numbered suffixes (Title 2.m4v) to avoid filename collisions.
Error Handling (download.fail_fast / --fail-fast)
The default is to continue processing remaining items after individual failures (fail_fast: false). Set download.fail_fast: true or use --fail-fast to stop after an error.
For rip, library, search, and sync playlists, expected Gamdl errors are reported as short messages without tracebacks. Unexpected exceptions (including DRM license failures and malformed API responses) are collected and printed with full Python tracebacks after the final results, once progress bars have closed. Use --no-tracebacks (or ui.no_tracebacks: true in YAML) to suppress tracebacks while keeping concise failure messages. Tracebacks may contain signed URLs, tokens, or account details; inspect them before sharing logs.
Automatic Selection (download.artist_auto_select / --artist-auto-select, download.library_auto_select / --library-auto-select)
Choose artist categories such as main-albums, singles-eps, top-songs, and music-videos, or library categories such as albums, playlists, songs, and music-videos. CLI values are comma-separated; YAML values are lists. Both options default to empty lists, meaning their respective browsers are used.
Metadata and Artwork
Tagging (output.no_tag / --no-tag, --tag)
Metadata tagging is enabled by default (output.no_tag: false). Use --no-tag to skip writing metadata tags for one command, or --tag to enable them even when disabled in YAML.
Excluded Tags (output.exclude_tags / --exclude-tags)
Exclude specific metadata fields, including cover, without disabling all tagging. Configure a YAML list or use comma-separated names on the CLI:
output:
no_tag: false
exclude_tags:
- comment
- title_sort
- cover
gamdl rip "<song URL>" --exclude-tags comment,title_sort,cover
See Tags and Path Templates for every accepted exclusion name, including fields that use different names in path templates.
Artwork (output.save_cover / --save-cover, output.cover_format / --cover-format)
Embedded artwork is normally included when tagging is enabled. Saving a separate artwork file is disabled by default. Choose jpg (default) or png for cover format.
Files and Folders
Output Directory (output.directory / --output-dir)
The first time you download media, output.directory is null, so Gamdl asks where to save your music and remembers your choice in config.yml. The suggested folder is the Music directory of your operating system's user profile, detected through platformdirs (including relocated Music folders on Windows and XDG music directories on Linux). Press Enter to accept it, or enter another location.
Use --output-dir PATH to bypass the prompt and override the destination for a command, or set output.directory directly in YAML. Non-interactive downloads require one of these explicit paths. output.temp_path / --temp-path optionally selects a working directory for temporary download files.
Filename Templates (output.*_template / matching CLI options)
Configure album, compilation, no-album, playlist, and filename templates. Each has a corresponding CLI flag, such as --album-folder-template or --single-disc-file-template.
output:
album_folder_template: "{album_artist}/{album}"
single_disc_file_template: "{track:02d} {title}"
multi_disc_file_template: "{disc}-{track:02d} {title}"
playlist_folder_template: "Playlists/{playlist_artist}"
The complete list of supported placeholders, their meanings, and the corresponding tag names is in Tags and Path Templates.
Use output.truncate / --truncate to limit filename component length when needed.
Playlists
Save Playlists (output.save_playlist / --save-playlist)
Enable generation of relative-path .m3u8 files for Apple Music playlists. It is disabled by default. The playlist folder and filename templates live under output.playlist_folder_template and output.playlist_file_template.
Database
Media Index (database.disabled / --no-database, database.path / --database-path)
The SQLite index is enabled by default. It tracks downloaded files with portable paths relative to output.directory, their codecs and their most relevant album/playlist source. Disable it with database.disabled: true or --no-database. The database defaults to media.sqlite3 in the same .gamdl folder as config.yml, and database.path remains configurable. The first creation of each file is reported as Created config at … or Created database at …. Custom configuration paths are supported through --config or GAMDL_CONFIG.
With the index enabled, rip checks existing catalog IDs before fetching per-track tags, playback streams, lyrics, or decryption information. With overwrite disabled (default), an indexed file that still exists within the output library can be reused directly. Existing cover/lyrics sidecars are also reused without network requests; missing sidecars can still be fetched, and playlist entries are finalized normally. Explicit codec selections, single-codec priorities without a verified matching codec, and --overwrite bypass the early skip so codec changes are not silently mistaken for existing matches. The same indexed ID information is used for local track resolution in sync playlists.
database:
disabled: false
save_metadata: false
Set save_metadata: true (or --save-metadata) to also store resolved tags in separate songs, music_videos, and uploaded_videos tables. Metadata writes reuse tags already resolved during downloading and do not save artwork or lyrics in SQLite. gamdl database scan indexes existing local media, checks local M3U playlists and complete albums to reconstruct source membership, and fills any missing metadata from embedded tags when save_metadata is on; it never downloads media or contacts Apple Music.
Interface
Progress Display (ui.no_progress / --no-progress)
Live progress is enabled by default (ui.no_progress: false). Set ui.no_progress: true or use --no-progress to disable it. ui.max_visible_tracks / --max-visible-tracks controls the number of track rows shown at once (default: 5).
Error Tracebacks (ui.no_tracebacks / --no-tracebacks)
Unexpected errors print full tracebacks at the end by default. Set ui.no_tracebacks: true or pass --no-tracebacks to hide them. Known, expected conditions remain concise. Review tracebacks before sharing, as exception messages may contain sensitive URLs or account information.
🏷️ Tags and Path Templates
Gamdl separates path placeholders (used in filenames and folders) from tag exclusions (used to omit embedded metadata). Some names differ between the two. This reference lists every supported name.
Path Template Placeholders
Use these placeholders in the output.*_template settings or their CLI equivalents:
| Placeholder | Value | Corresponding tag for --exclude-tags |
|---|---|---|
{album} |
Album title | album |
{album_artist} |
Album artist | album_artist |
{album_id} |
Apple Music album ID | album_id |
{artist} |
Track or video artist | artist |
{artist_id} |
Apple Music artist ID | artist_id |
{composer} |
Composer name | composer |
{composer_id} |
Apple Music composer ID | composer_id |
{date} |
Release date, normally a YYYY-MM-DD string |
release_date |
{disc} |
Disc number | disc_number |
{disc_total} |
Total discs | disc_total |
{media_type} |
Numeric media type identifier | media_type |
{playlist_artist} |
Playlist curator or artist | — |
{playlist_id} |
Apple Music playlist ID | — |
{playlist_title} |
Playlist title | — |
{playlist_track} |
Track position in the playlist (1-based) | — |
{title} |
Song or video title | title |
{title_id} |
Apple Music song or video ID | title_id |
{track} |
Track number | track_number |
{track_total} |
Total tracks | track_total |
For example, {track:02d} {title} produces 01 Song Title when a track number is available. Standard Python format specs for numeric fields work; arbitrary expressions, attribute access, and indexing are not allowed.
The {date} placeholder uses the original release-date text. To select part of a date, use strftime specifiers such as {date:%Y} (year), {date:%Y-%m} (year and month), or {date:%d} (day). ISO-formatted dates and timestamps are supported; year-only and year-month values are also accepted, with missing month/day components assumed to be January/1 when formatting. Missing or invalid dates use the Unknown Date fallback.
Playlist placeholders are populated when playlist context is available; otherwise, fallback text is used. Missing metadata also uses readable fallbacks such as Unknown Artist or Unknown Album, or an empty string for missing numbers. Gamdl sanitizes invalid filename characters and restricts path components to safe lengths. Excluding an embedded tag does not remove its value from filename formatting.
Excludable Metadata Tags
These are all 32 valid names for output.exclude_tags and --exclude-tags:
| Tag name | Metadata omitted from the saved file |
|---|---|
title |
Song or video title |
artist |
Track artist |
album |
Album title |
album_artist |
Album artist |
title_id |
Apple Music song or video ID |
artist_id |
Apple Music artist ID |
album_id |
Apple Music album ID |
track_number |
Track number (template: {track}) |
track_total |
Total tracks |
disc_number |
Disc number (template: {disc}) |
disc_total |
Total discs |
release_date |
Release date (template: {date}) |
genre |
Genre text |
genre_id |
Apple Music genre ID |
isrc |
International Standard Recording Code |
xid |
Apple Music external identifier |
title_sort |
Title used for sorting |
artist_sort |
Artist used for sorting |
album_sort |
Album title used for sorting |
composer |
Composer name |
composer_id |
Apple Music composer ID |
composer_sort |
Composer used for sorting |
copyright |
Copyright notice |
comment |
Comment text |
compilation |
Compilation flag |
gapless |
Gapless playback flag |
explicit |
Explicit-content flag |
storefront |
Numeric Apple Music storefront ID |
media_type |
Numeric media type identifier |
rating |
Content/parental rating |
lyrics |
Embedded plain-text lyrics |
cover |
Embedded cover artwork |
For example, --exclude-tags lyrics,cover,comment omits those embedded fields while keeping the remaining tags. cover affects embedded artwork; separate artwork files are controlled by --save-cover. Likewise, excluding lyrics does not disable external lyrics files—use --no-lyrics-file for that.
Use --no-tag to disable embedded tagging altogether. Only metadata provided for a given item can be written, even when a tag is not excluded.
🔄 Migrating from Gamdl 3.x
Gamdl 4.x introduces several changes to its CLI and configuration:
- Subcommands: Use
gamdl rip URLinstead of passing URLs directly togamdl. - YAML configuration: Replace your old INI configuration with the new YAML settings. Run
gamdl config initto generate a reference configuration. - Authentication: Configure Wrapper, Cookies, or Media User Token with
gamdl auth; the old--use-wrapperflag is replaced by an authentication method. - Codec selection: The default is now HLS
aacinstead ofaac-web. The genericalacpreference automatically selects the best ALAC tier. Interactive stream selection has dedicated flags such as--ask-song-codec; codec-priority lists accept comma-separated CLI values or YAML lists. - Date templates: Strftime-style placeholders such as
{date:%Y}and{date:%Y-%m}continue to work. Release dates are now stored as strings internally, but the path formatter parses them when a date specifier is requested. - Excluded tags: The old
allspecial value is no longer accepted in--exclude-tags; use--no-taginstead. Some path placeholders use different names from tag exclusions (for example,{date}versusrelease_date). - Download concurrency: Use
download.segment_concurrency/--segment-concurrencyfor media segment requests. Previous concurrency option names are not supported. - Playlist organization:
organizecan repair playlist paths, but restoring missing metadata headers in legacy playlists remains a separate, manual task. - Database format: Older SQLite indexes cannot be opened by 4.x. Gamdl does not overwrite or upgrade them automatically; move the old database aside or set a fresh
database.path. Your downloaded media files are not touched. - Native processing: The native muxing/decryption layer replaces the old external downloader and muxer workflow. Review removed 3.x flags rather than copying them directly.
- Python API: The modules and classes have been reorganized. Applications embedding Gamdl 3.x should update their imports and integration code.
Keep a backup of your old configuration until you have verified your new settings and output templates.
🐍 Python API
Gamdl also provides asynchronous Python APIs for catalog access, media resolution, downloading, and media processing. For example, to fetch a song's metadata using an exported Apple Music cookies file:
import asyncio
from gamdl.api import AppleMusicApi
from gamdl.media import MediaResolver
async def main():
api = await AppleMusicApi.from_cookies("cookies.txt")
async with api:
resolver = MediaResolver(api)
async for song in resolver.from_song("1228739609"):
metadata = await song.get_metadata()
print(metadata["attributes"]["name"])
asyncio.run(main())
The API is asynchronous; use context managers to close connections. More advanced applications can use Downloader, Drm, Streamer, Muxer, and PathFormatter directly.
HTTP Transports
gamdl.transport provides ApiHttpClient and RequestPacer for private/API requests (authentication, pacing, and retries), alongside PublicTransport for public HTTPS resources such as streaming manifests, initialization segments, and artwork. The public transport uses isolated requests at every redirect hop, so credentials and cookies from a caller-supplied HTTPX client are not forwarded. It rejects insecure redirects and preserves the lifetime of borrowed clients. HLS parsing stays in media.stream.StreamTransport, which uses PublicTransport for network requests. Existing gamdl.api and gamdl.api.http imports of ApiHttpClient / RequestPacer remain supported.
🛠️ Troubleshooting
Authentication fails: Check that your session is valid, your cookies include media-user-token, or your wrapper is reachable. Retry gamdl auth.
A codec or stream is unavailable: Not every track offers every codec. Try --ask-song-codec, --ask-music-video-streams, or the default aac HLS codec. You can still try aac-web with Widevine/PlayReady when appropriate.
DRM initialization fails: Verify that the relevant extra (widevine or playready) is installed, that a required device file is available, and that the stream supports the selected backend.
A download is skipped: The default is download.overwrite: false. Use --overwrite if you intentionally want to replace the existing file.
The library has unexpected paths: Check your filename templates and use gamdl organize --dry-run before applying changes.
For additional support, use GitHub Issues or the Discord server. When sharing error tracebacks, remove cookies, tokens, and signed URLs.
🤝 Contributing
Bug reports, feature requests, and pull requests are welcome. Please check existing issues before opening a new one.
For source development, install uv, Python, and Rust. Then run:
uv sync
uv run python -m unittest discover -s tests
cargo test --manifest-path native/Cargo.toml
Some media-related tests also require FFmpeg and FFprobe.
Releasing to PyPI
The publishing workflow builds a source distribution and precompiled ABI3 wheels for Linux (x86_64/ARM64), Windows (x86_64/ARM64), and macOS (universal2). Every wheel is installed and smoke-tested, and the full artifact set is checked before publication.
Run Publish Python Package manually from GitHub Actions to build and inspect artifacts without publishing. Publishing occurs only when a GitHub Release is published with a tag matching pyproject.toml (for example, v4.0.0). The workflow must be present on the repository's default branch for the release trigger to work.
PyPI Trusted Publishing must be configured for repository glomatico/gamdl, workflow python-publish.yml, and GitHub environment pypi. No long-lived PyPI token is needed. Configure GitHub environment protection rules as desired before publishing a release.
📄 License
Gamdl is released under the MIT License.
Metadata
Release files for gamdl 4.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| gamdl-4.0.0.tar.gz | 237.2 kB | With provenance | Details for gamdl-4.0.0.tar.gz |
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| gamdl-4.0.0-cp310-abi3-win_arm64.whl | CPython 3.10 | abi3 | Windows ARM64 | Details for gamdl-4.0.0-cp310-abi3-win_arm64.whl |
| gamdl-4.0.0-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details for gamdl-4.0.0-cp310-abi3-win_amd64.whl |
| gamdl-4.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details for gamdl-4.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
| gamdl-4.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details for gamdl-4.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
| gamdl-4.0.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.10 | abi3 | macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64 | Details for gamdl-4.0.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
Total release size: 14.8 MB
Release files / gamdl-4.0.0.tar.gz
| Download URL | gamdl-4.0.0.tar.gz |
|---|---|
| Size | 237.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d4fed3c5dc9b62bbc756ee4644252b13cf2b3c97fb752054eeb9c50fb33f3486
|
|
BLAKE2b-256 checksum How to use checksums |
9252718e7219c5b8f4063e148734ab7b80531ee8319c8460affa412d321dc3e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / gamdl-4.0.0-cp310-abi3-win_arm64.whl
| Download URL | gamdl-4.0.0-cp310-abi3-win_arm64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | CPython 3.10 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
edc555117080c4fe4465455876278584646d71ea83a1c5cb0c9a7175906f515d
|
|
BLAKE2b-256 checksum How to use checksums |
98df2f4a09fc5b151d91ef5f8b75cfa577d362796f23f003a4113ebbff89b717
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / gamdl-4.0.0-cp310-abi3-win_amd64.whl
| Download URL | gamdl-4.0.0-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 2.3 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
d34e8eec2117018304a1b033b7ff2052d1755f4b71255ead5da3dfc5d76e028e
|
|
BLAKE2b-256 checksum How to use checksums |
03fe97b00116c37434badd36bb182902c1ec5125e686063c61158e33bf6d815e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / gamdl-4.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | gamdl-4.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.7 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
0b22af9a0f6b8e1c3144a835ff6473d6373e6b06b3eb3b6f68ee21e57e83b969
|
|
BLAKE2b-256 checksum How to use checksums |
f24dc52f80fdeb5926d0202506f2fb0a9f3ed8dbde9dee2a440975bfd21592b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / gamdl-4.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | gamdl-4.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 2.7 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
d3a48e8eecc87576133cde2f444e43e56392d7f180bffedfde2f605682a602cc
|
|
BLAKE2b-256 checksum How to use checksums |
4b74c41d3c5971688d24f83d32b384b9b2059791e6f6a6747117c59eba34068a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / gamdl-4.0.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | gamdl-4.0.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 4.7 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
8f38c9f1105133541e7e0f28805bdccd5810aa1c413464a1e09f7f28fdf765b0
|
|
BLAKE2b-256 checksum How to use checksums |
e48b21f76812e144766352e0a9a467bf46e453bdead095aa6b6066493533db65
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logSecurity for gamdl 4.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 6 files in this release have been uploaded with provenance metadata.
Attestation for gamdl-4.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.