Sunnify Spotify Playlist Downloader: download Spotify playlists, albums, and tracks to local MP3s with artwork and tags

Sunnify · Spotify Playlist Downloader

Download Spotify playlists, albums, and tracks to local MP3s with embedded artwork and tags.
Free, open source, cross-platform. Point-and-click desktop app with a built-in headless CLI. No account, no subscription.

Latest release Total downloads GitHub stars Runs on macOS, Windows, and Linux Tests status License

Download  ·  Features  ·  How to use  ·  Build from source  ·  Disclaimer
> [!CAUTION] > **Educational / student portfolio project.** Sunnify is a technical demonstration, not a piracy tool. Use it only for content you own or are permitted to download, and only where doing so is legal in your jurisdiction. See the [full legal disclaimer](#legal-disclaimer) and [DISCLAIMER.md](DISCLAIMER.md). --- ## What is Sunnify? **Sunnify is a free, open-source Spotify playlist downloader for macOS, Windows, and Linux.** Paste any Spotify playlist, album, or track link and Sunnify saves it as local audio files (MP3, M4A, FLAC, Opus, or WAV) with the cover art, title, artist, album, year, and track number written straight into the file's tags. No Spotify account, no API keys, no separate FFmpeg install, and nothing that requires a terminal unless you want one. It is a desktop GUI built with Python and PyQt6, and every binary doubles as a headless [CLI](docs/CLI.md) for scripts, servers, and AI agents. Metadata is read from Spotify's public pages and audio is sourced and transcoded locally, so everything runs on your own machine.
Sunnify desktop app downloading a Spotify playlist to local MP3s
--- ## Download | Platform | Get it | Notes | | :--- | :--- | :--- | | **macOS (Apple Silicon)** | [`Sunnify-macOS.zip`](https://github.com/sunnypatell/sunnify-spotify-downloader/releases/latest) or Homebrew (below) | M-series Macs, macOS 13+ | | **macOS (Intel)** | [`Sunnify-macOS-Intel.zip`](https://github.com/sunnypatell/sunnify-spotify-downloader/releases/latest) or Homebrew (below) | Intel Macs, macOS 13+ | | **Windows** | [`Sunnify-Windows.exe`](https://github.com/sunnypatell/sunnify-spotify-downloader/releases/latest) | Run directly, no install | | **Linux** | [`Sunnify-Linux`](https://github.com/sunnypatell/sunnify-spotify-downloader/releases/latest) | `chmod +x Sunnify-Linux` then run | | **CLI (all platforms)** | Ships inside every binary above ([CLI reference](docs/CLI.md)) | [One-liners below](#command-line-headless) put `sunnify` on your PATH | Homebrew picks the right architecture automatically. Intel builds ride GitHub's final x86_64 runner image ([`macos-15-intel`](https://github.com/actions/runner-images/issues/13045), supported until August 2027), covering Intel Macs through the rest of their supported life. FFmpeg is bundled inside every prebuilt app, so there is nothing else to install. ### Homebrew (macOS) ```bash brew tap sunnypatell/sunnify https://github.com/sunnypatell/sunnify-spotify-downloader brew install --cask sunnypatell/sunnify/sunnify ``` The cask verifies the download's checksum and clears macOS quarantine for you, so the app opens normally on first launch. It also puts the `sunnify` command on your PATH. Use the full `sunnypatell/sunnify/sunnify` name as written. Homebrew only loads casks from third-party taps that you name explicitly, and naming it once is what lets a plain `brew upgrade` keep Sunnify current afterwards. If `brew upgrade` ever stops finding new versions, remove and re-add it: `brew uninstall --cask sunnify && brew untap sunnypatell/sunnify`, then run the two commands above again. Your settings and downloaded music are untouched. ### Command line (headless) Every Sunnify binary doubles as a headless CLI: same engine, same settings, no window. ```bash sunnify download "https://open.spotify.com/playlist/..." # or album/track sunnify info "" --json # metadata only sunnify doctor # self-check ``` Each one-liner below is a complete install: it fetches the latest release (the app and CLI are one binary) and puts the `sunnify` command on your PATH. No admin rights, checksum-verified, and identical to the commands in the [CLI reference](docs/CLI.md), so run them from either page. Already downloaded the app? You already have the CLI; the one-liner just adds the `sunnify` command name to your terminal. ```bash # macOS / Linux curl -fsSL https://raw.githubusercontent.com/sunnypatell/sunnify-spotify-downloader/main/scripts/install.sh | sh ``` ```powershell # Windows iwr -useb https://raw.githubusercontent.com/sunnypatell/sunnify-spotify-downloader/main/scripts/install.ps1 | iex ``` Full reference (commands, flags, NDJSON output for scripts and AI agents, exit codes) in [docs/CLI.md](docs/CLI.md).
macOS: opening the app from a direct download The app is ad-hoc signed but not notarized (notarization needs a paid Apple Developer account; this is an unfunded student project). The Homebrew install above is friction-free. For a direct `.zip` download from the Releases page, remove the quarantine flag once: ```bash xattr -r -d com.apple.quarantine /Applications/Sunnify.app ``` Or use Gatekeeper's flow: double-click once, then **System Settings → Privacy & Security → Open Anyway** (macOS Sequoia and later removed the old right-click-Open shortcut).
--- ## Features - **Playlists, albums, and single tracks.** Paste a normal link, an `intl-xx` locale link, or a `spotify:` URI copied from the desktop app. Each playlist or album downloads into its own folder. - **Five audio formats.** MP3, M4A, Opus (lossy at 128 / 192 / 256 / 320 kbps) and FLAC / WAV (lossless conversion of the source, see [Audio quality](#audio-quality)). Your choice is remembered between sessions. - **Real metadata, written correctly.** Title, artist(s), album, year, and track number are embedded for every format, with the front cover art baked in. MP3 tags are written for maximum player compatibility, so artwork and tags show up everywhere, including older car head-units, stock Android, and Windows Media Player. - **Per-track cover art.** Each song gets its own artwork, not one shared playlist cover. - **Parallel downloads.** Multiple songs download at once, so a playlist finishes much faster, with a cooperative Stop that takes effect immediately. - **Resume large playlists.** A per-folder manifest records what already landed, so a playlist throttled by rate limits finishes across multiple sessions instead of starting over. - **Filenames your way.** `Song - Artist`, `Artist - Song`, or just `Song` (the artist stays in the tags), with optional `01.` track-number prefixes so folders sort in playlist order. A live preview in Settings shows the result as you toggle. - **Unicode-safe filenames.** Accented, CJK, and Cyrillic titles are preserved; only characters your filesystem actually rejects are stripped. - **Accurate audio matching.** Sunnify matches on title, artist, and duration rather than grabbing the first search hit, so you get the real recording, not a remix or a sped-up edit. - **Bundled FFmpeg, no account.** Everything needed ships inside the app, and nothing asks you to log in. - **A way through YouTube's bot check.** If YouTube refuses your network, Sunnify says so plainly, and you can opt in to using cookies from your own YouTube session. Sunnify only reads the file, never changes it. See [YouTube cookies](docs/CLI.md#youtube-cookies). - **Headless CLI built in.** `sunnify download ` scripts every feature of the app: machine-readable output, meaningful exit codes, resume, and a `doctor` self-check. Made for terminals, cron jobs, and AI agents. See [docs/CLI.md](docs/CLI.md).
Sunnify settings showing audio format and quality options
--- ## How to use 1. **Copy a Spotify link** for a playlist, album, or track (the Share menu, or copy the URL from your browser). 2. **Paste it** into Sunnify. 3. **Pick a format and quality** in Settings, and choose where files should go (defaults to your Music folder). 4. **Download.** Watch per-track progress; press Stop anytime. Your downloads land in a folder named after the playlist or album, tagged and ready for any music library. --- ## Build from source Requires **Python 3.10+**. FFmpeg must be available (bundled in the prebuilt apps; otherwise install via Homebrew, your package manager, or PATH). ```bash git clone https://github.com/sunnypatell/sunnify-spotify-downloader.git cd sunnify-spotify-downloader pip install -r req.txt python Spotify_Downloader.py ``` To produce a standalone app with [PyInstaller](https://pyinstaller.org/): ```bash pip install pyinstaller pyinstaller Sunnify.spec # output in dist/ ``` --- ## Verify your download Every release since 2.0.8 ships a verifiable supply-chain trail. Each binary carries **SLSA Build Level 3 provenance** binding it to the exact source commit and the isolated builder workflow, plus a CycloneDX SBOM and offline Sigstore bundles, all logged to the public Rekor transparency log. ```bash # plain checksums, no extra tooling sha256sum -c checksums.txt --ignore-missing # cryptographic provenance (GitHub CLI) gh attestation verify Sunnify-Linux --repo sunnypatell/sunnify-spotify-downloader ``` Full details and the threat model are in [SECURITY.md](SECURITY.md#release-integrity). --- ## How it works Sunnify reads track metadata from Spotify's public embed pages (no authentication), finds the matching audio via a YouTube search through [yt-dlp](https://github.com/yt-dlp/yt-dlp), transcodes it to your chosen format with the bundled FFmpeg, and writes the tags and cover art with [Mutagen](https://mutagen.readthedocs.io/). It is a pure-Python core wrapped in a PyQt6 interface, packaged per-platform with PyInstaller. --- ## Troubleshooting These come up again and again. Each one links the issue where it was investigated in full. ### Audio quality Every format is encoded from YouTube's best audio stream for the track: about 128 kbps AAC or Opus, with an encoder cutoff near 20 kHz. Your format and bitrate pick the conversion, not the source. A 320 kbps MP3 keeps as much of that stream as MP3 can, and FLAC or WAV keep all of it with nothing further lost, but no setting adds detail the stream never had. So a spectrogram (Spek) showing nothing above roughly 20 kHz, or Fakin' the Funk calling the file a transcode, is reading the source correctly. Sample rate is a separate setting: YouTube serves 48 kHz, and Settings can convert to 44.1 kHz. See [#93](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/93), [#116](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/116). ### A different song was downloaded A YouTube result is only accepted when its title matches the Spotify track, the artist appears in it, and its length is within 30 seconds; otherwise the track is skipped rather than guessed. **Use closest result if no match** in Settings trades that for coverage by falling back to the closest length, which is where covers and remixes get in. A re-upload of the same recording with a voice tag over it can't be told apart by its metadata. If a song still comes down wrong with that setting off, open an issue with its Spotify link. See [#45](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/45), [#52](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/52), [#93](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/93). ### Some tracks failed The counter shows how many failed, and `sunnify.log` (Settings, **Open logs folder**) names each one with the reason. Paste the same link into the same folder to retry: tracks already on disk are skipped. See [#113](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/113). ### YouTube is refusing this network YouTube sometimes asks a whole network to prove it isn't a bot and then refuses every download from it. Another network usually clears it; otherwise use [YouTube cookies](docs/CLI.md#youtube-cookies). See [#95](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/95), [#112](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/112). ### Antivirus flags the Windows download A few engines flag executables built with PyInstaller by how they are packaged rather than what they do, and every release is a new file to them. Compare the file's SHA256 with `checksums.txt` on the release page and check its provenance (see [Verify your download](#verify-your-download)). See [#102](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/102), [#103](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/103). ### A link says it's unavailable Spotify serves an error page for private, removed, and region-locked items, and for every link in countries where it doesn't operate. Sunnify reports that instead of failing with a parser error. See [#94](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/94). ### Artist or discography links Not supported: Spotify's public pages only list an artist's top 10 tracks. Paste each album link, or add the albums to a public playlist and paste that. See [#90](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/90), [#114](https://github.com/sunnypatell/sunnify-spotify-downloader/issues/114). --- ## Legal Disclaimer ### This is a student portfolio project, not a piracy tool > **Sunnify was built solely as an educational demonstration of software engineering.** It exists to showcase technical skills for academic and portfolio purposes. The developer does not condone, encourage, or support copyright infringement or piracy. It demonstrates desktop application and headless CLI development with Python and PyQt6, public-API integration and reverse engineering, multi-threaded architecture, and a hardened CI/CD release pipeline. It is provided free of charge as an open-source educational resource, not for commercial use. ### Terms of use By downloading, installing, or using this software, you agree that: 1. **Personal use only.** Use it for content you own, have purchased, or have explicit permission to download. Downloading copyrighted material without authorization may violate the law where you live. 2. **You are responsible for compliance** with the laws of your country, state, or region. Some jurisdictions permit personal/backup downloads; others do not. 3. **No warranty.** The software is provided "as is," without warranty of any kind. 4. **Limitation of liability.** The developer is not liable for any damages or legal consequences arising from use or misuse. You assume all risk. 5. **No endorsement of piracy.** This is a technical demonstration and must be used responsibly and legally. ### Acceptable vs. not - ✅ Format-shifting music you have purchased elsewhere - ✅ Personal backups of content you own - ✅ Research into API design and audio processing, and learning software development - ❌ Distributing copyrighted content - ❌ Commercial use - ❌ Any use where such downloads are prohibited ### DMCA & takedown requests If you are a rights holder and believe this project infringes your intellectual property, email `sunnypatel124555@gmail.com` with details and I will respond promptly. This project complies with all valid takedown requests. > **If you are looking for a tool to pirate music, this is not it.** Please support artists by purchasing their music or using authorized streaming services. Use this software responsibly and legally, or do not use it at all. See [DISCLAIMER.md](DISCLAIMER.md) for the complete legal terms. --- ## Contributing Contributions, ideas, and bug reports are welcome. - Read [CONTRIBUTING.md](CONTRIBUTING.md) and the [Code of Conduct](CODE_OF_CONDUCT.md) - Open issues with clear repro steps and logs where possible - Keep PRs small and focused - Security reports: see [SECURITY.md](SECURITY.md) --- ## Author Created and maintained by **Sunny Jayendra Patel**. Questions or feedback: `sunnypatel124555@gmail.com`. Licensed under a custom educational-use license. See [LICENSE](LICENSE).