A Node.js web application that migrates your Spotify playlists to YouTube Music with a preview and review workflow.
- 🔐 OAuth Login - Secure authentication for Spotify and YouTube
- 📋 Playlist Browser - View and select your Spotify playlists
- 🔍 Analysis Queue - Pre-analyze tracks before migration with rate limiting
- 👀 Review & Edit - Side-by-side comparison of matches, add manual links for missing tracks
- 🔄 Real-time Progress - Live updates via Server-Sent Events
- 💾 Persistent Cache - Search results cached to disk, survives restarts
- 📊 Quota Optimization - Rate limiting and caching to preserve YouTube API quota
- 🎨 Modern UI - Dark theme with glassmorphism design
- 🐳 Docker Ready - Easy deployment with Docker Compose
- Go to Spotify Developer Dashboard
- Create a new application
- Add
http://localhost:3000/auth/spotify/callbackto Redirect URIs - Copy your Client ID and Client Secret
- Go to Google Cloud Console
- Create a new project (or select existing)
- Enable YouTube Data API v3
- Go to Credentials → Create Credentials → OAuth 2.0 Client ID
- Configure OAuth consent screen (External, add your email as test user)
- Create OAuth client ID (Web application)
- Add
http://localhost:3000/auth/youtube/callbackto Authorized redirect URIs - Copy your Client ID and Client Secret
# Clone the repository
git clone https://github.com/MrUnknownDE/sptify2yt.git
cd sptify2yt
# Install dependencies
npm install
# Copy environment template and add your API credentials
cp .env.example .env
nano .env # or use your preferred editor
# Start the server
npm startOpen http://localhost:3000 in your browser.
# Clone the repository
git clone https://github.com/MrUnknownDE/sptify2yt.git
cd sptify2yt
# Copy and configure environment
cp .env.example .env
nano .env
# Build and run
docker compose up -d
# View logs (optional)
docker compose logs -fOpen http://localhost:3000 in your browser.
To stop: docker compose down
All settings are configured via environment variables (.env file):
| Variable | Default | Description |
|---|---|---|
SPOTIFY_CLIENT_ID |
- | Spotify OAuth Client ID |
SPOTIFY_CLIENT_SECRET |
- | Spotify OAuth Client Secret |
YOUTUBE_CLIENT_ID |
- | Google OAuth Client ID |
YOUTUBE_CLIENT_SECRET |
- | Google OAuth Client Secret |
SESSION_SECRET |
- | Random string for session encryption |
PORT |
3000 |
Server port |
BASE_URL |
http://localhost:3000 |
Base URL for OAuth callbacks |
CACHE_PATH |
./cache |
Directory for persistent cache |
MAX_PLAYLIST_SIZE |
500 |
Maximum tracks per playlist |
RATE_LIMIT_DELAY_MS |
2000 |
Delay between YouTube API calls (ms) |
- Login - Connect your Spotify and YouTube accounts
- Select Playlist - Choose a Spotify playlist to migrate
- Analyze - Click "Analyze Playlist" to search for YouTube matches
- Review - View side-by-side comparison:
- ✅ Found - Track matched on YouTube
- ❌ Not found - Add a manual YouTube link
- Migrate - Start the migration to create the YouTube playlist
The app uses two levels of caching:
- Analysis Jobs - Complete analysis results saved to
./cache/job_*.json - Search Cache - Individual YouTube search results saved to
./cache/search_cache.json
Search results are cached for 30 days. If you analyze the same track again (even in a different playlist), it uses the cached result without making a new API call.
YouTube Data API has a daily quota of 10,000 units. Each search costs ~100 units, allowing approximately 100 searches per day.
| Feature | Savings |
|---|---|
| Search Cache | Reuses results for duplicate tracks |
| Rate Limiting | 2s delay prevents burst usage |
| Pre-Analysis | Only searches once, migration uses cached data |
| Manual Links | Skip API calls for unknown tracks |
sptify2yt/
├── src/
│ ├── server.js # Express server with SSE
│ ├── routes/
│ │ ├── auth.js # OAuth routes
│ │ ├── spotify.js # Spotify API routes
│ │ └── youtube.js # YouTube API + migration
│ ├── services/
│ │ ├── analysisQueue.js # Job queue with persistence
│ │ └── searchCache.js # YouTube search cache
│ └── public/
│ ├── index.html # SPA frontend
│ ├── styles.css # Dark theme styles
│ └── app.js # Frontend logic
├── cache/ # Persistent cache (auto-created)
├── .env.example # Environment template
├── Dockerfile
├── docker-compose.yml
└── package.json
- YouTube Music Playlists - YouTube and YouTube Music share playlists, so migrated playlists appear in both
- Track Matching - Searches for "Artist - Track Name" in YouTube's Music category
- Manual Links - For rare/unavailable tracks, paste any YouTube video URL
- Cache Cleanup - Jobs older than 7 days and search results older than 30 days are automatically cleaned up
MIT