Important: This tool requires a rooted Android phone and ADB (Android Debug Bridge) to function. It will not work without root access!
This comes without any warranty. Use it at your own risk and always respect local copyright laws.
This tool allows you to backup your downloaded YouTube Music content (both cache and offline downloads) from your rooted Android device. It retrieves the necessary encryption key, database files containing metadata, and the encrypted media files. The tool then decrypts these media files and optionally adds metadata (title, artist, cover art) to them.
These steps are generally needed only once to set up the environment.
-
Initialize the
blackboxprotobufsubmodule:
This dependency is used for decoding protocol buffer messages found in the YouTube Music databases.git submodule init submodules/blackboxprotobuf git submodule update
-
Enable ADB and Root Access on your Android device:
Ensure you have ADB installed on your computer and that you have enabled USB debugging on your Android device. You also need to have root access enabled on your device for the following commands to work. -
Fetch the encryption key and database files:
Connect your Android device to your computer via USB and run the following ADB commands:adb root adb shell cat /data/data/com.google.android.apps.youtube.music/shared_prefs/youtube.xml \ | grep -oP 'downloads_encryption_key">([^& <]+)' \ | cut -d'>' -f 2 > encryption_key.txt adb pull /data/data/com.google.android.apps.youtube.music/databases mkdir musicadb root: Restarts the ADB daemon with root privileges. This is required to read files of non-debugable packages.- The
adb shell catcommand retrieves the YouTube Music shared preferences file and extracts the decryption key, saving it toencryption_key.txt. adb pull: Downloads the database directory containingoffline*.dband*.entitystorewhich store metadata about your downloaded music.
Important: You will need to repeat theadb pullcommand after downloading new music in the app.mkdir music: Creates a directory to store the decrypted music files (you can choose a different name).
Once you have the database files, the encryption key, and the cache index, you can run the ytm_dumper script to extract and decrypt your music.
python3 -m ytm_dumper.cli databases/ $(cat encryption_key.txt) --dest music/$ python3 -m ytm_dumper.cli --help
usage: cli.py [-h] [--dest DEST] [--no-metadata] [--streamdir STREAMDIR] [-m MATCH] [-l] [-s SINCE] databases key
Dump Youtube Music exo cache music/videos from a rooted Android phone.
positional arguments:
databases Path to the SQLite databases directory containing the offline*.db and *.entitystore files.
key Base64 encoded decryption key. See README.md on how to obtain it.
options:
-h, --help show this help message and exit
--dest DEST Output path for all the media files.
--no-metadata Disable use of ffmpeg to write metadata (title, artist, cover art) to the decrypted files.
--streamdir STREAMDIR
Path to the offline/*/streams exo cache directory.
-m MATCH, --match MATCH
Only include files whose filename (based on artist and title) matches the given regular expression pattern.
-l, --list Only list files, do not download them.
-s SINCE, --since SINCE
Only query songs stored since the timestamp, e.g. '1h', 'yesterday' or 'Jan 1'
YouTube Music's offline functionality relies on SQLite databases to manage metadata and encrypted media files in the exocache:
-
Offline Database: This database (
offline*.db) stores metadata about your downloaded music and videos. It contains information such as the video ID and metadata from which acache_keycan be derived for each song. Thiscache_keyacts as an internal identifier for the downloaded content. -
Entity Store Database: The entity store database (
*.entitystore) holds various types of data, including information about cached videos and the metadata required to construct acache_keyassociated with a downloaded media item. -
cached_content_index.exi: This file acts as an index that links the internalcache_key(derived from the metadata in the databases) to acache_idwhich is part of the[cache_id].0.*.v3.exocache filename. That.exofile contains the encrypted media. The index itself is also encrypted and needs the decryption key to be read.
Here's a list of potential improvements, respective pull requests are welcome.
- Album information: Extract album information and add them to the metadata. The
offline*.dbcontains the tableplaylist_videomapping each video id to a playlist id (and it seems like albums are just playlists). The tableplaylistV13contains anoffline_playlist_data_protothat seems to contain the album information. - Database copy in python: Grab the database from python to avoid the manual
adb pullcommand. - Incremental updates: Keep track of the database state and download only newly added songs. This should help to reduce the runtime. (This is partially addressed by the
--sinceflag now.) - UI automation: Run uiautomator2 to download specific music in the app, then dump it from its cache.