This project creates private YouTube Music playlists from curated Taylor Swift song lists. It uses ytmusicapi to authenticate to YouTube Music, search for each song, create a playlist, and add the songs in small batches.
Important security warning:
browser.jsoncontains Google/YouTube Music session credentials, including cookies and authorization headers. Treat it like a password. Do not commit it, upload it, paste it into an issue, or share it with anyone. The current copy in this project should be considered exposed: sign out of the relevant Google sessions or revoke/rotate the credentials, then generate a freshbrowser.jsonbefore running or publishing this project.
When run, the script:
- Loads playlist names and songs from
ts-extremes-songs.json. - Connects to YouTube Music using authenticated browser headers.
- Searches for each title using
Taylor Swift <title>and thesongsfilter. - Creates a private playlist for each top-level JSON key.
- Adds found tracks in batches of five, waiting one second between batches.
- Prints tracks that could not be found instead of stopping the whole run.
The script currently loads ts-extremes-songs.json. ts-mood-songs.json is included as a second catalog, but it is not used by app.py until you change the PLAYLISTS assignment.
- Python 3.10 or newer. The code uses the
str | Nonetype syntax. - A Google account with access to YouTube Music.
- A desktop browser where that Google account is signed in to music.youtube.com.
- A valid authenticated
browser.jsonfile generated from your own browser session.
ytmusicapi is an unofficial client. It is not the official YouTube Data API, and its authentication format can stop working when YouTube changes its web application.
From the project directory, create and activate a virtual environment:
cd /path/to/yt-music
python3 -m venv .venv
source .venv/bin/activateOn Windows PowerShell, use:
.venv\Scripts\Activate.ps1Install the dependency:
python -m pip install --upgrade pip
python -m pip install ytmusicapiFor reproducible installs, record the currently working version:
python -m pip freeze > requirements.txtAt minimum, the dependency is:
ytmusicapi==1.11.5
There is no separate YouTube Music API key for this script. browser.json is a snapshot of authenticated browser request headers. It contains the session information that lets ytmusicapi act as your signed-in account.
-
Open music.youtube.com in your browser.
-
Sign in to the Google account that should own the new playlists.
-
Open Developer Tools:
- Chrome/Edge:
Cmd+Option+Ion macOS orCtrl+Shift+Ion Windows/Linux. - Firefox:
Cmd+Option+Ion macOS orCtrl+Shift+Ion Windows/Linux.
- Chrome/Edge:
-
Open the Network tab and reload YouTube Music.
-
Find a request to YouTube Music, such as a request whose URL contains
browseorsearch. -
Inspect the request headers and copy the complete request headers as raw text. In Chromium browsers, right-click the request and choose Copy > Copy request headers.
-
From the project directory, run:
python -c "import ytmusicapi; ytmusicapi.setup(filepath='browser.json')" -
Paste the copied headers when prompted. The command writes a new
browser.jsonin the project directory. -
Check that the generated file is not empty and that it is ignored by Git before running the application.
If your installed ytmusicapi version does not offer the interactive setup command, follow the ytmusicapi browser authentication documentation for that version. Do not copy only one cookie or invent a token: the complete current request headers are required.
Do not print the contents of browser.json. A minimal check is:
python -c "from ytmusicapi import YTMusic; print(len(YTMusic('browser.json').get_library_playlists()), 'playlists visible')"If this prints a playlist count, the session can read your YouTube Music library. If it raises an authentication error, generate a new file while signed in to the correct account.
Browser credentials expire or are invalidated when you sign out, change your password, revoke sessions, or when YouTube changes its request format. Delete the local browser.json, repeat the setup steps, and use the newly generated file. Never ask another person to send you their file.
Because the existing project file contains session credentials, rotate them before using this checkout:
- In your Google Account, review Security > Your devices and Security > Recent security activity.
- Sign out of unfamiliar or affected browser sessions.
- Change the Google password if the credentials may have been shared publicly.
- Generate a new local
browser.jsonafter signing in again.
The application currently creates the client with:
YTMusic("browser.json", "112811052418945050520")The second positional argument is the user value, not an API key. For a normal single-account browser session, the simpler form is usually enough:
YTMusic("browser.json")If you use multiple Google accounts, keep the appropriate account selector for your session and verify it with a harmless library-read test before creating playlists.
To use the mood catalog instead of the extremes catalog, change:
PLAYLISTS = json.load(open("ts-extremes-songs.json", "r"))to:
PLAYLISTS = json.load(open("ts-mood-songs.json", "r"))The script creates a playlist for every top-level key in the selected JSON file. Running it again creates new playlists; it does not look for or update previously created playlists.
With the virtual environment active and a valid browser.json present:
python app.pyYou should see a connection message, the number of playlists visible to the account, and progress for each playlist. The created playlists are private by default.
The script performs real account changes. It can create multiple playlists and add many tracks. There is no dry-run mode or automatic cleanup, so review the JSON files before running it.
Each catalog is a JSON object. Keys become playlist names, and values are lists of song objects:
{
"extreme_sad": [
{
"song": "Come In With The Rain (Taylor's Version)",
"bpm": 72,
"score": 10
}
]
}The script uses the song field. bpm and score are metadata for curation and are not sent to YouTube Music. A plain string is also accepted by create_playlist_with_songs, although the checked-in catalogs use objects:
{
"my_playlist": ["Lover", "Enchanted (Taylor's Version)"]
}Use exact or distinctive titles where possible. Search results are selected by the first result with a videoId, so similarly named tracks, live versions, remixes, and alternate versions may need careful naming.
Run the authentication setup from the project directory and confirm the file is named exactly browser.json.
The browser session is stale, incomplete, or belongs to the wrong account. Sign in again, generate a fresh file from current request headers, and verify it with the library-read command above.
Activate .venv and install the dependency with python -m pip install ytmusicapi. Using python -m pip helps ensure pip installs into the interpreter that runs app.py.
Search is title-based and depends on YouTube Music results. Try the official title, include (Taylor's Version) where relevant, or adjust search_song to inspect more than five results. A missing match does not prevent the remaining tracks from being added.
The script intentionally creates a new playlist every run. Delete duplicates manually in YouTube Music, or add playlist lookup/update logic before running it repeatedly.
Reduce the run frequency, keep the batch size modest, and increase the delay between requests. Do not run multiple copies concurrently against the same account.
Add these files to .gitignore before creating a repository or pushing changes:
.venv/
__pycache__/
*.py[cod]
browser.jsonIf browser.json has already been committed or shared, adding it to .gitignore is not enough: remove it from repository history and rotate the affected Google sessions. Also remove hard-coded account identifiers from app.py when they are not needed.
- This is an unofficial YouTube Music integration and may break after upstream changes.
- Authentication is tied to browser session credentials and must be refreshed periodically.
- Search matching is heuristic and does not guarantee the intended recording.
- Runs are not idempotent: each run creates new playlists.
- Only
ts-extremes-songs.jsonis loaded by default. - There are no automated tests because the main behavior makes live YouTube Music account changes.
Contributions are welcome. Feel free to open an issue to report a bug or suggest an improvement, or submit a pull request with a focused change. Please include clear reproduction steps for fixes and verify the extension by loading it in Chrome before opening a pull request.