Skip to main content

A command-line app for downloading Apple Music songs, music videos and post videos.

Project description

Gamdl (Glomatico's Apple Music Downloader)

PyPI version Python versions License Downloads

A command-line app for downloading Apple Music songs, music videos and post videos.

Join our Discord Server: https://discord.gg/aBjMEZ9tnq

✨ Features

  • 🎵 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

📋 Prerequisites

Required

  • 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:

Optional

Add these tools to your system PATH for additional features:

  • FFmpeg - Required for ffmpeg music video remux mode
  • mp4decrypt - Required for mp4box music video remux mode
  • MP4Box - Required for mp4box music video remux mode
  • N_m3u8DL-RE - Required for nm3u8dlre download mode, which is faster than the default downloader
  • Wrapper - For downloading songs in ALAC and other experimental codecs without API limitations

📦 Installation

Install Gamdl via pip:

pip install gamdl

Setup cookies:

  1. Place your cookies file in the working directory as cookies.txt, or
  2. Specify the path using --cookies-path or in the config file

🚀 Usage

gamdl [OPTIONS] URLS...

Supported URL Types

  • Songs
  • Albums (Public/Library)
  • Playlists (Public/Library)
  • Music Videos
  • Artists
  • Post Videos
  • Apple Music Classical

Examples

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

⚙️ Configuration

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.

Configuration Options

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
--wrapper-account-url Wrapper account URL http://127.0.0.1:30020
--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
--artist-auto-select Automatically select artist content to download (artist URLs) -
--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
--use-wrapper Use wrapper false
--wrapper-decrypt-ip Wrapper decryption server IP 127.0.0.1:10020
--download-mode Download mode ytdlp
--cover-format Cover format jpg
Template Options
--album-folder-template Album folder template {album_artist}/{album}
--compilation-folder-template Compilation folder template Compilations/{album}
--no-album-folder-template No album folder template {artist}/Unknown 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-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
--song-codec-priority Comma-separated codec priority 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
--use-album-date Use album release date for songs false
--fetch-extra-tags Fetch extra tags from preview (normalization and smooth playback) false
Music Video Options
--music-video-codec-priority Comma-separated codec priority h264,h265
--music-video-remux-mode Remux mode ffmpeg
--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

Template Variables

Tags for templates and exclude-tags:

  • album, album_artist, album_id
  • artist, artist_id
  • composer, composer_id
  • date (supports strftime format: {date:%Y})
  • disc, disc_total
  • media_type
  • playlist_artist, playlist_id, playlist_title, playlist_track
  • title, title_id
  • track, track_total

Tags for exclude-tags only:

  • album_sort, artist_sort, composer_sort, title_sort
  • comment, compilation, copyright, cover, gapless, genre, genre_id, lyrics, rating, storefront, xid
  • all (special: skip all tagging)

Logging Level

  • DEBUG, INFO, WARNING, ERROR

Download Mode

  • ytdlp, nm3u8dlre

Remux Mode

  • ffmpeg
  • mp4box - Preserve the original closed caption track in music videos and some other minor metadata

Cover Format

  • jpg
  • png
  • raw - Raw format as provided by the artist (requires save_cover to be enabled as it doesn't embed covers into files)

Metadata Language

Use ISO 639-1 language codes (e.g., en-US, es-ES, ja-JP, pt-BR). Don't always work for music videos.

Song Codecs

Stable:

  • aac-legacy - AAC 256kbps 44.1kHz
  • aac-he-legacy - AAC-HE 64kbps 44.1kHz

Experimental (may not work due to API limitations):

  • aac - AAC 256kbps up to 48kHz
  • aac-he - AAC-HE 64kbps up to 48kHz
  • aac-binaural - AAC 256kbps binaural
  • aac-downmix - AAC 256kbps downmix
  • aac-he-binaural - AAC-HE 64kbps binaural
  • aac-he-downmix - AAC-HE 64kbps downmix
  • atmos - Dolby Atmos 768kbps
  • ac3 - AC3 640kbps
  • alac - ALAC up to 24-bit/192kHz (unsupported)
  • ask - Interactive experimental codec selection

Synced Lyrics Format

  • lrc
  • srt - SubRip subtitle format (more accurate timing)
  • ttml - Native Apple Music format (not compatible with most media players)

Music Video Codecs

  • h264
  • h265
  • ask - Interactive codec selection

Music Video Resolutions

  • H.264: 240p, 360p, 480p, 540p, 720p, 1080p
  • H.265 only: 1440p, 2160p

Music Video Remux Formats

  • m4v, mp4

Post Video Quality

  • best - Up to 1080p with AAC 256kbps
  • ask - Interactive quality selection

Artist Auto-Select Options

  • main-albums
  • compilation-albums
  • live-albums
  • singles-eps
  • all-albums
  • top-songs
  • music-videos

⚙️ Wrapper

Use the wrapper to download songs in ALAC and other experimental codecs without API limitations. Cookies are not required when using the wrapper.

Setup Instructions

  1. Start the wrapper server - Run the wrapper server
  2. Enable wrapper in Gamdl - Use --use-wrapper flag or set use_wrapper = true in config
  3. Run Gamdl - Download as usual with the wrapper enabled

🐍 Embedding

Use Gamdl as a library in your Python projects:

import asyncio

from gamdl.api import AppleMusicApi, ItunesApi
from gamdl.downloader import (
    AppleMusicBaseDownloader,
    AppleMusicDownloader,
    AppleMusicMusicVideoDownloader,
    AppleMusicSongDownloader,
    AppleMusicUploadedVideoDownloader,
)
from gamdl.interface import (
    AppleMusicInterface,
    AppleMusicMusicVideoInterface,
    AppleMusicSongInterface,
    AppleMusicUploadedVideoInterface,
)

async def main():
    # Create AppleMusicApi instance (from cookies or wrapper)
    apple_music_api = await AppleMusicApi.create_from_netscape_cookies(
        cookies_path="cookies.txt",
    )
    itunes_api = ItunesApi(
        apple_music_api.storefront,
        apple_music_api.language,
    )

    # Check subscription
    assert apple_music_api.active_subscription

    # Set up interfaces
    interface = AppleMusicInterface(apple_music_api, itunes_api)
    song_interface = AppleMusicSongInterface(interface)
    music_video_interface = AppleMusicMusicVideoInterface(interface)
    uploaded_video_interface = AppleMusicUploadedVideoInterface(interface)

    # Set up base downloader and specialized downloaders
    base_downloader = AppleMusicBaseDownloader()
    song_downloader = AppleMusicSongDownloader(
        base_downloader=base_downloader,
        interface=song_interface,
    )
    music_video_downloader = AppleMusicMusicVideoDownloader(
        base_downloader=base_downloader,
        interface=music_video_interface,
    )
    uploaded_video_downloader = AppleMusicUploadedVideoDownloader(
        base_downloader=base_downloader,
        interface=uploaded_video_interface,
    )

    # Main downloader
    downloader = AppleMusicDownloader(
        interface=interface,
        base_downloader=base_downloader,
        song_downloader=song_downloader,
        music_video_downloader=music_video_downloader,
        uploaded_video_downloader=uploaded_video_downloader,
    )

    # Download a song
    url = "https://music.apple.com/us/album/never-gonna-give-you-up-2022-remaster/1624945511?i=1624945512"
    url_info = downloader.get_url_info(url)
    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())

📄 License

MIT License - see LICENSE file for details

🤝 Contributing

Currently, I'm not interested in reviewing pull requests that change or add features. Only critical bug fixes will be considered. However, feel free to open issues for bugs or feature requests.

Project details


Release history Release notifications | RSS feed

This version

2.9.3

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gamdl-2.9.3.tar.gz (64.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gamdl-2.9.3-py3-none-any.whl (69.7 kB view details)

Uploaded Python 3

File details

Details for the file gamdl-2.9.3.tar.gz.

File metadata

  • Download URL: gamdl-2.9.3.tar.gz
  • Upload date:
  • Size: 64.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for gamdl-2.9.3.tar.gz
Algorithm Hash digest
SHA256 a053d0801103df676af6effd348f068f2bdca51ab85551fc6aa56b684e5ffdd3
MD5 f4e33465edf0c442002ad7d0a9e574b7
BLAKE2b-256 766228429c8edd8667ba9012678d3c467304907e12d793e16e8d454b89c44f3f

See more details on using hashes here.

Provenance

The following attestation bundles were made for gamdl-2.9.3.tar.gz:

Publisher: python-publish.yml on glomatico/gamdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gamdl-2.9.3-py3-none-any.whl.

File metadata

  • Download URL: gamdl-2.9.3-py3-none-any.whl
  • Upload date:
  • Size: 69.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for gamdl-2.9.3-py3-none-any.whl
Algorithm Hash digest
SHA256 87fb91fda601476f7ce82b9475ac1043ae0b99371b445b1633501f1e0103f3a8
MD5 a1b036dcc9942c0a36b8c73883cd1cf1
BLAKE2b-256 ccd1fce410417e25cee8f415abdac4a6e8c8a65dbc7c055bccc0e3e4f80f3eb4

See more details on using hashes here.

Provenance

The following attestation bundles were made for gamdl-2.9.3-py3-none-any.whl:

Publisher: python-publish.yml on glomatico/gamdl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page