Skip to main content

SpotiFLAC Python Module

Fetch Spotify track metadata and retrieve matching lossless audio through configurable Tidal, Qobuz & Amazon Music provider backends. Integrate directly into your Python projects, build custom Telegram bots, automation tools, or bulk downloaders.

Disclaimer

This project is intended for educational and personal use only. The developer does not condone or encourage copyright infringement.

SpotiFLAC-Module-Version is an independent, third-party tool and is not affiliated with, endorsed by, or connected to Spotify, Tidal, Qobuz, Amazon Music, Deezer, or any other streaming service.

You are solely responsible for:

  1. Ensuring your use of this software complies with your local laws.
  2. Reading and adhering to the Terms of Service of the respective platforms.
  3. Any legal consequences resulting from the misuse of this tool.

The software is provided "as is", without warranty of any kind, express or implied. The author assumes no liability for any bans, damages, or legal issues arising from its use or misuse. Users assume all risk associated with its use.

If you are a copyright holder or an authorized representative and believe this repository infringes upon your rights, please contact the maintainer with sufficient detail (including relevant URLs and proof of ownership); the matter will be promptly investigated.


Looking for a standalone app?


Features

  • Native synchronous and asynchronous Python APIs
  • Modular JavaScript Extension system
  • Automatic provider fallback
  • Built-in GUI
  • Interactive CLI Wizard
  • Docker support
  • Configuration Profiles
  • MusicBrainz metadata enrichment
  • Embedded synchronized lyrics
  • Optional MP3 320 kbps transcoding

Installation

pip install SpotiFLAC

Quick Start

SpotiFLAC can be used in multiple ways. Choose the mode that fits your needs.

GUI Mode (recommended for most users)

Launch the graphical user interface with the --gui flag:

spotiflac --gui

(Or python launcher.py --gui if running from source)

Interactive Mode (step-by-step wizard)

SpotiFLAC features a smart Interactive Wizard that guides you step-by-step. To launch the wizard, use the --interactive flag:

spotiflac --interactive

(Or python launcher.py --interactive if running from source)

On launch it automatically runs a service health check before asking any questions, so you always know which providers are reachable.

What the wizard does at startup:

  • Service Health Check — probes provider endpoints and shows provider availability inline (✅ / ❌) before asking anything
  • URL History — shows your last 8 downloads so you can re-run one with a single keypress
  • Folder Memory — remembers your last output directory and offers it as the default
  • Profile Load — optionally restores a full saved configuration

Smart URL Detection: If you input an Artist URL, it will ask if you want to download "Featuring" tracks. It skips this question for albums or playlists.

Smart File Paths: If you input a Single Track URL, it will ask if you want to set a specific .flac output path. If you do, it intelligently skips all questions about filename formatting and subfolder organization.

Unified Quality Profiles: Automatically translates your desired quality tier across different services (like Tidal and Qobuz).

CLI Generator: At the end of the configuration, it generates and prints the exact CLI command for your specific setup, so you can copy and reuse it in your automated scripts.

Profile Save: After confirming the download, you can save the entire configuration as a named profile to reuse later.

Python API (Synchronous)

The classic synchronous API remains the simplest way to integrate SpotiFLAC into your own applications.

from SpotiFLAC import SpotiFLAC

SpotiFLAC(
    url="https://open.spotify.com/track/TRACK_ID",
    output_dir="./downloads",
    services=["tidal"],
)

This API is fully backwards-compatible with previous releases and is recommended for scripts and applications that do not require asynchronous execution.

Which API should I use?

API Best for
SpotiFLAC Scripts, CLI wrappers, automation
AsyncSpotiFLAC Discord bots, Telegram bots, FastAPI, asyncio applications

Asynchronous API

SpotiFLAC now features a 100% native asynchronous engine, making it ideal for modern Python applications built on asyncio, including:

  • Discord bots
  • Telegram bots
  • FastAPI applications
  • Quart / Sanic web servers
  • Background workers
  • Any asynchronous Python project

The new AsyncSpotiFLAC client uses a shared asynchronous HTTP session, allowing multiple downloads and metadata requests to run efficiently without blocking the event loop.

import asyncio
from SpotiFLAC import AsyncSpotiFLAC

async def main():
    async with AsyncSpotiFLAC(
        output_dir="./downloads",
        services=["tidal", "qobuz"],
        quality="LOSSLESS",
    ) as client:

        # Download a single track
        await client.download_track(
            "https://open.spotify.com/track/TRACK_ID"
        )

        # Fetch playlist metadata without downloading
        info, tracks = await client.get_playlist(
            "https://open.spotify.com/playlist/PLAYLIST_ID"
        )

        print(f"{info['name']} contains {len(tracks)} tracks")

asyncio.run(main())

Why use the async API?

  • Fully non-blocking (asyncio native)
  • Shared HTTP connection pooling
  • Lower memory usage
  • Much better performance when downloading multiple tracks concurrently
  • Perfect for long-running applications and web backends

Note: The classic synchronous SpotiFLAC() API remains fully supported and backwards-compatible.


JavaScript Extensions

SpotiFLAC supports modular JavaScript extensions originally developed for SpotiFLAC Mobile and now shared across all SpotiFLAC projects.

Extensions can provide alternative implementations for streaming services, allowing SpotiFLAC to continue working even when native APIs change. They are downloaded automatically, kept up to date, and transparently used as fallbacks whenever a native provider fails.

Note: If Node.js is not installed, SpotiFLAC automatically attempts to install it the first time a JavaScript extension is used.

Supported package managers:

  • Linux: apt-get, dnf, yum, pacman
  • macOS: brew
  • Windows: winget, choco

You can also explicitly prioritize an extension:

spotiflac URL ./out \
  --service ext:tidal-web ext:qobuz-web

Extensions use the ext: prefix and behave exactly like native providers. They can be mixed freely:

spotiflac URL ./out \
  --service tidal ext:qobuz-web deezer

Note: Automatic fallback to extensions is enabled by default whenever a native provider for the same service is installed as an extension. Disable it with use_extensions_fallback=False (Python) or --no-extensions-fallback (CLI) if you want SpotiFLAC to use only the explicitly requested providers in services/--service.


Docker Usage & Headless Automation

A lightweight, CLI-focused Docker image is available for running SpotiFLAC on servers, NAS devices, or any headless environment.

Build the Image

docker build -t spotiflac .

Basic Docker Usage

Run a download by mounting local directories to persist your downloads, configuration, cache, and extension registry across container restarts:

docker run --rm -it \
  -v "$(pwd)/downloads:/app/downloads" \
  -v "$(pwd)/.spotiflac_docker:/root/.spotiflac" \
  -v "$(pwd)/.cache_docker:/root/.cache/spotiflac" \
  spotiflac "https://open.spotify.com/track/TRACK_ID" \
  /app/downloads -s deezer -q LOSSLESS

Published Image (GHCR)

Official Docker images are published on GitHub Container Registry (GHCR), allowing you to run the latest version without building locally.

docker pull ghcr.io/bartolomeorusso9/spotiflac-module-version:latest

Logs in Headless Environments

A progress bar is a stream of carriage returns: readable on a terminal, unreadable in a log file. docker logs collapses each refresh into a [285B blob data] line, which buries everything worth reading.

SpotiFLAC therefore draws animated bars only when stderr is an interactive terminal. Everywhere else — Docker, cron, a redirected file — it prints the same information as plain lines instead:

[RUN] 24 track(s) · tidal, qobuz · LOSSLESS · 2 in parallel → /app/downloads
Track [3/24] Track Title — Artist Name (Album Name)
  ⬇  Track Title  ·  47%  ·  13.4 MB / 28.4 MB
  ✓  Track Title  ·  TIDAL  ·  FLAC  ·  28.4 MB  ·  12s

Progress lines are throttled to at most one per 25% and per 10 seconds, so a track costs a handful of lines rather than one per received chunk.

Set SPOTIFLAC_PROGRESS_BARS to override the detection in either direction:

export SPOTIFLAC_PROGRESS_BARS=0   # never draw bars, even on a terminal
export SPOTIFLAC_PROGRESS_BARS=1   # always draw bars

Supported URL Types

SpotiFLAC supports the following URL formats for Spotify, Tidal, Apple Music, SoundCloud, YouTube and Pandora:

Type Spotify Tidal Apple Music SoundCloud YouTube / YT Music Pandora
Track open.spotify.com/track/... listen.tidal.com/track/... music.apple.com/.../song/... soundcloud.com/artist/track-slug youtube.com/watch?v=... · youtu.be/... pandora.com/artist/.../song/TR:... · pandora.app.link/...
Album / Set open.spotify.com/album/... listen.tidal.com/album/... music.apple.com/.../album/... soundcloud.com/artist/sets/set-slug music.youtube.com/playlist?list=OLAK5uy_...
Playlist open.spotify.com/playlist/... listen.tidal.com/playlist/... music.apple.com/.../playlist/... youtube.com/playlist?list=PL...
Discography (via artist URL) open.spotify.com/artist/... listen.tidal.com/artist/.../discography/albums music.apple.com/.../artist/...

Note: SoundCloud and YouTube tracks are downloaded as MP3 (neither platform distributes lossless audio). Apple Music downloads as M4A/ALAC (lossless) or AAC depending on the selected quality. Pandora downloads as MP3 (mp3_192 by default) or M4A (aac_64 / aac_32). All other services deliver FLAC.

Joox, NetEase, Migu and Kuwo are download-only services — they cannot be used as input URL sources. Use a Spotify or Tidal link and set one of these as the service. These providers are primarily available in select Asian markets and may require a VPN outside those regions.

SoundCloud short links (on.soundcloud.com/...) and mobile links (m.soundcloud.com/...) are automatically resolved. Tracking parameters (e.g. ?utm_source=...) are stripped before processing.

Apple Music track links with an ?i= song parameter (e.g. music.apple.com/us/album/album-name/id?i=trackid) are also supported.

Pandora app links (pandora.app.link/...) are automatically resolved to their canonical web URL. Pandora pretty URLs (e.g. pandora.com/artist/artist-name/album-name/song-name/TR:...) are fully supported.


Advanced Configuration

You can customize the download behavior, prioritize specific streaming services, and organize your files automatically into folders.

from SpotiFLAC import SpotiFLAC

SpotiFLAC(
    url="https://open.spotify.com/album/ALBUM_ID",
    output_dir="./MusicLibrary",
    services=["qobuz", "amazon", "tidal"],
    filename_format="{year} - {album}/{track}. {title}",
    use_artist_subfolders=True,
    use_album_subfolders=True,
    loop=60,                     # retry duration in minutes
    track_max_retries=2,         # extra per-track retries on failure
    post_download_action="notify"
)

Service Health Check

SpotiFLAC can probe all provider endpoints before downloading to verify which ones are currently reachable.

In Interactive Mode this runs automatically at startup. In code or scripts you can call it directly:

from SpotiFLAC.core.health_check import (
    run_health_check,
    print_health_report,
    get_working_providers,
)

results = run_health_check(["tidal", "qobuz", "deezer", "soundcloud", "pandora"])
print_health_report(results)

working = get_working_providers(results)
print("Available providers:", working)
# CLI: check all services then download
spotiflac https://open.spotify.com/track/... ./out --service tidal qobuz

The health check runs in parallel with a configurable timeout (default: 5 s per endpoint) and never blocks your download if a check fails. In the GUI, the check reports provider-level availability and endpoint counts, without exposing individual raw endpoint URLs.

Configuration Profiles

Save and reuse complete download configurations without re-typing them every time.

Save a profile

# Save current flags as "hires-tidal"
spotiflac https://... ./out \
  --service tidal \
  --quality HI_RES_LOSSLESS \
  --use-album-subfolders \
  --filename-format "{year} - {album}/{track}. {title}" \
  --save-profile hires-tidal

Load a profile

# Load "hires-tidal" — flags override profile values when both are present
spotiflac https://... ./out --profile hires-tidal

In Python

import asyncio
from SpotiFLAC.core.profiles import (
    save_profile_async,
    get_profile_async,
    list_profiles_async,
)

async def main():
    await save_profile_async("hires-tidal", {
        "services":             ["tidal"],
        "quality":              "HI_RES_LOSSLESS",
        "use_album_subfolders": True,
        "filename_format":      "{year} - {album}/{track}. {title}",
    })

    cfg = await get_profile_async("hires-tidal")
    print(await list_profiles_async())  # ['hires-tidal']

asyncio.run(main())

Profiles are stored at ~/.cache/spotiflac/profiles.json. In the Interactive Wizard, you are prompted to load a profile at startup and optionally save one at the end.

Batch Downloads

Pass a list of URLs to download them all in sequence. Failed tracks per URL are collected and can be retried with loop.

from SpotiFLAC import SpotiFLAC

SpotiFLAC(
    url=[
        "https://open.spotify.com/album/ALBUM_ID",
        "https://open.spotify.com/playlist/PLAYLIST_ID",
        "https://listen.tidal.com/album/ALBUM_ID",
    ],
    output_dir="./MusicLibrary",
    services=["tidal", "qobuz"],
    use_album_subfolders=True,
)

Auto-Retry on Failure

Set track_max_retries (Python) or --retries (CLI) to automatically retry failed tracks. Each retry cycles through all configured providers from the beginning, waiting exponentially longer between attempts (2 s → 4 s → 8 s …, capped at 30 s).

from SpotiFLAC import SpotiFLAC

SpotiFLAC(
    url="https://open.spotify.com/album/...",
    output_dir="./downloads",
    services=["tidal", "qobuz", "deezer"],
    track_max_retries=3,   # up to 3 extra attempts per track
)
spotiflac https://open.spotify.com/album/... ./out \
  --service tidal qobuz deezer \
  --retries 3

Tip: Combine --retries with --loop for maximum resilience — --retries handles transient errors on individual tracks, while --loop re-queues permanently failed tracks after N minutes.

Per-Track Timeout

Set timeout_s (Python) or --timeout (CLI) to cap the time SpotiFLAC will spend downloading a single track. If the download does not complete within the specified number of seconds, the process is terminated and the track is marked as failed — allowing the next provider or retry to take over.

# CLI — skip any track that takes more than 3 minutes
spotiflac https://open.spotify.com/album/... ./out --service tidal --timeout 180
# Python API
from SpotiFLAC import SpotiFLAC
SpotiFLAC(
    url="https://open.spotify.com/album/...",
    output_dir="./downloads",
    services=["tidal", "qobuz"],
    timeout_s=120,
)

Tip: Pair --timeout with --retries so that a stalled track is automatically re-attempted against the next provider instead of blocking the entire queue indefinitely.

MP3 Transcoding

Downloads always fetch the best source a provider offers (FLAC, ALAC/M4A, …). Set transcode_to="mp3" (Python) or --mp3 / --transcode mp3 (CLI) to convert every finished track to MP3 — 320 kbps by default — for players or car stereos that cannot handle lossless files. Tags, cover art and lyrics are carried over to the MP3, and the original file is deleted once the conversion succeeds unless transcode_keep_original / --keep-original is set.

Requires ffmpeg on your PATH: the run stops immediately with a clear error if it is missing, so you never download a whole album only to fail at the conversion step.

# CLI — every track ends up as a 320 kbps MP3
spotiflac https://open.spotify.com/album/... ./out --service tidal --mp3

# Keep the FLAC too, and use 192 kbps instead
spotiflac https://open.spotify.com/album/... ./out --mp3 --transcode-bitrate 192k --keep-original
# Python API
from SpotiFLAC import SpotiFLAC
SpotiFLAC(
    url="https://open.spotify.com/album/...",
    output_dir="./downloads",
    services=["tidal", "qobuz"],
    transcode_to="mp3",
    transcode_bitrate="320k",
)

Skipping already-downloaded tracks still works. The converted file keeps the exact name the provider would have used, only with an .mp3 extension, so SpotiFLAC looks for that file before contacting any provider and skips the track when it is already there — no network request, no re-encode. Running the same album twice therefore costs nothing the second time. A leftover file from an earlier lossless run is converted in place instead of being re-downloaded, so an existing library converges to MP3 in a single pass.

The conversion is a no-op for providers that already deliver MP3 (e.g. SoundCloud), which are passed through untouched.

Multiple Playlists in One Folder

Pass --playlist (-p) once per playlist to sync several of them into a single destination folder. Repeat the flag as many times as you need — the last positional argument is the destination:

spotiflac -p https://open.spotify.com/playlist/AAA \
          -p https://open.spotify.com/playlist/BBB \
          -p https://open.spotify.com/playlist/CCC \
          ./Music --service tidal
  • One copy per track. A song that appears in three of those playlists is downloaded once. Tracks are matched by ISRC (resolved automatically when the metadata lacks it), falling back to artist + title, so the same recording pulled from different playlists is recognised even when the catalogue ids differ.
  • Nothing already on disk is downloaded again. The destination folder is indexed before any provider is contacted, in any audio format — a track already there as .m4a is not re-fetched just because this run would produce a .flac.
  • One M3U per playlist. Each playlist gets a <Playlist Name>.m3u8 file in the destination folder listing its own tracks, in playlist order, with paths relative to the folder — so the whole directory stays portable and can be copied to a phone or a USB stick as is. Two playlists sharing a name get Name.m3u8 and Name (2).m3u8.
  • Cheap to re-run. Playlist files are rewritten only when their content actually changed. Running the same command again after a playlist gained a track downloads that one track and touches that one M3U file.

Tracks that failed to download are left out of the playlist file, so it always lists files that really exist; they are picked up on the next run.

Everything else keeps working as usual — --mp3, --filename-format, --service, --retries and friends all apply:

# Sync three playlists as 320 kbps MP3, writing classic .m3u files
spotiflac -p URL1 -p URL2 -p URL3 ./Music --mp3 --m3u m3u

With --mp3 a playlist entry points at the converted file, and a track already present as MP3 is skipped without any network request. Use --m3u none to merge the playlists into one folder without writing playlist files at all.

Note: avoid --use-track-numbers (and {position} in --filename-format) here: the number depends on the merged playlist order, so filenames would change whenever any playlist does — and previously downloaded tracks would be fetched again under the new name. SpotiFLAC warns when you do.

Post-Download Actions

Action Description
none Do nothing (default)
open_folder Open the output folder in the system file manager
notify Send an OS desktop notification with a summary
command Run a custom shell command — placeholders: {folder}, {succeeded}, {failed} (quote {folder} in your template, e.g. '{folder}', to handle spaces; this does not protect against an apostrophe inside the path itself)
SpotiFLAC(url="...", output_dir="./downloads", post_download_action="open_folder")

SpotiFLAC(url="...", output_dir="./downloads",
          post_download_action="command",
          post_download_command="rsync -av '{folder}/' user@nas:/music/")
spotiflac https://... ./out --post-action notify
spotiflac https://... ./out --post-action command --post-command "rsync -av '{folder}/' user@nas:/music/"

Note: Wrap {folder} in single quotes in your command template (e.g. '{folder}') to safely handle spaces and most special characters. Single quotes do not protect against an apostrophe (') inside the output path itself — avoid apostrophes in output_dir, or escape them manually for your shell before running the command.

Discography Download

Download the complete discography of an artist. Duplicate tracks (same ISRC across different releases) are automatically skipped.

from SpotiFLAC import SpotiFLAC

# Spotify — albums + singles
SpotiFLAC(url="https://open.spotify.com/artist/ARTIST_ID", output_dir="./MusicLibrary",
          services=["qobuz", "tidal"], use_album_subfolders=True, filename_format="{year} - {album}/{track}. {title}")

# Tidal — full discography (append /discography/albums or /discography/singles to filter)
SpotiFLAC(url="https://listen.tidal.com/artist/ARTIST_ID", output_dir="./MusicLibrary",
          services=["tidal"], use_album_subfolders=True, filename_format="{year} - {album}/{track}. {title}")
spotiflac https://open.spotify.com/artist/... ./MusicLibrary \
  --service tidal --include-featuring \
  --use-album-subfolders --filename-format "{year} - {album}/{track}. {title}"

Recommended layout: --use-album-subfolders + --filename-format "{year} - {album}/{track}. {title}".

Custom Output Path (single tracks)

For single track downloads you can specify the exact file path instead of relying on output_dir + filename_format.

from SpotiFLAC import SpotiFLAC

SpotiFLAC(
    url="https://open.spotify.com/track/TRACK_ID",
    output_dir="./downloads",
    output_path="files/song.flac"
)

Note: output_path is automatically ignored when the URL points to an album, playlist, or artist/discography.

Qobuz Local API URL (Optional)

By default, SpotiFLAC attempts Qobuz requests anonymously, without any local API configured. For improved reliability, reduced rate limits, and to use your own Qobuz subscription credentials instead of anonymous access, you can deploy a self-hosted Qobuz stream API and point SpotiFLAC to it.

How to deploy your own instance: github.com/BartolomeoRusso9/qobuz-rest-api

Note: Self-hosting requires your own valid Qobuz account and is subject to Qobuz's Terms of Service. You are responsible for ensuring your use complies with those terms and with applicable law in your jurisdiction.

How to apply the Qobuz Local API URL in SpotiFLAC:

  • Interactive Wizard: The wizard prompts you to enter your local Qobuz API URL during configuration.
  • Environment Variable:
export QOBUZ_LOCAL_API_URL="https://localhost:8000"
  • Python:
from SpotiFLAC import SpotiFLAC

SpotiFLAC(
    url="URL",
    output_dir="./downloads",
    qobuz_local_api_url="https://localhost:8000",
)
  • config.json:
{
    "qobuz_local_api_url": "https://localhost:8000"
}

Custom Tidal API Instance (Optional)

By default, SpotiFLAC connects to a shared pool of public hifi-api mirrors to fetch Tidal streams. For guaranteed availability, full control, and to use your own Tidal Premium credentials instead of relying on third-party mirrors, you can self-host your own instance and point SpotiFLAC to it — it will always be tried first, before any public mirror.

How to deploy your own instance: github.com/binimum/hifi-api

Note: Self-hosting requires your own valid Tidal account and is subject to Tidal's Terms of Service. You are responsible for ensuring your use complies with those terms and with applicable law in your jurisdiction.

Python

from SpotiFLAC import SpotiFLAC

SpotiFLAC(
    url="https://open.spotify.com/track/TRACK_ID",
    output_dir="./downloads",
    services=["tidal"],
    tidal_custom_api="https://your-instance.example.com",
)

CLI

spotiflac https://open.spotify.com/track/... ./downloads \
  --service tidal \
  --tidal-api "https://your-instance.example.com"

Interactive Wizard

The wizard prompts for a custom Tidal API URL at step 12.5, right after the optional tokens section.

config.json

{
    "tidal_custom_api": "https://your-instance.example.com"
}

Note: The custom instance is also saved and restored when using --save-profile / --profile.


CLI Usage (standalone executables)

./SpotiFLAC-Windows.exe url
                        output_dir
                        [--service tidal qobuz deezer amazon soundcloud youtube apple pandora joox netease migu kuwo]
                        [--filename-format "{title} - {artist}"]
                        [--output-path "files/song.flac"]
                        [--quality LOSSLESS]
                        [--use-track-numbers]
                        [--use-album-track-numbers]
                        [--use-artist-subfolders]
                        [--use-album-subfolders]
                        [--first-artist-only]
                        [--qobuz-local-api URL]
                        [--tidal-api URL]
                        [--timeout seconds]
                        [--loop minutes]
                        [--no-extensions-fallback]
                        [--verbose]
                        [--no-lyrics]
                        [--lyrics-providers spotify apple musixmatch amazon lrclib]
                        [--no-enrich]
                        [--enrich-providers deezer apple qobuz tidal soundcloud]
                        [--retries N]
                        [--post-action none|open_folder|notify|command]
                        [--post-command "CMD with {folder} {succeeded} {failed}"]
                        [--profile NAME]
                        [--save-profile NAME]
chmod +x SpotiFLAC-Linux-arm64
./SpotiFLAC-Linux-arm64 url
                        output_dir
                        [--service tidal qobuz deezer amazon soundcloud youtube apple pandora joox netease migu kuwo]
                        [--filename-format "{title} - {artist}"]
                        [--output-path "files/song.flac"]
                        [--quality LOSSLESS]
                        [--use-track-numbers]
                        [--use-album-track-numbers]
                        [--use-artist-subfolders]
                        [--use-album-subfolders]
                        [--first-artist-only]
                        [--qobuz-local-api URL]
                        [--tidal-api URL]
                        [--timeout seconds]
                        [--loop minutes]
                        [--no-extensions-fallback]
                        [--verbose]
                        [--no-lyrics]
                        [--lyrics-providers spotify apple musixmatch amazon lrclib]
                        [--no-enrich]
                        [--enrich-providers deezer apple qobuz tidal soundcloud]
                        [--retries N]
                        [--post-action none|open_folder|notify|command]
                        [--post-command "CMD with {folder} {succeeded} {failed}"]
                        [--profile NAME]
                        [--save-profile NAME]

(For ARM devices like Raspberry Pi, replace x86_64 with arm64)


API Reference

SpotiFLAC() Parameters

Parameter Type Default Description
url str / list[str] Required A single URL or a list of URLs (batch mode) for Spotify, Tidal, Apple Music, SoundCloud, YouTube or Pandora.
output_dir str Required The destination directory path where the audio files will be saved.
output_path str None Exact destination file path for single track downloads. Overrides output_dir + filename_format. Automatically ignored for albums, playlists and artist discographies.
services list ["tidal"] Specifies which services to use and their priority order. Choices: tidal, qobuz, deezer, amazon, soundcloud, youtube, apple, pandora, joox, netease, migu, kuwo. Also accepts ext:<extension-name> (e.g. ext:tidal-web) to use an installed JavaScript extension as a provider; native and ext: providers can be freely mixed in the same priority list.
filename_format str "{title} - {artist}" Format for naming downloaded files. See placeholders below.
use_track_numbers bool False Prefixes the filename with the track number.
use_album_track_numbers bool False Uses the track's original album number instead of the download queue position.
use_artist_subfolders bool False Automatically organizes downloaded files into subfolders by artist.
use_album_subfolders bool False Automatically organizes downloaded files into subfolders by album.
first_artist_only bool False Uses only the first artist in tags and filename.
include_featuring bool False When downloading an artist discography, also includes tracks where the artist appears as a featured artist.
tidal_custom_api str None URL of a self-hosted hifi-api instance. Takes priority over all public mirrors.
timeout_s int None Per-track download timeout in seconds. If a single track download does not complete within this time, the process is terminated and the track is marked as failed. SpotiFLAC then moves on to the next provider or retry. Set to None (default) to disable the timeout.
loop int None Duration in minutes to keep retrying permanently failed tracks after a full session completes.
track_max_retries int 0 Extra download attempts per track when all providers fail on the first try. Each retry cycles through all providers again with exponential backoff (2 s → 4 s → 8 s …, capped at 30 s).
quality str "LOSSLESS" Download quality. Tidal: "DOLBY_ATMOS", "HI_RES_LOSSLESS", "LOSSLESS", "HIGH", "LOW". Qobuz: "6" (CD), "7" (Hi-Res), "27" (Hi-Res Max). Apple Music: "alac", "atmos", "ac3", "aac", "aac-legacy". Pandora: "mp3_192", "aac_64", "aac_32".
allow_fallback bool True Automatically falls back to the next available quality tier if the requested quality is unavailable.
log_level int logging.WARNING Python logging level.
embed_lyrics bool True Whether to fetch and embed synchronized lyrics (LRC) into the audio file.
lyrics_providers list ["spotify", "apple", "musixmatch", "lrclib", "amazon"] Priority order of lyrics providers to attempt.
enrich_metadata bool True Enables multi-provider metadata enrichment (HD covers, BPM, labels, etc.).
enrich_providers list ["deezer", "apple", "qobuz", "tidal", "soundcloud"] Priority order of metadata providers to attempt.
qobuz_local_api_url str None Optional local Qobuz stream API URL. When set, the provider uses this endpoint for Qobuz stream requests.
use_extensions_fallback bool True Whether to automatically pair a matching installed JavaScript extension as a fallback provider when a native provider fails. Set to False to use only the providers explicitly listed in services.
transcode_to str None Converts every finished track to this format. Currently only "mp3" (see MP3 Transcoding). None keeps the provider's original format. Requires ffmpeg.
transcode_bitrate str "320k" Bitrate used by transcode_to, e.g. "320k", "256k", "192k".
transcode_keep_original bool False Keeps the original lossless file next to the converted one. By default the source is deleted once the conversion succeeds.
post_download_action str "none" Action after all downloads finish: "none", "open_folder", "notify", "command".
post_download_command str "" Shell command to run when post_download_action="command". Supports {folder}, {succeeded}, {failed} placeholders; quote {folder} in your template (e.g. '{folder}') since the substituted path may contain spaces.

Filename Format Placeholders

When customizing the filename_format string, you can use the following dynamic tags:

  • {title} — Track title
  • {artist} — Track artist(s)
  • {album} — Album name
  • {album_artist} — The artist(s) of the entire album
  • {disc} — The disc number
  • {track} — The track's original number in the album
  • {position} — Download queue / playlist position (zero-padded, e.g. 01)
  • {date} — Full release date (e.g., YYYY-MM-DD)
  • {year} — Release year (e.g., YYYY)
  • {isrc} — Track ISRC code

CLI Flag Reference

Flag Short Default Description
--service -s tidal One or more providers in priority order. Choices: tidal, qobuz, deezer, amazon, soundcloud, youtube, apple, pandora, joox, netease, migu, kuwo. Also accepts ext:<extension-name> (e.g. ext:tidal-web) for installed JavaScript extension providers, mixable with native providers in the same list.
--filename-format -f {title} - {artist} Filename template with placeholders.
--output-path -o None Exact output file path for single track downloads. Ignored for albums, playlists and discographies.
--quality -q LOSSLESS Audio quality. Tidal: DOLBY_ATMOS, HI_RES_LOSSLESS, LOSSLESS, HIGH, LOW. Qobuz: 6, 7, 27. Apple Music: alac, atmos, ac3, aac, aac-legacy. Pandora: mp3_192, aac_64, aac_32.
--use-track-numbers False Prefix filenames with track numbers.
--use-album-track-numbers False Use the track's original album number instead of queue position.
--use-artist-subfolders False Organize files into per-artist subfolders.
--use-album-subfolders False Organize files into per-album subfolders.
--first-artist-only False Use only the first artist in tags and filename.
--include-featuring False Include tracks where the artist appears as a featured artist. Only applies to artist/discography URLs.
--qobuz-local-api None Optional local Qobuz stream API URL.
--tidal-api None URL of a self-hosted hifi-api instance. Takes priority over the built-in public mirror pool.
--timeout None Per-track download timeout in seconds. If a track download stalls or takes longer than this limit, it is forcibly terminated and marked as failed, then SpotiFLAC moves to the next provider or retry.
--loop -l None Keep retrying permanently failed tracks every N minutes.
--no-extensions-fallback False Disable automatic fallback to installed JS extensions when a native provider fails (fallback is enabled by default).
--loop -l None Keep retrying permanently failed tracks every N minutes.
--retries 0 Extra per-track download attempts on failure. Cycles through all providers with exponential backoff.
--playlist -p None Playlist URL to sync; repeat once per playlist. All tracks go to a single destination folder, shared tracks are downloaded once, and each playlist gets its own M3U file (see Multiple Playlists in One Folder).
--m3u m3u8 Playlist file written for each --playlist: m3u8, m3u or none. Rewritten only when its content changed.
--transcode none Convert every downloaded track to this format: none or mp3. Requires ffmpeg.
--mp3 Shorthand for --transcode mp3.
--transcode-bitrate 320k Bitrate used by --transcode, e.g. 320k, 256k, 192k.
--keep-original False Keep the original lossless file alongside the transcoded one.
--verbose -v False Enable debug logging.
--no-lyrics False Disable lyrics embedding (lyrics are embedded by default).
--lyrics-providers spotify apple musixmatch lrclib amazon Lyrics provider priority order.
--no-enrich False Disable multi-provider metadata enrichment (enrichment is enabled by default).
--enrich-providers deezer apple qobuz tidal soundcloud Metadata enrichment provider priority order.
--post-action none Action after all downloads finish: none, open_folder, notify, command.
--post-command "" Shell command for --post-action=command. Placeholders: {folder}, {succeeded}, {failed}; quote {folder} in your template (e.g. '{folder}') since the substituted path may contain spaces.
--profile None Load a saved profile. CLI flags override profile values.
--save-profile None Save current CLI configuration as a named profile after the run.

MusicBrainz Enrichment

SpotiFLAC automatically queries MusicBrainz in the background (when an ISRC is available) while the audio is being downloaded, adding professional-grade tags at no extra time cost. Fields written when found:

Tag Description
GENRE Genre(s), sorted by popularity (up to 5)
BPM Beats per minute
LABEL / ORGANIZATION Record label name
CATALOGNUMBER Catalog number
BARCODE Release barcode / UPC
ORIGINALDATE / ORIGINALYEAR First-ever release date
RELEASECOUNTRY Country of release
RELEASESTATUS Release status (e.g. Official)
RELEASETYPE Release type (e.g. Album, Single)
MEDIA Media format (e.g. CD, Digital Media)
SCRIPT Script of the release text
ARTISTSORT Artist sort name for file managers
MUSICBRAINZ_TRACKID MusicBrainz recording ID
MUSICBRAINZ_ALBUMID MusicBrainz release ID
MUSICBRAINZ_ARTISTID MusicBrainz artist ID
MUSICBRAINZ_RELEASEGROUPID MusicBrainz release group ID
MUSICBRAINZ_ALBUMARTISTID MusicBrainz album artist ID
ALBUMARTISTSORT Album artist sort name for file managers

Download Validation

After each download, SpotiFLAC validates the file to detect common issues:

  • Preview detection — if the expected duration is ≥ 60 s but the downloaded file is ≤ 35 s, the file is deleted and the download is retried with the next provider.
  • Duration mismatch — for tracks longer than 90 s, a deviation greater than 25% (or 15 s minimum) from the expected duration is treated as a corrupt download and the file is removed.

Want to support the project?

If this software is useful and brings you value, consider supporting the project by buying us a coffee. Your support helps keep development going.

Ko-fi


API Credits

Song.link · hifi-api · qobuz-rest-api · dabmusic.xyz · GD Studio Music API · Music Wjhe API · afkarxyz · MusicBrainz · SoundCloud · Apple Music · YouTube Music · Pandora · squid.wtf · flacdownloader.com · monochrome · spotiflacapp · anandprtp · Deezer · Amazon Music · Tidal · LRCLIB · Musixmatch · Songstats · Soundplate · iTunes Search API · Cobalt

[!TIP] Star the repo to show support, and click Watch → Custom → Releases on GitHub if you want to be notified as soon as a new release goes out.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spotiflac-1.7.7.tar.gz (792.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spotiflac-1.7.7-py3-none-any.whl (777.0 kB view details)

Uploaded Python 3

File details

Details for the file spotiflac-1.7.7.tar.gz.

File metadata

  • Download URL: spotiflac-1.7.7.tar.gz
  • Upload date:
  • Size: 792.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for spotiflac-1.7.7.tar.gz
Algorithm Hash digest
SHA256 842a8e1272e2e86bba33dd9f78856a5b5e396fe8fe85d85bbab011169c1459a9
MD5 83a120b06002ce5c69bef4c59b261c1b
BLAKE2b-256 f16a05de72765f8c281fcedc3abbdd939708c7ccf740840494500b1a597a147b

See more details on using hashes here.

File details

Details for the file spotiflac-1.7.7-py3-none-any.whl.

File metadata

  • Download URL: spotiflac-1.7.7-py3-none-any.whl
  • Upload date:
  • Size: 777.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15

File hashes

Hashes for spotiflac-1.7.7-py3-none-any.whl
Algorithm Hash digest
SHA256 7a868e69e57698bf4c0c29899aa51de4914396b9e7c78f69755cb3d69c30cf87
MD5 857be1352e83bcafd279cc2b1d28b6b7
BLAKE2b-256 8b0fd9a4e3e6f1cf973ebf8d77b4ce91ff3d9861cef05c66bd146f5c3fcf175e

See more details on using hashes here.

Release history Release notifications | RSS feed

4.1.0

2 files

4.0.3

2 files

4.0.2

2 files

4.0.1

2 files

4.0.0

2 files

3.9.0

2 files

3.8.0

2 files

3.7.0

2 files

3.6.0

2 files

3.5.0

2 files

3.1.0

2 files

3.0.9

2 files

3.0.8

2 files

3.0.7

2 files

3.0.6

2 files

3.0.5

2 files

3.0.4

2 files

3.0.3

2 files

3.0.2

2 files

3.0.1

2 files

3.0.0

2 files

1.8.1

2 files

1.8.0

2 files

1.7.9

2 files

1.7.8

2 files

This release

1.7.7 This release

2 files

1.7.6

2 files

1.7.5

2 files

1.7.4

2 files

1.7.3

2 files

1.7.2

2 files

1.7.1

2 files

1.7.0

2 files

1.6.9

2 files

1.6.8

2 files

1.6.7

2 files

1.6.6

2 files

1.6.5

2 files

1.6.4

2 files

1.6.3

2 files

1.6.2

2 files

1.6.1

2 files

1.6.0

2 files

1.5.9

2 files

1.5.8

2 files

1.5.7

2 files

1.5.6

2 files

1.5.5

2 files

1.5.4

2 files

1.5.3

2 files

1.5.2

2 files

1.5.1

2 files

1.5.0

2 files

1.4.9

2 files

1.4.8

2 files

1.4.7

2 files

1.4.6

2 files

1.4.5

2 files

1.4.4

2 files

1.4.3

2 files

1.4.2

2 files

1.4.1

2 files

1.4.0

2 files

1.3.9

2 files

1.3.8

2 files

1.3.7

2 files

1.3.6

2 files

1.3.5

2 files

1.3.4

2 files

1.3.3

2 files

1.3.2

2 files

1.3.1

2 files

1.3.0

2 files

1.2.9

2 files

1.2.8

2 files

1.2.7

2 files

1.2.6

2 files

1.2.5

2 files

1.2.4

2 files

1.2.3

2 files

1.2.2

2 files

1.2.1

2 files

1.2.0

2 files

1.1.9

2 files

1.1.8

2 files

1.1.7

2 files

1.1.6

2 files

1.1.5

2 files

1.1.4

2 files

1.1.3

2 files

1.1.2

2 files

1.1.1

2 files

1.1.0

2 files

1.0.9

2 files

1.0.8

2 files

1.0.7

2 files

1.0.6

2 files

1.0.5

2 files

1.0.4

2 files

1.0.3

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

0.9.9

2 files

0.9.8

2 files

0.9.7

2 files

0.9.6

2 files

0.9.5

2 files

0.9.4

2 files

0.9.3

2 files

0.9.2

2 files

0.9.1

2 files

0.9.0

2 files

0.8.9

2 files

0.8.7

2 files

0.8.6

2 files

0.8.5

2 files

0.8.4

2 files

0.8.3

2 files

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.9

2 files

0.7.8

2 files

0.7.7

2 files

0.7.6

2 files

0.7.5

2 files

0.7.4

2 files

0.7.3

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.9

2 files

0.6.8

2 files

0.6.7

2 files

0.6.6

2 files

0.6.5

2 files

0.6.4

2 files

0.6.3

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.9

2 files

0.5.8

2 files

0.5.6

2 files

0.5.5

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.9

2 files

0.4.8

2 files

0.4.7

2 files

0.4.6

2 files

0.4.5

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.9

2 files

0.3.8

2 files

0.3.7

2 files

0.3.6

2 files

0.3.5

2 files

0.3.3

2 files

0.3.2

2 files

0.2.13

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page