YouTube Music album downloader with Spotify metadata auto-tagging.
No accounts required.
GIF is at 3x speed
yubal is a self-hosted app for building a local music library. Paste a YouTube Music album URL, and yubal handles downloading, tagging, and album art — automatically.
┌──────────┐
┌─────────┐ │ Spotify │
│ YouTube │ │ metadata │
└──────▲──┘ └──▲───────┘
│ │
┌──────────────────┐
│ yubal │──────► /Artist/Year - Album
YouTube Music ─────►│ │ ├─01 - Track.opus
Album URLs │ (yt-dlp + beets) │ ├─02 - Track.opus
└──────────────────┘ ├─...
└─cover.jpg
- yt-dlp: Downloads highest available quality audio streams from YouTube.
- beets: Handles auto-tagging using Spotify metadata and ensures correct album art embedding.
- Web Interface: Clean, responsive UI for submitting albums and monitoring real-time progress.
- Job Queue: Integrated FIFO queue that processes downloads sequentially to ensure reliability and avoid rate limiting.
- Smart Auto-tagging: Automatic metadata fetching via beets, enriched by Spotify's metadata for accurate tracklists and art.
- Format Configuration: Optimized for
opus(native YouTube quality), with optional transcoding for other formats - Docker-ready: Multi-arch support (amd64/arm64) for easy deployment.
The recommended way to run yubal is via Docker Compose.
services:
yubal:
image: ghcr.io/guillevc/yubal:latest
container_name: yubal
ports:
- 8000:8000
environment:
YUBAL_TZ: UTC
# Check the Configuration section for more variables
volumes:
- ./data:/app/data # Where your music will be saved
- ./beets:/app/beets # Beets configuration and database
- ./ytdlp:/app/ytdlp # yt-dlp configuration (cookies)
restart: unless-stoppeddocker compose up -d
Open your browser to http://localhost:8000 and paste a YouTube Music album URL.
Tip
Premium Quality & Age Restrictions
To download age-restricted content or access higher bitrate audio (for Premium accounts), you must provide cookies:
- Export your cookies using a browser extension. See yt-dlp FAQ
- Save the file as
cookies.txt. - Place it in your mounted
ytdlpvolume (or upload via the Web UI).
yubal is configured via Environment Variables.
| Variable | Description | Default (Docker) |
|---|---|---|
YUBAL_HOST |
Server bind address | 0.0.0.0 |
YUBAL_PORT |
Server listening port | 8000 |
YUBAL_DATA_DIR |
Destination for tagged music | /app/data |
YUBAL_BEETS_DIR |
Location of beets db and config | /app/beets |
YUBAL_YTDLP_DIR |
Location of cookies.txt | /app/ytdlp |
YUBAL_AUDIO_FORMAT |
Output audio codec (e.g., opus, mp3) |
opus |
YUBAL_AUDIO_QUALITY |
Transcoding quality (VBR scale 0-10) | 0 (Best) |
YUBAL_TZ |
Timezone (IANA format) | UTC |
Note
Audio Transcoding
By default, yubal keeps the original opus stream from YouTube to maintain maximum quality and processing speed. Transcoding only occurs if you change YUBAL_AUDIO_FORMAT or if the source is not natively available in your chosen format.
- Cookies upload via Web UI
- Docker multi-arch support (amd64/arm64)
- Configurable audio format and quality
- Batch import (multiple URLs at once)
- Post-import webhook (trigger library scan on Gonic/Navidrome/Jellyfin)
- PWA support for mobile
- (maybe) Browse YouTube Music albums in the web app.
- (maybe) Playlist support (download full playlists)
Have a feature request? Open an issue!
If yubal is useful to you, consider supporting its development:
- Color Scheme: Flexoki by Steph Ango.
- Core Tools: This project would not be possible without yt-dlp and beets.
This software is for personal archiving only. Users must comply with YouTube's Terms of Service and applicable copyright laws.