DEPRECATED — renamed to youtube-music-dl. Download and label albums and playlists from YouTube.
Project description
youtube-multi-dl
[!IMPORTANT]
youtube-multi-dlhas been renamed toyoutube-music-dland is no longer maintained under this name. It's the same tool by the same maintainer — the new name just better reflects its focus. Please switch:pip uninstall youtube-multi-dl && pip install youtube-music-dlThis
3.1.0release still works as documented, but every run prints a reminder to migrate. All future development happens inyoutube-music-dl.
youtube-multi-dl makes it super easy to download and label music from YouTube. It handles single songs, playlists, and single-song albums (it splits them by chapters).
It tags them (title, artist, album, track number) so they're correctly grouped and ordered in whatever music player you use, cleans up the song titles, and gives files clean names. Output is Opus by default (excellent quality at small sizes, and copied straight from YouTube's stream without re-encoding when possible) or mp3.
It's a wrapper around the amazing yt-dlp, built to be as simple as possible to use from the command line, in a script, or by an AI agent. It prints a single JSON object describing what it did.
# Download and label tracks 1-10 of this playlist by "Star Band de Dakar"
youtube-multi-dl "https://www.youtube.com/watch?v=PlnanwD_vS0&index=1&list=PLcOYKKFxnwAdGh4NCgpXq_FNQoZKL6xWM" -a "Star Band de Dakar" -p "1-10"
# Download "Nilsson Schmilsson" from a single vid, split it by chapters, and label each song
youtube-multi-dl eTYushgUR00 -a "Harry Nilsson" --album "Nilsson Schmilsson"
# Download this Lucinda Williams album from a list of single-song URLs/IDs
youtube-multi-dl vWyXoGUdj4U 9R_dkP2duog qAJ8OCqe0v4 qWJCu3d6EX0 dPr0Iyh0z60 4VMUjcQ2ggs haUHiHVTvtg IOCPe_ff2RE ihuPM-xiCqY pjYxBxGSNnY HrSEeNE_Uzw cpP11qYuhg8 -a "Lucinda Williams" --album "Sweet Old World"
# Download this Pharoah Sanders album from a single vid, split it by chapters, and label each song; youtube-multi-dl guesses at the album name from the video metadata
youtube-multi-dl SDeuYY3Hi_I -a "Pharoah Sanders"
Installation
pip install youtube-multi-dl
Deps
youtube-multi-dl needs a few system binaries (used by yt-dlp):
- FFmpeg and
ffprobeto convert and split audio- macOS:
brew install ffmpeg - Ubuntu:
sudo apt install ffmpeg
- macOS:
- A JavaScript runtime: modern YouTube requires one for extraction; Deno is recommended (Node also works)
- macOS:
brew install deno - Ubuntu: see Deno install docs
- macOS:
If a required binary is missing, youtube-multi-dl tells you (with an error.code of NO_FFMPEG or NO_JS_RUNTIME) instead of failing cryptically.
It's worth noting that yt-dlp occasionally "breaks", for example because YouTube changes something that prevents it from properly downloading videos. In these cases fixes appear quickly. If youtube-multi-dl suddenly stops working, try running pip install --upgrade "yt-dlp[default]" to upgrade yt-dlp.
What it does that plain yt-dlp doesn't
yt-dlp can extract audio, embed metadata, and split by chapters on its own. youtube-multi-dl is a focused convenience layer on top of it that adds:
- Custom-timestamp splitting. Split a single "full album" video at boundaries you supply in a JSON/CSV
--chapters-file. Useful when the tracklist is only in the description and there are no real YouTube chapters. yt-dlp can only split by chapters that already exist. - Albums from a list of single-song URLs, tagged with a shared album and sequential track numbers, in one command.
- Opinionated one-liner defaults: makes an album folder, cleans song titles (strips the artist/album out), tags everything, and gives files clean, ordered names.
- Automatic mode detection: you don't tell it whether the URL is a playlist, a chaptered video, or single songs, it figures it out. It also auto-splits a single video that does have chapters, with no extra flag. When driven with an agent, it can download albums that don't have chapters, as long as the description has track names and durations, or if these are supplied by the user.
- Agent-friendly output: one JSON object on stdout, a stable error/exit-code contract, idempotent re-runs, and a skill that teaches agents how to run common workflows.
Usage
youtube-multi-dl downloads tagged tracks into an <artist>/<album>/ folder, created inside your current directory (or the -o path), so you can browse your music by artist on disk. Run youtube-multi-dl -h for the full help.
It prints one JSON object to stdout (logs go to stderr), so youtube-multi-dl … 2>/dev/null | jq gives you clean JSON. Re-runs are idempotent. Tracks already present (matched by an embedded youtube_video_id tag) are skipped. Exit code is 0 on success, 2 if some tracks failed, 1 on a fatal error.
Required Arguments
url: URL or ID of a YouTube playlist, a video with chapters, or one or more single-song URLs-a/--artistARTIST
Optional Arguments
--album: required for single-song URLs; otherwise defaults to the playlist/video title-p,--playlist-items: playlist items to download; e.g. "1,3-5,7-9,11,12"-t,--track-numbers: track numbers to assign; must be the same length as the items-s,--strip-patterns: extra regex patterns to remove from titles--no-strip-meta: don't strip the artist/album out of titles-f,--audio-format: {opus,mp3}; defaultopus; Opus is copied from YouTube's stream without re-encoding when possible; mp3 is for maximum device compatibility-q,--audio-quality: a bitrate like160K, or0–9VBR for mp3; Omit for opus to avoid re-encoding (recommended)--chapters-file: JSON or CSV file of chapters used to split a single video at custom timestamps; see these examples-o,--output-path: directory in which the album directory is created; Precedence: this flag (even-o .) → theYMD_OUTPUT_DIRenv var → the current directory--force: re-download tracks even if they're already present--probe: print what a real run would do (mode, chapters, description) as JSON, without downloading — useful for deciding whether an album video needs a--chapters-file--print-schema/--print-skill: print the JSON Schemas / the agent skill and exit
File names and tags
Tracks land at <artist>/<album>/NN - Title.ext (e.g. Harry Nilsson/Nilsson Schmilsson/01 - Gotta Get Up.opus), named cleanly and in order. The artist/album is stripped out of both the title tag (what your player shows) and the filename. The source video is not lost: it's stored in a youtube_video_id tag on each file (yt-dlp also embeds the source URL), which is how re-runs know what's already been downloaded.
Env vars
YMD_OUTPUT_DIR: default output directory- E.g. set
export YMD_OUTPUT_DIR="$HOME/Music"
- E.g. set
Use with AI agents
Because the CLI is non-interactive and emits schema-stable JSON, an agent can drive it directly. E.g. "download this album by this artist to ~/Music", a YouTube URL, or a CSV of albums to fetch one by one. This repo ships a skill that teaches an agent the workflows, the output schema, and the error codes. To use this skill with an agent, copy or symlink it into your agent's skills directory.
The CLI is self-describing, so an agent needs no filesystem paths: --print-skill prints the skill, --print-schema prints the JSON Schemas, and --probe <url> reports the detected mode (playlist / chaptered video / single song) and the video description without downloading — which is how an agent decides whether a "full album" video needs a generated --chapters-file.
Contributing
Fork the repo and submit a PR. Create an issue if something is broken!
Development
This project uses uv for packaging and development. Run uv sync to set things up:
uv sync
By default this creates a virtual environment at .venv in the repo root (the standard location uv uses) and installs all dependencies into it, including dev tools (ruff, pyright). pyrightconfig.json points pyright at this .venv, so type checking can resolve yt-dlp, mutagen, and the other deps without any extra configuration.
uv sync installs the project as an editable install in .venv, so running it through uv run always reflects your latest code — no reinstall step:
uv run youtube-multi-dl SDeuYY3Hi_I -a "Pharoah Sanders"
Note that python -m youtube_multi_dl.command_line ... works too. Run other tools the same way with uv run, e.g. uv run pyright, or activate the environment with source .venv/bin/activate.
Run cd .git/hooks && ln -s -f ../../pre-push to add the pre-push hook to ensure you can't push anything that doesn't pass ruff, pyright and pytest.
Style
Uses ruff for formatting, linting, and import sorting.
uv run ruff format .to format source files in placeuv run ruff check .to lint (add--fixto auto-fix)uv run pyrightto type-checkuv run pytestto run the tests
Release/Deploy to PyPI
uv build
uv publish
Install locally
To put a youtube-multi-dl command on your PATH that tracks the repo — so it always picks up later code edits — install it editable:
uv tool install --editable .
Plain uv tool install . snapshots the current code instead, so you'd have to re-run uv tool install . --reinstall after every edit. Also, remember that you can skip install and simply do uv run youtube-multi-dl ..., which always reflects the latest code.
License
This code is licensed under the MIT License.
Thanks
To the maintainers of yt-dlp, Mutagen and FFmpeg, and to anyone who doesn't want all that sweet music to go behind ads or a paywall.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file youtube_multi_dl-3.1.0.tar.gz.
File metadata
- Download URL: youtube_multi_dl-3.1.0.tar.gz
- Upload date:
- Size: 67.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
797884336a2dbcd12bd64a219d323d831640309e42cb9e3a9b4a9ab307a40e3b
|
|
| MD5 |
22e2a86abcae65e92698c7289a05e25a
|
|
| BLAKE2b-256 |
c04703f78448540fb1d722adf1d3bd9310b341e60864cb23b66c079cfbc54342
|
File details
Details for the file youtube_multi_dl-3.1.0-py3-none-any.whl.
File metadata
- Download URL: youtube_multi_dl-3.1.0-py3-none-any.whl
- Upload date:
- Size: 22.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
526b7f30b041db7382223801ab061aeb768b1aad7d61256708ac81b743618306
|
|
| MD5 |
ef4b168cf9a5833b22878d2dc7dd7419
|
|
| BLAKE2b-256 |
a88e9a6258e9a7da520d931cace9e798fc5bad7d0589098445e95fc6a8c16973
|