Command line tool to download music from YT Music with appropriate metadata.
Note: This tool is still in its infancy, expect bugs. Please report any issues encountered with this tool.
ytmusicdl.py
is easy to set up and has been tested on Windows and Linux. Make sure the prerequisites listed below are installed on your system.
I will no longer be maintaining the Windows binary. The build.cmd
file will still be included, but you'll have to install some other prerequisites for that to work.
- Python 3.8+ (Official Website)
pillow
(Official Website) (PyPI) (install usingpip
)ytmusicapi
(GitHub) (Documentation) (PyPI) (install usingpip
)music_tag
(GitHub) (PyPI) (install usingpip
)yt-dlp
(GitHub) (PyPI) (install usingpip
)FFMPEG
(required byyt-dlp
)- For Windows: must be added to
%PATH%
(Recommended: yt_dlp provided builds - GitHub) - For Linux: Install from your package manager
- For Windows: must be added to
usage: ytmusicdl.py [-h] [-f {opus,m4a,mp3}] [-q QUALITY] [-p BASE_PATH] [-o OUTPUT_TEMPLATE] [-a ARCHIVE] [-b] [--account ACCOUNT] [--write-json] [--cover-format {png,jpg}] [--write-cover] [--write-lyrics] [--no-lyrics]
[--skip-existing] [--skip-download] [--download-limit DOWNLOAD_LIMIT] [--playlist-limit PLAYLIST_LIMIT] [-v] [--log LOG] [--log-verbose] [--about]
URL [URL ...]
Downloads songs from YT Music with appropriate metadata
positional arguments:
URL List of URL(s) to download
options:
-h, --help show this help message and exit
-f {opus,m4a,mp3}, --format {opus,m4a,mp3}
Audio output format
-q QUALITY, --quality QUALITY
Audio quality: VBR (best: 0 - worst: 9) or CBR (e.g. 256)
-p BASE_PATH, --base-path BASE_PATH
Base output path (default is current working directory)
-o OUTPUT_TEMPLATE, --output-template OUTPUT_TEMPLATE
Output template for downloaded songs
-a ARCHIVE, --archive ARCHIVE
Path to file that keeps record of the downloaded songs
-b, --batch Treat URL arguments as paths to files containing a list of URLs or IDs (one per line)
Specify "-" for input to be taken from console (stdin)
--account-headers ACCOUNT_HEADERS
Path to file containing authentication headers
Allows special URL placeholder values to be used.
--write-json Write JSON with information about each song (follows output template)
--cover-format {png,jpg}
Set the cover image format (png or jpg)
--write-cover Write each song's album cover to a file (follows output template)
--write-lyrics Write each song's lyrics to a file (follows output template)
--no-lyrics Don't obtain lyrics
--skip-existing Skip over existing files
--skip-download Skip downloading songs
--download-limit DOWNLOAD_LIMIT
Limit the number of songs to be downloaded in an instance
--playlist-limit PLAYLIST_LIMIT
Limit the number of songs to be downloaded from a playlist
-v, --verbose Show all debug messages on console and log
--log LOG Path to verbose log output file
--log-verbose Save all debug messages to the log
--about Display version information (must specify at least one (dummy) URL)
Specify the desired output format with the -f
or --format
option. The available formats are OPUS, M4A (AAC) and MP3.
OPUS and M4A are directly downloaded from YT Music, while MP3 will be trans-coded from the best available format using FFMPEG.
For unauthenticated or free accounts:
- OPUS codec, OGG container, averaging 140 kbps variable bitrate
- AAC-LC codec, M4A container, 128 kbps "constant" bitrate
To select a different output quality, specify either a variable bitrate (0-9) or a constant bitrate (e.g. 128k) with the -q
or --quality
option.
This will re-encode downloaded audio using FFMPEG.
Any relative paths specified as an argument will be treated as relative to the path specified by the -p
or --base-path
option.
If not specified, the base path defaults to the current working directory of the terminal window.
The -o
or --output
option is used to indicate a template for the output file names, relative to the base path. The audio download, --write-json
and --write-cover
all follow the output template.
The template usually contains special sequences that are replaced with values for each download.
The sequence is {value_name}
and it can be combined with other characters, for example: {song_title} - {song_artist} [{song_id}].{ext}
- this is the default output template.
Some values might not be available in certain cases, like music videos where album related data isn't available. If a value is not available, it will be replaced with the placeholder string Unknown
.
If you wish to specify other values in case one isn't available, you can use the |
character.
Example: {album_artist|song_artist}
will parse to either the album artist if available, song artist if available or the placeholder string Unknown
.
If you want to supress the Unknown
placeholder string, you can add an empty value to the end of the list.
Example: {album_artist|song_artist|}
will parse to an empty string if none of the values are available.
For more advanced templates, you can specify text to follow a value only if it is available using the +
operator.
Notice that the value list ends in |
, as we want to supress the placeholder string.
Example: {song_index|+ - }{song_title}.{ext}
will parse to 1 - Song Title.opus
if the song index is available, otherwise it will parse to Song Title.opus
Notice: The output template must end in .{ext}
, as hard-coding a file extension would cause issues.
- Song related
song_id
,song_title
,song_duration
,song_year
song_type
-Song
orVideo
song_artist
- first song artistsong_artists
- all song artists, separated by,
- Album related
song_index
- song's index in an albumalbum_total
- total number of songs in an albumalbum_id
,album_title
album_type
-Album
orSingle
, as seen on YT Music album pagealbum_duration
album_artist
- first album artistalbum_artists
- all album artists, separated by,
- Playlist related
song_playlist_index
- song's index in a playlistplaylist_total
- total number of songs in a playlistplaylist_id
,playlist_title
playlist_author
- first playlist authorplaylist_authors
- all playlist authors (collaborators), separated by,
playlist_visibility
-Public
,Unlisted
orPrivate
- Other
date
,time
,date_time
- date and/or approximate time of downloadext
- can only be used at the end of the template
The archive file will store a list of song IDs that have been previously downloaded. The file is written to after every song download.
To enable, provide either an absolute path, or a path relative to the base path to the -a
or --archive
option.
If the -b
or --batch
option is provided, URL arguments will be treated as paths to files containing URLs or IDs to download, separated by new lines.
If a relative path is provided, it will be taken as relative to the specified base path.
Follow the instructions on ytmusicapi documentation to get your account headers ready for use with ytmusicdl.py
.
Specify your JSON file containing account header data using the --account-headers
argument. This lets you use special placeholder IDs to download songs from your library:
library_songs
- Download songs from the Songs tab on the Library pagelibrary_albums
- Download each album on the Albums tab on the Library pagelibrary_playlists
- Download each playlist on the Playlists tab on the Library pageliked_songs
- Download your liked songs playlist
Most of the time you will be using library_songs
as it includes liked songs and all available songs from albums added to your library.
--skip-existing
will skip over existing files without overwriting--skip-download
will not download the audio, but will still perform other actions.
Notice: any processed song will still be added to the archive even when using--skip-download
.--playlist-limit
limits the number of songs to be downloaded from each playlist.--download-limit
limits the number of songs to be downloaded in the current instance.--no-lyrics
will not get the lyrics for songs, this skips an API request and speeds up the download slightly.--write-json
and--write-lyrics
will write out a JSON file containing song information (the contents of thesong: dict
from source code) and the song lyrics (if available) respectively.--write-cover
will write out the song cover art in the selected format.--cover-format
selects the cover format (png
orjpg
) to be embedded in metadata and to be writte out by--write-cover
.
ytmusicdl.py URL
Downloads the specified URL to the current working directory in the default format (OPUS) and quality(0 / best).
ytmusicdl.py -f "m4a" -p "Music" -a "archive.txt" -o "{album_artist|song_artist}/{album_title|song_title}/{song_index|+ - }{song_title}.{ext}" URL [URL ...]
Downloads the specified URL(s) with the following options:
- Selected format:
m4a
- Base path:
Music
(relative to current working directory) - Archive file
archive.txt
(relative to base path) - Output template:
{album_artist|song_artist}/{album_title|song_title}/{song_index|+ - }{song_title}.{ext}
- Example for audio-only song:
Album Artist/Album Title/1 - Song Title.ext
- Example for music video:
Song Artist/Song Title/Song Title.ext
- Example for audio-only song:
To build the project to an EXE file, you just need to run the build.cmd
script in the setup
folder.
Prerequisite: pyinstaller
(install from pip
) - make sure it's added to %PATH%
.
ytmusicdl.py
will download music videos as audio only.