🎧 Download entire Spotify playlists to local MP3s with embedded artwork and tags. Desktop app, Python core, and a full web stack in one repo.
Caution
This software was developed as a student portfolio project for educational purposes only. It is intended to demonstrate software engineering skills including API integration, multi-threading, cross-platform development, and full-stack architecture.
By using this software, you acknowledge that:
- You will only use it in jurisdictions where downloading copyrighted content for personal use is permitted
- You are responsible for complying with all applicable laws in your region
- This tool should only be used with content you own or have explicit permission to download
- The developer assumes no liability for misuse of this software
See full disclaimer below and read DISCLAIMER.md for complete legal terms.
- Overview
- Architecture
- Features
- Requirements
- Quick Start (3 Paths)
- Desktop App Setup (Windows and cross-platform)
- Web App Setup (Backend and Frontend)
- Configuration
- Usage Guide
- Diagnostics
- Troubleshooting
- Notes and Roadmap
- ⚖️ Legal Disclaimer
- Contributing and Community
- Author
Sunnify is built to be resilient, fast, and simple:
- Uses Spotify's embed page API to fetch playlist/track metadata without credentials.
- Downloads audio via YouTube search using
yt-dlpwith FFmpeg. - Writes clean ID3 tags and embeds cover art for your library.
- Ships as a PyQt desktop app, a Flask API, and a modern Next.js web client.
- Supports both individual track and full playlist downloads (v2.0.0+).
Screenshots from the desktop app in action:
root
├─ Spotify_Downloader.py (PyQt5 desktop app)
├─ spotifydown_api.py (Spotify embed page API client)
├─ Template.py / Template.ui (Generated UI for the desktop app)
├─ scripts/
│ └─ check_api_status.py (Diagnostics for embed API and yt-dlp)
├─ dist/
│ └─ Sunnify (Spotify Downloader).exe (Prebuilt Windows executable)
├─ web-app/
│ ├─ sunnify-backend/ (Flask API: SSE + JSON responses)
│ │ ├─ app.py (/api/scrape-playlist, /api/download)
│ │ ├─ requirements.txt (Backend dependencies)
│ │ └─ Procfile (gunicorn entry)
│ └─ sunnify-webclient/ (Next.js 14 + Tailwind + shadcn/ui)
│ ├─ app/page.tsx (Renders <SunnifyApp />)
│ └─ components/sunnify-app.tsx (Main UI + API integration)
├─ req.txt (Desktop app Python deps)
├─ Sunnify (Spotify Downloader).spec (PyInstaller build spec)
└─ README.md
- 🎼 Full playlist and single track downloader (tagged MP3 library)
- 🖼️ Artwork and tagging (title, artists, album, release date, cover art)
- 🚦 Spotify embed page API (no credentials required)
- 🎯 YouTube audio via
yt-dlpwith FFmpeg conversion - 🪟 Clean desktop UI (progress, preview panel, settings, download location picker)
- 🌐 Web experience (Flask backend and Next.js client)
Pre-built apps: No dependencies required. FFmpeg is bundled.
Building from source:
- Python 3.9 or newer
- FFmpeg on PATH (for MP3 conversion)
- Node.js 18+ (for web client only)
- Internet access to
open.spotify.comand YouTube
Install FFmpeg for building from source
Windows:
winget install Gyan.FFmpegmacOS:
brew install ffmpegLinux:
sudo apt install -y ffmpeg| Platform | Download | Notes |
|---|---|---|
| Windows | Sunnify.exe | Run directly, no install needed |
| macOS | Sunnify.app | See macOS notes below |
| Linux | Sunnify | Make executable: chmod +x Sunnify |
macOS: Unsigned app instructions
The macOS app is not notarized. After downloading and extracting:
# Remove quarantine attribute (required for unsigned apps)
sudo xattr -cr /Applications/Sunnify.app
# Or if you extracted elsewhere:
sudo xattr -cr ~/Downloads/Sunnify.appIf you see "app is damaged" or "unidentified developer":
- Open System Preferences → Security & Privacy → General
- Click "Open Anyway" next to the Sunnify message
- Or run the
xattrcommand above
- Python users:
pip install -r req.txtthenpython Spotify_Downloader.py - Homebrew (macOS):
brew tap sunnypatell/sunnify https://github.com/sunnypatell/sunnify-spotify-downloader brew install --cask sunnify
- Web stack: run the Flask backend and Next.js client under
web-app/
Windows PowerShell commands:
# Clone
git clone https://github.com/sunnypatell/sunnify-spotify-downloader.git
cd sunnify-spotify-downloader
# Create and activate a venv (recommended)
py -3 -m venv .venv; .\.venv\Scripts\Activate.ps1
# Install dependencies
pip install -r req.txt
# Ensure FFmpeg is on PATH
ffmpeg -version
# Launch the PyQt app
python .\Spotify_Downloader.pymacOS/Linux equivalent:
git clone https://github.com/sunnypatell/sunnify-spotify-downloader.git
cd sunnify-spotify-downloader
python3 -m venv .venv && source .venv/bin/activate
pip install -r req.txt
ffmpeg -version
python Spotify_Downloader.pyBuild a Windows EXE with PyInstaller:
.\.venv\Scripts\Activate.ps1
pyinstaller "Sunnify (Spotify Downloader).spec"Output files are placed in dist/.
cd web-app\sunnify-backend
py -3 -m venv .venv; .\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python .\app.py
# Serves on http://127.0.0.1:5000Endpoints:
POST /api/scrape-playlistprocesses a playlist and emits progress or completion events.GET /api/download/<filename>?path=<dir>serves a file from a directory.
The local server can stream Server-Sent Events (SSE). Each event looks like:
{"event":"progress"|"complete"|"error","data":{...}}.
Production style run with gunicorn:
pip install gunicorn
gunicorn app:app --bind 0.0.0.0:5000cd ..\sunnify-webclient
npm install
npm run dev
# Opens http://localhost:3000Configure API base in .env.local (recommended):
NEXT_PUBLIC_API_BASE=http://127.0.0.1:5000Then update components/sunnify-app.tsx to use process.env.NEXT_PUBLIC_API_BASE + '/api/scrape-playlist'.
Local production simulation:
npm run build
npm startNote: the web client points to a Render-hosted backend by default. The free tier spins down after inactivity, so the first request may take up to 50 seconds. For local development, update the API URL in components/sunnify-app.tsx.
NEXT_PUBLIC_API_BASEbase URL for the webclient backend (set via.env.local)- Desktop app download location: click the ⚙ (settings) button to change
Advanced configuration tips
- Corporate networks may block
open.spotify.com. Allowlist this domain. - Increase request timeouts only if your network is unusually slow. See
spotifydown_api.pyfor defaults. - Ensure download paths have write permissions.
Desktop app (GUI):
- Launch Sunnify.
- Paste a Spotify URL:
- Playlist:
https://open.spotify.com/playlist/<ID> - Single track:
https://open.spotify.com/track/<ID>
- Playlist:
- Click the green Download button (or press Enter) to start.
- Optional: click ⚙ to change download location.
- Optional: enable Show Preview to see the cover and meta.
- Optional: enable Add Meta Tags to embed ID3 and artwork.
- Output appears in your chosen download folder (default:
music/).
Web client:
- Start Flask backend and Next.js client.
- Open
http://localhost:3000. - Enter playlist URL and a writable download path.
- Click Process Playlist and watch progress.
SpotifyEmbedAPIfetches playlist/track data from Spotify's embed pages (/embed/playlist/{id},/embed/track/{id}).- Extracts
__NEXT_DATA__JSON blob containing full track metadata without authentication. - For playlists >100 tracks, uses spclient API with anonymous tokens from embed pages.
PlaylistClientis a high-level wrapper providing simple methods for common operations.
For each track:
- Fetch metadata from Spotify embed page.
- Search YouTube:
ytsearch1:<title> <artists> audio. - Download and convert to MP3 (
yt-dlpplus FFmpeg). - Write ID3 tags (Mutagen) with title, artist, album, date.
- Embed cover art (from track or playlist metadata).
POST /api/scrape-playlistcan stream JSON events (SSE) while processing.- Completion event includes
playlistNameandtrackswith download links.
Validate Spotify embed API and yt-dlp from your network:
python .\scripts\check_api_status.pyExample output shows embed API status, large playlist fallback, and YouTube search results. See API_STATUS.md for details.
- FFmpeg not found: install FFmpeg and restart terminal so PATH updates.
- yt-dlp errors:
pip install -U yt-dlpand ensure YouTube is reachable. - URL rejected: format must be
https://open.spotify.com/playlist/<ID>orhttps://open.spotify.com/track/<ID>. - Embed API fails: check if
open.spotify.comis accessible from your network. - Hosted backend cold starts: free tiers can sleep; first call might take seconds.
- Permission errors: choose a download path you have write access to.
- macOS "app is damaged": run
sudo xattr -cr /path/to/Sunnify.appto remove quarantine. - macOS "unidentified developer": open System Preferences → Security & Privacy → click "Open Anyway".
Important note (hosted backends): on free compute plans, the backend might sleep and take a moment to wake on the first request.
Coming soon:
- Apple Music and iTunes import
- Android MTP copy support
- Webclient SSE progress UI
IMPORTANT: This software was developed solely as an educational demonstration of software engineering concepts. It exists to showcase technical skills for academic and portfolio purposes. The developer does not condone, encourage, or support any form of copyright infringement or piracy.
Sunnify was created as a student portfolio project to demonstrate proficiency in:
- Full-stack software development (Python, Flask, Next.js, PyQt5)
- API design and reverse engineering
- Multi-threaded application architecture
- Cross-platform desktop application development
- CI/CD pipelines and automated testing
This project is provided free of charge as an open-source educational resource. It is not intended for commercial use or to facilitate copyright infringement.
By downloading, installing, or using this software, you agree to the following:
-
Personal Use Only: This software is intended for downloading content you already own, have purchased, or have explicit permission to download. Downloading copyrighted material without authorization may violate laws in your jurisdiction.
-
Jurisdictional Compliance: You are solely responsible for determining whether your use of this software complies with applicable laws in your country, state, or region. Some jurisdictions permit downloading copyrighted content for personal/backup purposes; others do not.
-
No Warranty: This software is provided "as is" without warranty of any kind, express or implied. The developer makes no guarantees regarding functionality, reliability, or fitness for any particular purpose.
-
Limitation of Liability: The developer shall not be held liable for any damages, legal consequences, or other liabilities arising from the use or misuse of this software. Users assume all risks associated with its use.
-
No Endorsement of Piracy: This project does not endorse, encourage, or facilitate piracy or copyright infringement. It is designed as a technical demonstration and should be used responsibly and legally.
This project may be used for:
- ✅ Downloading music you have purchased elsewhere for format-shifting
- ✅ Creating personal backups of content you own
- ✅ Educational research into API design and audio processing
- ✅ Learning software development techniques
- ❌ NOT for distributing copyrighted content
- ❌ NOT for commercial purposes
- ❌ NOT in jurisdictions where such downloads are prohibited
By downloading, installing, or using this software, you acknowledge that:
- You alone are responsible for how you use this software
- You will comply with all applicable laws in your jurisdiction
- You understand that unauthorized downloading of copyrighted content may be illegal
- You accept that the developer bears no responsibility for your actions
- You have read and agree to the full terms in DISCLAIMER.md
If you are a rights holder and believe this project infringes on your intellectual property, please contact sunnypatel124555@gmail.com with details, and I will respond promptly. This project will comply with all valid takedown requests.
See SECURITY.md for reporting security vulnerabilities and LICENSE for license terms.
If you are looking for a tool to pirate music, this is not it. This project exists purely as a technical demonstration. The developer strongly encourages supporting artists by purchasing music through legitimate channels or using authorized streaming services. Use this software responsibly and legally, or do not use it at all.
Contributions, ideas, and bug reports are welcome.
- Read the CODE_OF_CONDUCT and CONTRIBUTING
- Open issues with clear repro steps and logs where possible
- Prefer small, focused PRs
Created and maintained by Sunny Jayendra Patel. Reach me at sunnypatel124555@gmail.com or connect on LinkedIn.

