A command-line app for downloading Apple Music songs, music videos and post videos.
Join our Discord Server: https://discord.gg/aBjMEZ9tnq
- π΅ High-Quality Songs - Download songs in AAC 256kbps and other codecs
- π¬ High-Quality Music Videos - Download music videos in resolutions up to 4K
- π Synced Lyrics - Download synced lyrics in LRC, SRT, or TTML formats
- π·οΈ Rich Metadata - Automatic tagging with comprehensive metadata
- π€ Artist Support - Download all albums or music videos from an artist
- βοΈ Highly Customizable - Extensive configuration options for advanced users
- Python 3.10 or higher
- Apple Music Cookies - Export your browser cookies in Netscape format while logged in with an active subscription at the Apple Music website:
- Firefox: Export Cookies
- Chromium: Get cookies.txt LOCALLY
- FFmpeg - Must be in your system PATH
- Windows: AnimMouse's FFmpeg Builds
- Linux: John Van Sickle's FFmpeg Builds
Add these tools to your system PATH for additional features:
- mp4decrypt - Required for
mp4boxremux mode, music videos, and experimental codecs - MP4Box - Required for
mp4boxremux mode - N_m3u8DL-RE - Required for
nm3u8dlredownload mode, which is faster than the default downloader
Install Gamdl via pipx:
pipx is recommended for installing Gamdl to avoid dependency conflicts, but you can also use pip.
pipx install gamdlSetup cookies:
- Place your cookies file in the working directory as
cookies.txt, or - Specify the path using
--cookies-pathor in the config file
gamdl [OPTIONS] URLS...- Songs
- Albums (Public/Library)
- Playlists (Public/Library)
- Music Videos
- Artists
- Post Videos
Download a song:
gamdl "https://music.apple.com/us/album/never-gonna-give-you-up-2022-remaster/1624945511?i=1624945512"Download an album:
gamdl "https://music.apple.com/us/album/whenever-you-need-somebody-2022-remaster/1624945511"Download from an artist:
gamdl "https://music.apple.com/us/artist/rick-astley/669771"Interactive Prompt Controls:
| Key | Action |
|---|---|
| Arrow keys | Move selection |
| Space | Toggle selection |
| Ctrl + A | Select all |
| Enter | Confirm selection |
Configure Gamdl using command-line arguments or a config file.
Config file location:
- Linux:
~/.gamdl/config.ini - Windows:
%USERPROFILE%\.gamdl\config.ini
The file is created automatically on first run. Command-line arguments override config values.
| Option | Description | Default |
|---|---|---|
| General Options | ||
--read-urls-as-txt, -r |
Read URLs from text files | false |
--config-path |
Config file path | <home>/.gamdl/config.ini |
--log-level |
Logging level | INFO |
--log-file |
Log file path | - |
--no-exceptions |
Don't print exceptions | false |
--no-config-file, -n |
Don't use a config file | false |
| Apple Music Options | ||
--cookies-path, -c |
Cookies file path | ./cookies.txt |
--language, -l |
Metadata language | en-US |
| Output Options | ||
--output-path, -o |
Output directory path | ./Apple Music |
--temp-path |
Temporary directory path | . |
--wvd-path |
.wvd file path | - |
--overwrite |
Overwrite existing files | false |
--save-cover, -s |
Save cover as separate file | false |
--save-playlist |
Save M3U8 playlist file | false |
| Download Options | ||
--nm3u8dlre-path |
N_m3u8DL-RE executable path | N_m3u8DL-RE |
--mp4decrypt-path |
mp4decrypt executable path | mp4decrypt |
--ffmpeg-path |
FFmpeg executable path | ffmpeg |
--mp4box-path |
MP4Box executable path | MP4Box |
--download-mode |
Download mode | ytdlp |
--remux-mode |
Remux mode | ffmpeg |
--cover-format |
Cover format | jpg |
| Template Options | ||
--album-folder-template |
Album folder template | {album_artist}/{album} |
--compilation-folder-template |
Compilation folder template | Compilations/{album} |
--single-disc-file-template |
Single disc file template | {track:02d} {title} |
--multi-disc-file-template |
Multi disc file template | {disc}-{track:02d} {title} |
--no-album-folder-template |
No album folder template | {artist}/Unknown Album |
--no-album-file-template |
No album file template | {title} |
--playlist-file-template |
Playlist file template | Playlists/{playlist_artist}/{playlist_title} |
--date-tag-template |
Date tag template | %Y-%m-%dT%H:%M:%SZ |
--exclude-tags |
Comma-separated tags to exclude | - |
--cover-size |
Cover size in pixels | 1200 |
--truncate |
Max filename length | - |
| Song Options | ||
--codec-song |
Song codec | aac-legacy |
--synced-lyrics-format |
Synced lyrics format | lrc |
--no-synced-lyrics |
Don't download synced lyrics | false |
--synced-lyrics-only |
Download only synced lyrics | false |
| Music Video Options | ||
--music-video-codec-priority |
Comma-separated codec priority | h264,h265 |
--music-video-remux-format |
Music video remux format | m4v |
--music-video-resolution |
Max music video resolution | 1080p |
| Post Video Options | ||
--uploaded-video-quality |
Post video quality | best |
Use these variables in folder/file templates or --exclude-tags:
| Variable | Description |
|---|---|
{album}, {album_artist}, {album_id}, {album_sort} |
Album info |
{artist}, {artist_id}, {artist_sort} |
Artist info |
{title}, {title_id}, {title_sort} |
Title info |
{composer}, {composer_id}, {composer_sort} |
Composer info |
{track}, {track_total}, {disc}, {disc_total} |
Track numbers |
{genre}, {genre_id} |
Genre info |
{date} |
Release date (supports strftime: {date:%Y}) |
{playlist_artist}, {playlist_id}, {playlist_title}, {playlist_track} |
Playlist info |
{compilation}, {gapless}, {rating} |
Media properties |
{comment}, {copyright}, {lyrics}, {cover} |
Additional metadata |
{media_type}, {storefront}, {xid} |
Technical info |
all |
Special: Skip all tagging |
DEBUG,INFO,WARNING,ERROR
ytdlp,nm3u8dlre
ffmpegmp4box- Preserve the original closed caption track in music videos and some other minor metadata
jpgpngraw- Raw format as provided by the artist (requiressave_coverto be enabled as it doesn't embed covers into files)
Use ISO 639-1 language codes (e.g., en-US, es-ES, ja-JP, pt-BR). Don't always work for music videos.
Stable:
aac-legacy- AAC 256kbps 44.1kHzaac-he-legacy- AAC-HE 64kbps 44.1kHz
Experimental (may not work due to API limitations):
aac- AAC 256kbps up to 48kHzaac-he- AAC-HE 64kbps up to 48kHzaac-binaural- AAC 256kbps binauralaac-downmix- AAC 256kbps downmixaac-he-binaural- AAC-HE 64kbps binauralaac-he-downmix- AAC-HE 64kbps downmixatmos- Dolby Atmos 768kbpsac3- AC3 640kbpsalac- ALAC up to 24-bit/192kHzask- Interactive experimental codec selection
lrcsrt- SubRip subtitle format (more accurate timing)ttml- Native Apple Music format (not compatible with most media players)
h264h265ask- Interactive codec selection
- H.264:
240p,360p,480p,540p,720p,1080p - H.265 only:
1440p,2160p
m4v,mp4
best- Up to 1080p with AAC 256kbpsask- Interactive quality selection
Use Gamdl as a library in your Python projects:
import asyncio
from gamdl.api import AppleMusicApi
from gamdl.downloader import (
AppleMusicBaseDownloader,
AppleMusicDownloader,
AppleMusicMusicVideoDownloader,
AppleMusicSongDownloader,
AppleMusicUploadedVideoDownloader,
)
async def main():
# Initialize API
api = AppleMusicApi.from_netscape_cookies(cookies_path="cookies.txt")
await api.setup()
# Initialize downloaders
base_downloader = AppleMusicBaseDownloader(apple_music_api=api)
base_downloader.setup()
song_downloader = AppleMusicSongDownloader(base_downloader)
song_downloader.setup()
music_video_downloader = AppleMusicMusicVideoDownloader(base_downloader)
music_video_downloader.setup()
uploaded_video_downloader = AppleMusicUploadedVideoDownloader(base_downloader)
uploaded_video_downloader.setup()
# Create main downloader
downloader = AppleMusicDownloader(
base_downloader,
song_downloader,
music_video_downloader,
uploaded_video_downloader,
)
# Download a song
url_info = downloader.get_url_info(
"https://music.apple.com/us/album/never-gonna-give-you-up-2022-remaster/1624945511?i=1624945512"
)
if url_info:
download_queue = await downloader.get_download_queue(url_info)
if download_queue:
for download_item in download_queue:
await downloader.download(download_item)
if __name__ == "__main__":
asyncio.run(main())MIT License - see LICENSE file for details
Contributions are welcome! Feel free to open issues or submit pull requests, but you may discuss major changes first on our Discord server.