Unofficial Qobuz API client with CLI, local library, and download pipeline
Project description
Kabooz
Unofficial Qobuz CLI and Python library — download hi-res audio, manage your local library, and browse the catalog from the command line or from a script.
kabooz album https://open.qobuz.com/album/0093046758769
kabooz track https://open.qobuz.com/track/12345678 -q cd --lyrics
kabooz artist https://open.qobuz.com/artist/298 --type album
kabooz info https://open.qobuz.com/album/0093046758769
kabooz search "handel dixit dominus" --type albums
kabooz goodies https://open.qobuz.com/album/0093046758769
Requires an active Qobuz subscription. Not affiliated with or endorsed by Qobuz.
Why Kabooz
Qobuz is one of the few streaming services that has genuinely cared about music as an art form — hi-res lossless audio, a serious catalog with real depth, no advertisements, and fair artist payouts. It deserves your subscription. Kabooz exists because Qobuz is that good, and because a command-line interface to it is a natural thing to want.
Beyond downloading, Kabooz manages a local library — favorites and playlists stored in a local SQLite database that works even in token pool mode. It embeds full metadata using MusicBrainz for enrichment and LRCLIB for synced lyrics. The architecture is designed so that every operation available in the CLI is equally callable from Python.
Install
pip install 'kabooz[cli]'
See docs/installation.md for more, including editable development installs.
Quick start
1. Authenticate
kabooz login --app-id YOUR_APP_ID --app-secret YOUR_APP_SECRET \
-u your@email.com
Kabooz will prompt for anything not supplied. Credentials are saved to
~/.config/kabooz/config.toml and the session token to
~/.config/kabooz/session.json.
See docs/authentication.md for token pool mode and other options.
2. Download
# Single track at maximum quality
kabooz track https://open.qobuz.com/track/12345678
# Full album at CD quality with synced lyrics
kabooz album https://open.qobuz.com/album/0093046758769 -q cd --lyrics
# Artist's full discography (albums only)
kabooz artist https://open.qobuz.com/artist/298 --type album
# Playlist
kabooz playlist https://open.qobuz.com/playlist/12345
# Bonus files only (booklets, PDFs, videos)
kabooz goodies https://open.qobuz.com/album/0093046758769
3. Browse without downloading
# Full album info — tracklist, format, goodies, ISRC codes
kabooz info https://open.qobuz.com/album/0093046758769
# Search
kabooz search "beethoven" --type albums -n 20
# New releases, editorial picks, genre tree
kabooz new-releases
kabooz featured --type editor-picks
kabooz genres
Quality levels
| Flag | Format | Notes |
|---|---|---|
mp3 / 320 |
MP3 320 kbps | Lossy |
cd / flac / lossless |
FLAC 16-bit 44.1 kHz | CD quality |
24bit |
FLAC 24-bit 96 kHz | High-res |
hires / best / max |
FLAC up to 24-bit 192 kHz | Maximum (default) |
The best quality your subscription supports is used automatically when the requested quality exceeds your tier.
Features
Downloads
- Tracks, albums, playlists, artist discographies, and favorites
.partfile convention — downloads are atomic; a file exists only when fully complete including tagging. Interrupted downloads resume automatically.- Parallel downloads with configurable worker count (
-j) - External downloader support (aria2c, wget) via shell template
Metadata
- Full FLAC (Vorbis Comments) and MP3 (ID3v2.4) tagging
- Embedded full-resolution cover art
- Standalone
cover.jpgoption - Synced lyrics from LRCLIB — written to both LRC frames (for players that scroll lyrics) and plain text frames
- MusicBrainz enrichment via ISRC lookup
- Performer credits, ReplayGain values, ISRC, UPC, composer, work title
Naming templates
- Fully configurable file and folder naming via template strings
- Separate templates for albums, singles, EPs, compilations, playlists, and artist discographies
- Placeholders for title, artist, album, year, quality, ISRC, label, genre, disc number, and more
- See docs/naming.md for the full reference
Local library
- SQLite database for favorites and playlists — works in all modes including token pool mode
- Local playlist creation, sharing as TOML files, and importing
- Sync favorites from your Qobuz account
- Download history log
Account management
- View profile and subscription tier
- Manage Qobuz account playlists (create, update, delete, follow, add/remove tracks)
- Update account fields, change password
Python library
- Every CLI operation is callable from Python via
QobuzSession - Typed models for all API responses — no raw dict access required
- Streaming URL resolution with automatic start/end reporting
Configuration
Configuration lives at ~/.config/kabooz/config.toml. The most commonly
changed settings:
[download]
output_dir = "/storage/Music"
quality = "hi_res" # mp3_320 | flac_16 | flac_24_96 | hi_res
max_workers = 1 # parallel track downloads
[tagging]
embed_cover = true
fetch_lyrics = false # set true to embed synced lyrics
save_cover_file = false # set true to write cover.jpg
[musicbrainz]
enabled = false # set true to enrich tags via ISRC
kabooz config --show # view full config
kabooz config --set download.quality=cd # update a value
kabooz config --set tagging.fetch_lyrics=true
Full reference: docs/configuration.md
Naming templates
By default albums are saved as:
Discovery [FLAC 24bit 96kHz] [2001]/01. One More Time.flac
This is controlled by naming templates in the config:
[naming]
album = "{album} [{quality}] [{year}]/{track:02d}. {title}"
single = "{artist} - {title}"
Override per-command:
kabooz album 0093046758769 --template "{albumartist}/{album}/{track:02d}. {title}"
Full placeholder reference: docs/naming.md
Python library
Every CLI operation is equally callable from Python:
from kabooz import QobuzSession, Quality
from pathlib import Path
sess = QobuzSession.from_config()
# Metadata
album = sess.get_album("0093046758769")
print(album.display_title, "—", album.artist.name)
for t in album.tracks.items:
print(f" {t.track_number:02d}. {t.display_title} {t.isrc}")
# Download
result = sess.download_album(
"0093046758769",
quality=Quality.FLAC_16,
dest_dir=Path("/storage/Music"),
fetch_lyrics_flag=True,
)
print(f"{result.succeeded} downloaded, {result.skipped} skipped")
# Search
results = sess.search("beethoven", search_type="albums", limit=10)
for a in results.albums.items:
print(a.id, a.display_title, a.artist.name)
# Stream URL for a player
stream = sess.prepare_stream("12345678", quality=Quality.HI_RES)
# play stream.url, then:
sess.report_stream_end(stream.track_id)
Full library reference: docs/library.md
Architecture
kabooz/
├── client.py Raw Qobuz API — HTTP, auth, all endpoints
├── session.py Business logic — downloads, tagging, library
├── cli.py CLI presentation layer
├── config.py TOML config read/write
├── quality.py Quality enum
├── exceptions.py Exception hierarchy
├── auth/ Credentials, token pool, session persistence
├── download/ Downloader, tagger, lyrics, MusicBrainz, naming
├── models/ Typed dataclasses for every API response
└── local/ SQLite store, local playlists, export/import
The core rule: cli.py is presentation only. All business logic lives in
session.py, which means every CLI operation is equally a library call.
Full architecture notes: docs/architecture.md
Tinker with it
Kabooz is deliberately designed to be hackable.
The business logic lives in one file — session.py. The models are plain
dataclasses with from_dict() constructors. The CLI is a thin layer that
calls session methods and prints results. Adding a new feature means writing
a session method, wiring a CLI command, and adding a test.
Some things that would make Kabooz meaningfully better and are not yet done:
- Async downloads — the HTTP layer uses synchronous httpx; an async version would make parallel downloads faster without thread overhead
- Better TUI — the Textual-based TUI is incomplete
- More MusicBrainz depth — currently applies recording and release group IDs; much more is available per ISRC
- Windows path handling — the filename sanitizer works on Linux/macOS/Android; Windows has additional constraints not yet handled
If you find something broken, missing, or improvable — fix it. PRs, forks, and feature branches are all welcome. The AGPL license keeps improvements in the commons.
Read docs/contributing.md to get started.
Documentation
| Installation | Requirements, pip, Termux |
| Authentication | Login, token pool, session management |
| CLI reference | Every command, every option |
| Configuration | Full config file reference |
| Naming templates | All placeholders, examples |
| Python library | API reference with code examples |
| Architecture | How the code is organized |
| Contributing | Where to add things, code style, tests |
Credits
Kabooz would not exist without Qobuz — the platform it talks to, and genuinely one of the best things to happen to music in years. Tag enrichment is powered by MusicBrainz. Synced lyrics come from LRCLIB. Technical help from @tmxkwpn on Telegram.
Full acknowledgements: CREDITS.md
License
AGPL-3.0-or-later.
You can use it, study it, modify it, and distribute it. If you distribute a modified version you must make the source available under the same terms.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kabooz-0.1.0.tar.gz.
File metadata
- Download URL: kabooz-0.1.0.tar.gz
- Upload date:
- Size: 207.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc5643980f01b9bee7b3508b0e4e297d48c00fdd1013430c5d5bc3fd68f5c109
|
|
| MD5 |
cd968721cf59458529c7ef6f3b6d4e0a
|
|
| BLAKE2b-256 |
c3105e6a5f38b847d94abdc4df2663e9aecca05c1c8f669427528fde348f0fab
|
File details
Details for the file kabooz-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kabooz-0.1.0-py3-none-any.whl
- Upload date:
- Size: 174.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7f9e204f4f42aceea3e8f542b2690a0e3fd2a69ed3478784c80ecacd75f6418
|
|
| MD5 |
631fefb74159121f2b43a5d900bf5806
|
|
| BLAKE2b-256 |
6523cc9a6b6dfd4179c517a63bed21a90740f463dd979ee60ee4e88d7163498e
|