A modular, Python-based command-line tool for downloading music from Spotify & Youtube using yt-dlp.
Features interactive menus, system checks, download management, metadata embedding, robust logging, and Spotify Web API (OAuth PKCE) playlist/liked-song loading.
NEW: Spotify Web API (OAuth PKCE) — authenticate and download directly from your Spotify playlists and Liked Songs
- Enhanced Interactive CLI menus for downloads, management, and automation
- Batch and single downloads pick and choose what you prefer
- Playlist file download: using the playlist file.
- Download from Exportify CSVs that you can get from Exportify
- Download From Youtube paste the link and download playlist or video as audio file.
- Flexible playlist downloads: whole playlists at once or individual ones.
- System resource checks (CPU, RAM, storage)
- Track management via JSON files (pending, failed, history)
- Download by artist and song name
- Configurable settings in
config.json - metadata embedding for downloaded music
- Retry failed downloads
- Duplicate detection and file organization
- Colorful terminal logs (via
colorama) - Persistent logging to
app.log - Modular, maintainable codebase
- Export library data as JSON with detailed track and album info.
- Clean up music library by removing broken, or unreadable tracks.
- Choosing audio format and target bitrate w/ quality and size impacts.
HARMONI can now load tracks directly from your Spotify account (playlists + liked songs) via the Spotify Web API.
- A Spotify account
- (Recommended) a Spotify Developer app Client ID
- A Redirect URI (default:
http://127.0.0.1:8888/callback)
This project uses Authorization Code + PKCE, so no client secret is required.
- Go to https://developer.spotify.com/dashboard
- Create an app (or select an existing app)
- In the app settings, add this Redirect URI exactly (must match byte-for-byte):
http://127.0.0.1:8888/callback
- Copy your Client ID
- Paste it into your config:
spotify_client_idinspotify-yt-dlp-downloader/config.json
These are the key settings used by the Spotify Web API workflow:
{
"spotify_client_id": "",
"spotify_redirect_uri": "http://127.0.0.1:8888/callback",
"spotify_scopes": [
"playlist-read-private",
"playlist-read-collaborative",
"user-library-read"
],
"spotify_cache_tokens": true,
"spotify_auto_refresh": true
}Notes:
spotify_scopescontrols what Spotify permissions you request.- The defaults support reading your playlists and your liked songs.
- Token caching is stored at
data/spotify_tokens.jsonwhen enabled. - Spotify no longer allows
localhostas a redirect URI; use a loopback IP like127.0.0.1.
- Run the app
- Go to: Downloads Menu → Spotify Web API (OAuth) — Playlists / Liked Songs
- Choose: Authenticate with Spotify (OAuth PKCE)
- The app will show an authorize URL and offer to open it in your browser
- After you approve, Spotify redirects to your
spotify_redirect_uri - HARMONI starts a tiny local callback server and should auto-capture the redirect.
- If the callback server cannot start (port in use / restricted environment), it will fall back to asking you to paste the full redirect URL.
After authentication, HARMONI caches the token (if enabled) and will reuse/refresh it automatically.
From the same Spotify menu:
- Download from my playlists
- Download from liked songs
You’ll be prompted to:
- pick playlists (checkbox UI)
- optionally cap the maximum tracks loaded (for large libraries)
- choose tracks to download using the per-playlist song selection UI
If you are using the Spotify Web API workflow above, you can skip this section.
If you prefer file-based workflows (CSV/JSON), HARMONI still supports Spotify exports via either Exportify or Spotify’s official data export.
NOTE: You have two options for getting Spotify data into the application:
- Official Spotify Data Export (detailed below)
- Exportify (recommended alternative - no waiting for email)
Before using HARMONI for spotify downloads, you can request your personal Spotify data from Spotify's Privacy page. Spotify will provide you with a ZIP file containing several JSON files, including one named YourLibrary.json.
This YourLibrary.json file contains your saved tracks, albums, and playlists metadata, which HARMONI can use to generate the track list and manage downloads.
How to get your Spotify data:
Go to Spotify's Privacy Request page.
Request your personal data export.
Spotify will email you a ZIP file when ready.
Extract the ZIP and locate YourLibrary.json.
Use or convert this JSON file as the basis for your data/tracks.json to run HARMONI.
Exportify is a simpler, faster way to get your Spotify playlists without waiting for Spotify's email response.
How to use Exportify:
Go to https://exportify.net/
Click "Login with Spotify" and authorize the application
Click "Export" next to your chosen playlist
Save the CSV file to the data/exportify/ folder in your project
Exportify downloads are immediately available and don't require the waiting period associated with official Spotify data exports.
This step is essential to generate the input data HARMONI needs for downloading your favorite music.
spotify-ytdlp/
│
├── main.py # Entry point, interactive menus
├── config.py # Loads config from config.json
├── config.json # User-configurable settings
├── requirements.txt # Dependencies
├── changelog.md # change log
├── app.log # Log file
├── todo.md # Development notes
├── constants.py # constants
│
├── history/
│ └── prototype.py # First version of this entire app
├── data/
│ ├── exportify # Directory where you should place your exportify csv files
│ ├── tracks.json # Track list (with artist, album, track, uri)
│ ├── playlists.json # (Optional/legacy) playlists export format
│ ├── failed_downloads.json # Tracks that failed to download
│ └── download_history.json # Downloaded tracks history
│ └── spotify_tokens.json # (Optional) cached Spotify OAuth token (Spotify Web API)
├── export/
│ ├── potyy_export_(MDY).json # export of tracks in music folder
│ └── playlist_tracklist.json # playlist in tracks format
├── downloader/
│ ├── base_downloader.py # Download logic (single, batch)
│ ├── playlist_download.py # Download playlists
│ ├── metadata.py # Embed metadata
│ ├── retry_manager.py # Retry failed downloads
│ ├── youtube_link_downloader.py # Download Directly from youtube link
│ └── __init__.py│
├── menus/ # Interactive menu modules
│ ├── automation_menu.py # Menu for automation section
│ ├── downloads_menu.py # Menu for downloads section
│ ├── main_menu.py # Menu for main section
│ ├── management_menu.py # Menu for management section
│ ├── tools_menu.py # Menu for tools section
│ └── __init__.py
+
+├── spotify_api/ # Spotify Web API (stdlib-only) OAuth PKCE + client + loaders
├── tools/
│ ├── choose_audio_format.py # pick global format for download
│ ├── compress_music.py # compress songs to a certain format
│ ├── dependency_check.py # check if your dependencies are installed
│ ├── library_cleanup.py # deletes broken track files
│ ├── library_export_json.py # all tracks in music folder as json
│ ├── open_log.py # opens app.log
│ ├── playlist_to_tracklist.py # playlist turned into tracklist format
│ └── __init__.py
├── managers/
│ ├── file_manager.py # Duplicate detection, file organization
│ ├── resume_manager.py # Resume batch downloads
│ ├── schedule_manager.py # Scheduled downloads
│ └── __init__.py
├── utils/
│ ├── logger.py # Logging utilities
│ ├── loaders.py # Loading utilities
│ ├── system.py # System resource checks
│ ├── track_checker.py # Check downloaded files
│ └── __init__.py
└── music/ # Downloaded music files
- Python 3.9+
- ffmpeg available on your system PATH (required for
yt-dlpaudio extraction/post-processing) - Internet connection (YouTube)
- Spotify Web API (recommended):
- a Spotify account
- your own Spotify Developer app Client ID
- a Redirect URI (default:
http://127.0.0.1:8888/callback)
- Legacy file-based inputs: Exportify CSVs and/or Spotify official export JSON
Prefer not installing system dependencies? Use the Docker deployment below.
-
Clone the repository:
git clone https://github.com/Ssenseii/spotify-yt-dlp-downloader.git cd spotify-ytdlp -
Create and activate virtual environment:
python3 -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate
-
Install dependencies:
python3 -m pip install -r requirements.txt
(if you use system check it'll say yt-dlp is not installed even if it is so don't worry about that until I fix that check).
-
Ensure
yt-dlpis installed:python3 -m pip install yt-dlp
For an effortless setup and launch experience, use the provided start.sh script:
./start.shThis script automatically handles:
- Virtual Environment Creation: If
.venvdoesn't exist, it creates one for you - Dependency Installation: Automatically installs all required packages from
requirements.txtwhen creating a new virtual environment - Application Launch: Activates the virtual environment and starts the application
No manual setup required! The script will guide you through the process with clear status messages.
If you'd rather not install Python/ffmpeg locally, you can run HARMONI fully inside Docker. The provided Docker setup includes system dependencies like ffmpeg and runs the same interactive questionary menus.
- Docker
- Docker Compose (recommended)
From the spotify-yt-dlp-downloader/ folder:
docker compose build
docker compose run --rm --service-ports spotify-yt-dlp-downloaderIf you have an older Docker setup,
docker-composemay be the correct command.
docker build -t spotify-yt-dlp-downloader .
docker run --rm -it \
-v "$(pwd)/data:/app/data" \
-v "$(pwd)/music:/app/music" \
-v "$(pwd)/export:/app/export" \
-v "$(pwd)/config.json:/app/config.json" \
-e TERM=xterm-256color \
spotify-yt-dlp-downloaderThe examples above mount local folders/files into the container so your library survives container restarts:
./data→/app/data(tracks/playlists/history/failed +data/exportify/*.csv)./music→/app/music(downloaded audio)./export→/app/export(JSON exports, etc.)./config.json→/app/config.json(your settings)
# Rebuild after code/dependency changes
docker compose build --no-cache
# Run again (interactive menu)
docker compose run --rm spotify-yt-dlp-downloader
# Open a shell inside the container (for debugging)
docker compose run --rm --entrypoint /bin/sh spotify-yt-dlp-downloader- This is an interactive CLI app, so you need a TTY:
- Compose already sets
stdin_open: trueandtty: true - With plain Docker, always use
-it
- Compose already sets
- If the checkbox menus don’t respond, try a real terminal (not a basic IDE console) and ensure
TERMis set (see examples above).
If the system fails to donwload your music too frequently, make sure to run this command
```bash
python3 -m pip install --upgrade yt-dlp
```
Edit config.json to set your preferences:
{
"tracks_file": "data/tracks.json",
"playlists_file": "data/playlists.json",
"output_dir": "music",
"audio_format": "mp3",
"sleep_between": 5,
"average_download_time": 20,
"spotify_client_id": "",
"spotify_redirect_uri": "http://127.0.0.1:8888/callback",
"spotify_scopes": [
"playlist-read-private",
"playlist-read-collaborative",
"user-library-read"
],
"spotify_cache_tokens": true,
"spotify_auto_refresh": true
}data/tracks.json should contain:
{
"tracks": [
{
"artist": "Artist Name",
"album": "Album Name",
"track": "Song Title",
"uri": "spotify:track:xxxx"
}
]
}data/playlists.json should contain:
{
"playlists": [
{
"name": "Simon vol.94",
"lastModifiedDate": "2025-05-03",
"items": [
{
"track": {
"trackName": "Time of Our Lives",
"artistName": "Pitbull",
"albumName": "Globalization",
"trackUri": "spotify:track:2bJvI42r8EF3wxjOuDav4r"
},
"episode": null,
"audiobook": null,
"localTrack": null,
"addedDate": "2025-05-03"
},
]
}]
}Run the program:
# First activate the virtual environment
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Then run the program
python3 main.pyor
# Just do everything for me...
./start.shYou will see a menu with options for downloading, checking files, importing playlists, retrying failed downloads, and more.
Here's the updated Dependencies section including mutagen and schedule:
- yt-dlp - YouTube downloader
- psutil - System resource monitoring
- colorama - Colored terminal output
- mutagen - Audio metadata tagging and manipulation
- schedule - Job scheduling for periodic tasks
- Questionar - for the interactive menu
- Shutil - for systems stuff
Install all:
python3 -m pip install -r requirements.txtor
./start.sh- Terminal output is colored for readability
app.logstores a full log history of actions, warnings, and errors
This tool is for personal use only.
Ensure you respect copyright laws and YouTube's terms.
This project is licensed under the MIT License — see the LICENSE file for details.

