hifi-api is a Rust port of the original sachinsenal0x64/hifi / binimum/hifi-api project — a Tidal Music Proxy with intelligent multi-account switching, direct instant playback, a catalog/metadata credential split, and a secure admin panel.
This is a complete rewrite from Python (FastAPI) to Rust (Axum). Key differences:
| Aspect | binimum/hifi-api (Python) | this (Rust) |
|---|---|---|
| Language | Python 3 | Rust |
| Framework | FastAPI + Uvicorn | Axum 0.8 |
| HTTP client | httpx | reqwest (HTTP/2, connection pooling) |
| Database | Optional SQLite via aiosqlite | SQLite via sqlx with inline migrations |
| Performance | Interpreted, GIL-bound | Compiled, zero-cost abstractions |
| Memory | ~100-200 MB idle | ~5-15 MB idle |
| Startup time | ~2-5 seconds (import overhead) | ~100ms (compiled binary) |
| Concurrent connections | ~50-100 per instance (async Python, GIL-bound) | ~5,000-10,000 concurrent tasks per instance (tokio M:N threading, no GIL)¹ |
| Ban avoidance | Basic round-robin across accounts | Weighted scoring (balance + recency + error-rate) with immediate failover across accounts, dedicated catalog credential for metadata |
| Request distribution | Full requests, one account at a time | Weighted per-request selection across accounts; every playback request runs immediately, spread evenly — no queue, no polling |
| Token cache | In-memory dict | Per-account memory + shared Redis, per-account refresh locks |
| Throttling | Playback serialization + 429 retries | None — requests go straight to Tidal, unbounded, each with multi-account failover |
| Auth flow | Separate Python script (tidal_auth.py) | Built-in OAuth device flow (AUTO_SETUP=true) |
| Admin panel | External SPA | Embedded single HTML file (rust-embed) |
| Concurrency | asyncio event loop | tokio multi-threaded runtime |
| Deployment | Python interpreter required | Single static binary, Docker optional |
Important
Music piracy is illegal in most countries. This project is intended for use with a valid Tidal account for educational purposes (for example, in your homelab). I won't provide support for people hosting this API on the open internet.
Warning
Tidal has begun blocking accounts en masse starting from around now - not only users using this API but also other providers such as lucide.to. There is currently no solution for this - this includes homelab users who don't expose their API to the Internet.
# 1. Copy and edit config
cp .env.example .env
# 2. Run (auto-setup will prompt you to authorize via browser)
cargo runOn first boot with no accounts, the app prints a URL. Open it in your browser, log into Tidal, and the account is added automatically.
Set env vars in .env:
CLIENT_ID=lw3vR6GE1vtNBsjv
CLIENT_SECRET=Y8tIpqKJxs9BEIwYr0I9bSbMWDsogXJx9LaN3mCHwD4%3D
REFRESH_TOKEN=<your_refresh_token>The CLIENT_ID and CLIENT_SECRET above are Tidal's public OAuth credentials. You only need to provide your REFRESH_TOKEN.
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
hifi.db |
SQLite path (ephemeral for serverless) |
ADMIN_KEY |
(none) | Admin panel auth (empty = open) |
COUNTRY_CODE |
US |
Tidal region code |
AUTO_SETUP |
false |
Enable auto-OAuth-setup on first boot |
TOKEN_FILE |
token.json |
Legacy upstream credential file, imported into the DB on startup when present (supports role: "catalog" per entry) |
CATALOG_CLIENT_ID / CATALOG_CLIENT_SECRET / CATALOG_REFRESH_TOKEN / CATALOG_USER_ID |
(none) | Dedicated metadata credential, kept out of the playback pool (upstream CATALOG_*) |
CATALOG_TOKEN |
(none) | Static bearer token for metadata, no refresh (upstream CATALOG_TOKEN, legacy CATALOG_ACCESS_TOKEN also honored) |
USE_PROXIES |
false |
Enable proxy rotation for all Tidal traffic (optional; everything goes direct when off) |
PROXIES_FILE |
proxies.txt |
Proxy list (one per line, http(s)://[user:pass@]host:port) |
FALLBACK_TO_DIRECT_CONNECTION |
false |
If true, fall back to direct when no proxy works (exposes host IP); if false, Tidal traffic returns 503 until a proxy works |
MAX_RETRIES |
2 |
Retry count on proxy failure |
ROTATE_PROXIES_ON_REFRESH |
false |
Rotate the proxy on every token refresh (upstream parity) |
USER_AGENT |
okhttp/5.3.2 |
Upstream User-Agent override |
DEV_MODE |
false |
Verbose upstream logging (status + body preview) |
AUTO_HEAL |
true |
Retry system-disabled accounts with backoff (never touches manual OFF; editable in admin panel) |
ATMOS_MODE |
prefer |
Default Atmos preference for manifests/dash: prefer (EAC3_JOC first) or off (FLAC first); ?atmos= overrides per request |
TRUST_PROXY_HEADERS |
true |
Use X-Forwarded-For/X-Real-IP for client IP (set to false for direct connections) |
DISCORD_WEBHOOK_URL |
(none) | Discord webhook for 403/all-down alerts (empty = disabled, test in panel) |
UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN |
(none) | Shared cross-instance state via Upstash Redis (empty = single-host mode). See Multi-instance sync |
REDIS_POOL |
(none) | Alternative backend: native Redis/Valkey for this host's pool (rediss://user:pass@host:port/db). Wins over the Upstash pair when set — one backend per fleet. (PUBLIC_POOL_REDIS_URL still works as a deprecated fallback.) |
USE |
(none) | Pool selector on the shared instance: private loads db 0, public loads db 1 (overrides the URL db). Anything else disables sync rather than loading the wrong pool. |
RUST_LOG |
info |
Log level |
Push to GitHub and create a new Web Service:
- Connect your repo
- Set runtime to Docker
- Set env vars (
DATABASE_URL=/data/hifi.db,ADMIN_KEY,AUTO_SETUP=true) - Add a Disk mount at
/data(1 GB)
fly launch --dockerfile Dockerfile
fly secrets set ADMIN_KEY=<secret> AUTO_SETUP=true
fly volume create data --size 1
fly deployConnect repo → Railway auto-detects railway.json and Dockerfile. Set env vars in the dashboard.
Docker-based deployment is supported via vercel.json / netlify.toml. Note that these platforms are designed for serverless — for a persistent SQLite-backed service, Render or Fly.io are recommended.
docker build -t hifi-api .
docker run -d -p 8000:8000 \
-v hifi-data:/data \
-e DATABASE_URL=/data/hifi.db \
-e ADMIN_KEY=changeme \
-e AUTO_SETUP=true \
hifi-apicompose.vps.yml runs the public fleet, the private fleet, and Caddy (automatic HTTPS + routing) on one host:
cp .env.vps.example .env.vps # fill secrets, never commit
# Point DNS A records at the server, one per fleet in .env.vps
docker compose -f compose.vps.yml --env-file .env.vps up -dEach fleet gets its own subdomain, volume, admin key, and pool (USE=public → shared-Redis db 1, USE=private → db 0); accounts restore from Redis on first boot, nothing to import. App ports stay localhost-only — only Caddy's 80/443 face the network. Adding a subdomain later: add its DNS A record, copy one block in Caddyfile (+ a service in compose.vps.yml if it needs a container), then up -d caddy — certificates are automatic.
Access at /admin. If ADMIN_KEY is set, include the header X-Admin-Key: <your_key>. When empty, the panel is open.
| Section | What it does |
|---|---|
| Live request log | Real xterm.js terminal (vendored, offline) with plain-language rows, error split, slowest list, search + filters, and 1000-line scrollback |
| Accounts | Numbered cards with credentials, user ID, stats, CATALOG badge for metadata-only accounts, premium badge (PREMIUM/PREVIEW-ONLY/UNCHECKED) with per-account probe, Test/Refresh/Check-premium/Edit/Duplicate/Catalog/ON-OFF/Delete; Add via OAuth asks for an optional label in the modal |
| Import / Export | Download all credentials as credentials.json (catalog accounts carry role: "catalog"), or restore from one (duplicates skipped by refresh token; upstream token.json shape accepted) |
| API Keys | Per-client keys (X-API-Key) with quotas. While none exists the API stays open; creating the first key locks public routes behind a key (owner X-Admin-Key bypasses) |
| Settings | Atmos default + auto-heal toggle — applied live, persisted to DB |
| Proxies | Status of the proxy pool (active proxy, pool size, failures). Configure via USE_PROXIES/PROXIES_FILE + restart |
| Alerts | Discord webhook status + test button (fires on account 403 and all-accounts-down); on-demand Status and Accounts-roster reports (accounts shown as TIDAL-1…N, never real names) |
| Cache | Metadata cache hits/misses + clear button |
| Backup / Restore | Download a hifi.db snapshot, or restore from one (validated, applied live, no restart) |
| Header actions | Test All + per-account refresh |
No per-IP or upstream rate limiting is applied — every request goes straight to Tidal:
- Weighted account selection — each request picks the best playback account by usage balance, recency, and error rate, and fails over to the next account on
429/403/token errors instead of parking it. - Direct playback (no queue) —
/track,/trackManifests,/dash,/widevineand/videoexecute immediately: every request runs straight through to Tidal with the normal multi-account failover, spread evenly across accounts by weighted selection. Nothing waits, nothing polls — the panel's Playback card shows live ops vs pool size. Each op is bounded by a 120s timeout. - Catalog split — metadata routes (
/info,/search,/album,/artist,/mix,/playlist,/cover,/lyrics,/topvideos, …) prefer a dedicated catalog credential when configured (CATALOG_TOKENor aCATALOG_*/catalog-flagged account), falling back to the pool. Catalog accounts never serve playback.
Identical concurrent metadata requests (e.g. ten users hitting the same search) are coalesced into one upstream call. Metadata responses are cached for an hour, then served stale for another hour while a background refresh runs (so expiry never causes a user-facing miss); repeat errors are cached briefly (404s for 60s, 429/5xx for 15s). Cache keys are canonicalized, so encoding or param-order variants of the same request share one entry. Watch X-Cache (HIT/STALE/NEGATIVE/MISS) and the Cache card (hits, misses, stale, negative).
Running more than one instance (e.g. several Render hosts sharing the load)? Point them at one shared Redis database and they coordinate through it instead of drifting apart. Two backends, same key layout and behavior — a host belongs to exactly one pool, so set only one per fleet:
- Upstash backend:
UPSTASH_REDIS_REST_URL+UPSTASH_REDIS_REST_TOKEN(Upstash Redis REST credentials, as host secrets — never commit them). - Native backend:
REDIS_POOL=rediss://user:pass@host:port/db(native Redis/Valkey over TLS — e.g. Layerbase). Wins over the Upstash pair when set; when present-but-unusable the instance stays local rather than syncing to the wrong pool. (PUBLIC_POOL_REDIS_URLstill works as a deprecated fallback.)
What gets shared:
| Synced | How |
|---|---|
| App settings (Atmos, auto-heal) | Write-through on admin save/restore; first boot seeds Redis when empty (first writer wins), later boots adopt the shared values; re-pulled every 30s |
| Tidal access tokens | Shared on refresh, reused on miss (no cross-host refresh stampedes) |
| API-key usage quotas | Fire-and-forget INCR per use, reconciled into the local counter every 60s |
| Account credentials | Write-through on add/edit/toggle/catalog-flag; union-merged at startup + every 60s (newest updated_at wins, live counters and catalog flags preserved) — a wiped host restores its accounts from Redis; explicit deletes stay deleted; backup restores win via republish |
| Fleet stats heartbeat | Every instance publishes hifi:stats:<instance-id> (total/active/premium/at, 180s TTL) on boot + every 60s; pool dashboards read the freshest record — same numbers as /admin/stats |
| API-key definitions | Same pattern (hashes/flags/quota only — raw keys are never stored anywhere) |
Without these vars everything stays local (today's single-host behavior). All Redis calls are fail-open with short timeouts: if Redis is unreachable the instance keeps serving from local state. Intentionally not synced: the metadata response cache (per-host L1), request log, proxy state. Note that anyone holding the Redis REST token can read the backed-up Tidal credentials — guard it like database access.
When a Tidal account's subscription can't access FULL quality, Tidal returns a ~30s PREVIEW manifest (FULL_REQUIRES_SUBSCRIPTION). This API never proxies the snippet as if it were the full track: it tries the next account instead, and returns 503 Preview only if no account can serve FULL — so players fall back to another source instead of playing 0:29.
Tidal appears to region lock by account, not by countryCode. Nevertheless, countryCode is still exposed for your own testing. However, the /track/ endpoint does not appear to the region-locked. This would mean that you could use the Tidal OpenAPI to request a region-locked song with countryCode (as the OpenAPI uses the countryCode parameter properly) through search/album endpoints then stream from this API.
Usually, tracks that support Atmos will have DOLBY_ATMOS in mediaMetadata.tags. To request Dolby Atmos tracks, use the new trackManifests endpoint - see its spec for more info on Atmos.
Control preference with ?atmos=true|only|off on /trackManifests and /dash (server default via ATMOS_MODE=prefer, overridable per request). Responses include a top-level atmos_available flag when the manifest actually carries an EAC3_JOC rendition. Note: Atmos needs a Dolby-capable player plus a Widevine license (proxied through /widevine); most browsers can't play EAC-3 JOC, so pass ?atmos=off for plain FLAC.
These responses are samples and you should host the API yourself.
None.
200 OK
{
"version": "2.x",
"Repo": "https://github.com/itsmeadarsh2008/hifi-api"
}Returns info about a track given ID.
id:int(required) - Tidal track ID.
200 OK
{
"version": "2.6",
"data": {
"id": 144371283,
"title": "Don't Look Back In Anger",
"duration": 328,
"replayGain": -10.46,
"peak": 0.999969,
"allowStreaming": true,
"streamReady": true,
"payToStream": false,
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"streamStartDate": "2020-08-11T00:00:00.000+0000",
"premiumStreamingOnly": false,
"trackNumber": 10,
"volumeNumber": 1,
"version": "Live at Wembley Stadium, July 2000",
"popularity": 51,
"copyright": "(P) 2000 Big Brother Recordings Ltd",
"bpm": 86,
"key": "C",
"keyScale": "MAJOR",
"url": "http://www.tidal.com/track/144371283",
"isrc": "GBBQY0002027",
"editable": false,
"explicit": true,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mediaMetadata": {
"tags": [
"LOSSLESS"
]
},
"upload": false,
"accessType": "PUBLIC",
"spotlighted": false,
"artist": {
"id": 109,
"name": "Oasis",
"handle": null,
"type": "MAIN",
"picture": "0491c8eb-c16f-409c-915d-36a79d9e6384"
},
"artists": [
{
"id": 109,
"name": "Oasis",
"handle": null,
"type": "MAIN",
"picture": "0491c8eb-c16f-409c-915d-36a79d9e6384"
}
],
"album": {
"id": 144371273,
"title": "Familiar To Millions (Live)",
"cover": "8f2d544e-2452-46de-ba70-25498434e2ef",
"vibrantColor": "#cb8784",
"videoCover": null
},
"mixes": {
"TRACK_MIX": "0010f77179063ef106e2efaac9507a"
}
}
}id:int(required) - Tidal track ID.quality:str(optional, defaultHI_RES_LOSSLESS) -HI_RES_LOSSLESS,LOSSLESS,HIGH,LOW.immersiveaudio:bool(optional, defaultFalse) - Requests immersive audio (Dolby Atmos/Sony 360). It doesn't properly work - I would use /trackManifests/ below.
{
"version": "2.0",
"data": {
"trackId": 48717877,
"assetPresentation": "FULL",
"audioMode": "STEREO",
"audioQuality": "LOSSLESS",
"manifestMimeType": "application/vnd.tidal.bts",
"manifestHash": "/smSLXXzSAVB+EsSVgyRzxtDuDo9rxPAH7n4tDwuXU4=",
"manifest": "eyJtaW1lVHlwZSI6ImF1ZGlvL2ZsYWMiLCJjb2RlY3MiOiJmbGFjIiwiZW5jcnlwdGlvblR5cGUiOiJOT05FIiwidXJscyI6WyJodHRwczovL2xnZi5hdWRpby50aWRhbC5jb20vbWVkaWF0cmFja3MvQ0FFYUt3Z0RFaWRtWWpSaVpUQmlOalUzWWpRNE4yUTVNREJsWkdKaE56bGhPR0ppT1dNME1WODJNUzV0Y0RRLzAuZmxhYz90b2tlbj0xNzY2ODcwMDU3fk5UVmlNamhtWWpkak9UTmlOV1U0TVRNM1l6SXdOVGN4TTJRM05qVmhOakptWTJFeU5EWXdNZz09Il19",
"albumReplayGain": -12.41,
"albumPeakAmplitude": 0.999969,
"trackReplayGain": -11.07,
"trackPeakAmplitude": 0.999969,
"bitDepth": 16,
"sampleRate": 44100
}
}Where manifest is either base64 encoded JSON (use "manifestMimeType": "application/vnd.tidal.bts" to identify).
Note
You should probably be using the newer endpoint /trackManifests/ instead which returns some more stuff.
{
"mimeType": "audio/flac",
"codecs": "flac",
"encryptionType": "NONE",
"urls": [
"https://lgf.audio.tidal.com/mediatracks/CAEaKwgDEidmYjRiZTBiNjU3YjQ4N2Q5MDBlZGJhNzlhOGJiOWM0MV82MS5tcDQ/0.flac?token=1766870057~NTViMjhmYjdjOTNiNWU4MTM3YzIwNTcxM2Q3NjVhNjJmY2EyNDYwMg=="
]
}{
"version": "2.0",
"data": {
"trackId": 194567102,
"assetPresentation": "FULL",
"audioMode": "STEREO",
"audioQuality": "HI_RES_LOSSLESS",
"manifestMimeType": "application/dash+xml",
"manifestHash": "yyQEQ8ZX8ITLjQfFu0ADBdh/y03PpUd0NEPBz7RcuHk=",
"manifest": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48TVBEIHhtbG5zPSJ1cm46bXBlZzpkYXNoOnNjaGVtYTptcGQ6MjAxMSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmNlbmM9InVybjptcGVnOmNlbmM6MjAxMyIgeHNpOnNjaGVtYUxvY2F0aW9uPSJ1cm46bXBlZzpkYXNoOnNjaGVtYTptcGQ6MjAxMSBEQVNILU1QRC54c2QiIHByb2ZpbGVzPSJ1cm46bXBlZzpkYXNoOnByb2ZpbGU6aXNvZmYtbWFpbjoyMDExIiB0eXBlPSJzdGF0aWMiIG1pbkJ1ZmZlclRpbWU9IlBUMy45OTNTIiBtZWRpYVByZXNlbnRhdGlvbkR1cmF0aW9uPSJQVDJNNDIuODc5UyI+PFBlcmlvZCBpZD0iMCI+PEFkYXB0YXRpb25TZXQgaWQ9IjAiIGNvbnRlbnRUeXBlPSJhdWRpbyIgbWltZVR5cGU9ImF1ZGlvL21wNCIgc2VnbWVudEFsaWdubWVudD0idHJ1ZSI+PFJlcHJlc2VudGF0aW9uIGlkPSIwIiBjb2RlY3M9ImZsYWMiIGJhbmR3aWR0aD0iMTY2NzU1MyIgYXVkaW9TYW1wbGluZ1JhdGU9IjQ0MTAwIj48U2VnbWVudFRlbXBsYXRlIHRpbWVzY2FsZT0iNDQxMDAiIGluaXRpYWxpemF0aW9uPSJodHRwczovL3NwLWFkLWNmLmF1ZGlvLnRpZGFsLmNvbS9tZWRpYXRyYWNrcy9HaXNJQXhJbk9XWTBNVGs1WXpVMFpESmpaRGhqTm1RM1ptWXdOV0ZsTVdVNVpqTXpOR1ZmTmpJdWJYQTBJaUFkQUFDQVFDQUNLaENoT1h0R0VnMjNPV3duT3lra0lRRG1NZ1VOQUFDZ1FRLzAubXA0P1BvbGljeT1leUpUZEdGMFpXMWxiblFpT2lCYmV5SlNaWE52ZFhKalpTSTZJbWgwZEhCek9pOHZjM0F0WVdRdFkyWXVZWFZrYVc4dWRHbGtZV3d1WTI5dEwyMWxaR2xoZEhKaFkydHpMMGRwYzBsQmVFbHVUMWRaTUUxVWF6VlplbFV3V2tSS2FscEVhR3BPYlZFeldtMVpkMDVYUm14TlYxVTFXbXBOZWs1SFZtWk9ha2wxWWxoQk1FbHBRV1JCUVVOQlVVTkJRMHRvUTJoUFdIUkhSV2N5TTA5WGQyNVBlV3RyU1ZGRWJVMW5WVTVCUVVOblVWRXZLaUlzSWtOdmJtUnBkR2x2YmlJNmV5SkVZWFJsVEdWemMxUm9ZVzRpT25zaVFWZFRPa1Z3YjJOb1ZHbHRaU0k2TVRjMk5qZzNNRFEzTW4xOWZWMTkmYW1wO1NpZ25hdHVyZT12WH51cFNqWEJVVVRKMmdTMGRoTnVrY1ozLUNIaFNNd2ozUzIzWXVzNGpaMEV3QlNiZEJXT2xmeW5yWmxOYnQ2V0t0QjA4OGppZzM5d1YteHpERUx5RHlnTk4zb2E4Zk01cDVVaFQ3T0JKUWc2Q35pSzlEZ3FleE9ka3ZzeEpMbVlOUFdSYzJ2Qkt+TGRPbG1qNVVybEdmbGhYUHRZTn42d2g0aWQ3MHlQcllyVkNHdFZJT1ZzZlAyanpHRDFNM1EyVTkxMGNuOWdPYU15aU9YSUtncDl4MXhFajhEZW9QVDZPY3hiNC1HfmtBUzBhTDlJSFlNdn42RjMzWnU1Si1KdTFIQmN3MmNHV1IwVWZiNHM0ZUpEaE1kdWxHT1hLRmROVVlkdHVqZGdpcXBiSWlXajVWaUNieHJZa1JQVEZ0OXdncS1yMnVRWE1wOGFIZzd2MFZOV1FfXyZhbXA7S2V5LVBhaXItSWQ9SzE0TFpDWjlRVUk0SkwiIG1lZGlhPSJodHRwczovL3NwLWFkLWNmLmF1ZGlvLnRpZGFsLmNvbS9tZWRpYXRyYWNrcy9HaXNJQXhJbk9XWTBNVGs1WXpVMFpESmpaRGhqTm1RM1ptWXdOV0ZsTVdVNVpqTXpOR1ZmTmpJdWJYQTBJaUFkQUFDQVFDQUNLaENoT1h0R0VnMjNPV3duT3lra0lRRG1NZ1VOQUFDZ1FRLyROdW1iZXIkLm1wND9Qb2xpY3k9ZXlKVGRHRjBaVzFsYm5RaU9pQmJleUpTWlhOdmRYSmpaU0k2SW1oMGRIQnpPaTh2YzNBdFlXUXRZMll1WVhWa2FXOHVkR2xrWVd3dVkyOXRMMjFsWkdsaGRISmhZMnR6TDBkcGMwbEJlRWx1VDFkWk1FMVVhelZaZWxVd1drUkthbHBFYUdwT2JWRXpXbTFaZDA1WFJteE5WMVUxV21wTmVrNUhWbVpPYWtsMVlsaEJNRWxwUVdSQlFVTkJVVU5CUTB0b1EyaFBXSFJIUldjeU0wOVhkMjVQZVd0clNWRkViVTFuVlU1QlFVTm5VVkV2S2lJc0lrTnZibVJwZEdsdmJpSTZleUpFWVhSbFRHVnpjMVJvWVc0aU9uc2lRVmRUT2tWd2IyTm9WR2x0WlNJNk1UYzJOamczTURRM01uMTlmVjE5JmFtcDtTaWduYXR1cmU9dlh+dXBTalhCVVVUSjJnUzBkaE51a2NaMy1DSGhTTXdqM1MyM1l1czRqWjBFd0JTYmRCV09sZnluclpsTmJ0NldLdEIwODhqaWczOXdWLXh6REVMeUR5Z05OM29hOGZNNXA1VWhUN09CSlFnNkN+aUs5RGdxZXhPZGt2c3hKTG1ZTlBXUmMydkJLfkxkT2xtajVVcmxHZmxoWFB0WU5+NndoNGlkNzB5UHJZclZDR3RWSU9Wc2ZQMmp6R0QxTTNRMlU5MTBjbjlnT2FNeWlPWElLZ3A5eDF4RWo4RGVvUFQ2T2N4YjQtR35rQVMwYUw5SUhZTXZ+NkYzM1p1NUotSnUxSEJjdzJjR1dSMFVmYjRzNGVKRGhNZHVsR09YS0ZkTlVZZHR1amRnaXFwYklpV2o1VmlDYnhyWWtSUFRGdDl3Z3EtcjJ1UVhNcDhhSGc3djBWTldRX18mYW1wO0tleS1QYWlyLUlkPUsxNExaQ1o5UVVJNEpMIiBzdGFydE51bWJlcj0iMSI+PFNlZ21lbnRUaW1lbGluZT48UyBkPSIxNzYxMjgiIHI9IjM5Ii8+PFMgZD0iMTM3ODYwIi8+PC9TZWdtZW50VGltZWxpbmU+PC9TZWdtZW50VGVtcGxhdGU+PExhYmVsPkZMQUNfSElSRVM8L0xhYmVsPjwvUmVwcmVzZW50YXRpb24+PC9BZGFwdGF0aW9uU2V0PjwvUGVyaW9kPjwvTVBEPg==",
"albumReplayGain": -8.91,
"albumPeakAmplitude": 0.970377,
"trackReplayGain": -8.91,
"trackPeakAmplitude": 0.970377,
"bitDepth": 24,
"sampleRate": 44100
}
}Where manifest is base64 encoded MPD manifest (use "manifestMimeType": "application/dash+xml" to identify).
<?xml version='1.0' encoding='UTF-8'?>
<MPD
xmlns="urn:mpeg:dash:schema:mpd:2011"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:cenc="urn:mpeg:cenc:2013" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-main:2011" type="static" minBufferTime="PT3.993S" mediaPresentationDuration="PT2M42.879S">
<Period id="0">
<AdaptationSet id="0" contentType="audio" mimeType="audio/mp4" segmentAlignment="true">
<Representation id="0" codecs="flac" bandwidth="1667553" audioSamplingRate="44100">
<SegmentTemplate timescale="44100" initialization="https://sp-ad-cf.audio.tidal.com/mediatracks/GisIAxInOWY0MTk5YzU0ZDJjZDhjNmQ3ZmYwNWFlMWU5ZjMzNGVfNjIubXA0IiAdAACAQCACKhChOXtGEg23OWwnOykkIQDmMgUNAACgQQ/0.mp4?Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6Imh0dHBzOi8vc3AtYWQtY2YuYXVkaW8udGlkYWwuY29tL21lZGlhdHJhY2tzL0dpc0lBeEluT1dZME1UazVZelUwWkRKalpEaGpObVEzWm1Zd05XRmxNV1U1WmpNek5HVmZOakl1YlhBMElpQWRBQUNBUUNBQ0toQ2hPWHRHRWcyM09Xd25PeWtrSVFEbU1nVU5BQUNnUVEvKiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTc2Njg3MDQ3Mn19fV19&Signature=vX~upSjXBUUTJ2gS0dhNukcZ3-CHhSMwj3S23Yus4jZ0EwBSbdBWOlfynrZlNbt6WKtB088jig39wV-xzDELyDygNN3oa8fM5p5UhT7OBJQg6C~iK9DgqexOdkvsxJLmYNPWRc2vBK~LdOlmj5UrlGflhXPtYN~6wh4id70yPrYrVCGtVIOVsfP2jzGD1M3Q2U910cn9gOaMyiOXIKgp9x1xEj8DeoPT6Ocxb4-G~kAS0aL9IHYMv~6F33Zu5J-Ju1HBcw2cGWR0Ufb4s4eJDhMdulGOXKFdNUYdtujdgiqpbIiWj5ViCbxrYkRPTFt9wgq-r2uQXMp8aHg7v0VNWQ__&Key-Pair-Id=K14LZCZ9QUI4JL" media="https://sp-ad-cf.audio.tidal.com/mediatracks/GisIAxInOWY0MTk5YzU0ZDJjZDhjNmQ3ZmYwNWFlMWU5ZjMzNGVfNjIubXA0IiAdAACAQCACKhChOXtGEg23OWwnOykkIQDmMgUNAACgQQ/$Number$.mp4?Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6Imh0dHBzOi8vc3AtYWQtY2YuYXVkaW8udGlkYWwuY29tL21lZGlhdHJhY2tzL0dpc0lBeEluT1dZME1UazVZelUwWkRKalpEaGpObVEzWm1Zd05XRmxNV1U1WmpNek5HVmZOakl1YlhBMElpQWRBQUNBUUNBQ0toQ2hPWHRHRWcyM09Xd25PeWtrSVFEbU1nVU5BQUNnUVEvKiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTc2Njg3MDQ3Mn19fV19&Signature=vX~upSjXBUUTJ2gS0dhNukcZ3-CHhSMwj3S23Yus4jZ0EwBSbdBWOlfynrZlNbt6WKtB088jig39wV-xzDELyDygNN3oa8fM5p5UhT7OBJQg6C~iK9DgqexOdkvsxJLmYNPWRc2vBK~LdOlmj5UrlGflhXPtYN~6wh4id70yPrYrVCGtVIOVsfP2jzGD1M3Q2U910cn9gOaMyiOXIKgp9x1xEj8DeoPT6Ocxb4-G~kAS0aL9IHYMv~6F33Zu5J-Ju1HBcw2cGWR0Ufb4s4eJDhMdulGOXKFdNUYdtujdgiqpbIiWj5ViCbxrYkRPTFt9wgq-r2uQXMp8aHg7v0VNWQ__&Key-Pair-Id=K14LZCZ9QUI4JL" startNumber="1">
<SegmentTimeline>
<S d="176128" r="39"/>
<S d="137860"/>
</SegmentTimeline>
</SegmentTemplate>
<Label>FLAC_HIRES</Label>
</Representation>
</AdaptationSet>
</Period>
</MPD>Two equivalent styles (binimum-compatible query style included):
GET /trackManifests/192157851?formats=FLAC_HIRES,FLAC
GET /trackManifests/?id=192157851&formats=FLAC_HIRES&formats=FLAC
id:str(required, path or query) - Tidal track ID.formats:str(optional, defaultHEAACV1,AACLC,FLAC,FLAC_HIRES,EAC3_JOC) - Requested audio formats. Accepts comma-separated (?formats=FLAC,FLAC_HIRES) or repeated (?formats=FLAC&formats=FLAC_HIRES).adaptive:str(optional, defaulttrue) - Adaptive streaming (where multiple formats are returned in one response).manifestType:str(optional, defaultMPEG_DASH, optionsMPEG_DASH,HLS) - Manifest type.uriScheme:str(optional, defaultHTTPS, optionsHTTPS,DATA) - URI scheme. DATA returns everything in base64, HTTPS returns a link to the manifest.usage:str(optional, defaultPLAYBACK, optionsPLAYBACK,DOWNLOAD) - Usage type.countryCode:str(optional, default serverCOUNTRY_CODE) - Override region for this request.atmos:str(optional, default serverATMOS_MODE) -true/preferputsEAC3_JOCfirst,onlyrequests just it,offstrips it. Explicitformats=are always respected verbatim.
200 OK (default everything)
{
"version": "2.7",
"data": {
"data": {
"id": "85905134",
"type": "trackManifests",
"attributes": {
"trackPresentation": "FULL",
"uri": "https://im-fa.manifest.tidal.com/1/manifests/Egg4NTkwNTEzNBgCIhZuVE1BeW93OVRvekZZUzhBcEUzQmVBIhZVQmd4MDNIUjVlVlRhNmdKa0kzUTlnIhZuWmdWQk9CUHRFZTFTblNYbUlmUW5nIhZhRDVyZXBtaUY2OEdGYXJ6V0tZcll3KAEwAg.mpd?token=1774196362~ZTk0MWU2MmI1ZmEyMzI0MDc4NmMxMDdiYTg5MTgwNTA3YjY0OWJjOA==",
"hash": "nzLt3KkLfegkCxSubZodCWRrZCO1l4FpXpv6yB0kNrM=",
"formats": [
"HEAACV1",
"AACLC",
"FLAC",
"FLAC_HIRES"
],
"albumAudioNormalizationData": {
"replayGain": -10.81,
"peakAmplitude": 0.901572
},
"trackAudioNormalizationData": {
"replayGain": -10.1,
"peakAmplitude": 0.901468
}
}
},
"links": {
"self": "/trackManifests/85905134?uriScheme=HTTPS&adaptive=true&formats=AACLC%2CEAC3_JOC%2CFLAC%2CFLAC_HIRES%2CHEAACV1&usage=PLAYBACK&manifestType=MPEG_DASH"
}
}
}Note
Be aware - the API returns Atmos by default if available. Most browsers can't play Atmos - so specify every format except from Atmos to avoid it.
{
"version": "2.7",
"data": {
"data": {
"id": "434493254",
"type": "trackManifests",
"attributes": {
"trackPresentation": "FULL",
"uri": "https://im-fa.manifest.tidal.com/1/manifests/Egk0MzQ0OTMyNTQYAiIWUzVyXzNHdVlYby02RnIwSDM5aUh2USgBMAI.mpd?token=1774196401~ZGQyZjgzMDNkZjc1MTdlNTJmYmQxZjEwZjZjOGFlMWVjN2RjNjFiNA==",
"hash": "P9JIfU1+7xwdasgo84AJaGAiygOHKvsfAK3aZ1xOOLk=",
"formats": [
"EAC3_JOC"
]
}
},
"links": {
"self": "/trackManifests/434493254?uriScheme=HTTPS&adaptive=true&formats=AACLC%2CEAC3_JOC%2CFLAC%2CFLAC_HIRES%2CHEAACV1&usage=PLAYBACK&manifestType=MPEG_DASH"
}
}
}Convenience wrapper for players (mpv, ffplay): fetches the manifest and returns a 307 redirect straight to the Tidal .mpd URL.
mpv --no-ytdl "http://localhost:8000/dash/192157851"atmos:str(optional, default serverATMOS_MODE) -true/preferputsEAC3_JOCfirst,onlyrequests just it,offstrips it (plainFLAC_HIRES,FLAC,AACLCchain).
Returns 503 when the track is preview-only for all accounts (see Preview-only tracks).
Proxy endpoint for Widevine DRM license requests. Allows the frontend to seamlessly request Widevine DRM certificates and licenses while transparently appending the Tidal auth token.
None. Send the Widevine challenge in the request body.
200 OK
Returns the DRM license response.
Finds recommendations to play, given a song. Similar to the mix. Returns 20 songs.
id:int(required) - Tidal track ID.
200 OK
{
"version": "2.6",
"data": {
"limit": 20,
"offset": 0,
"totalNumberOfItems": 26,
"items": [
{
"track": {
"id": 37160635,
"title": "Under Pressure (Live at Wembley '86)",
"duration": 221,
"replayGain": -11.87,
"peak": 0.980133,
"allowStreaming": true,
"streamReady": true,
"payToStream": false,
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"streamStartDate": "2003-08-19T00:00:00.000+0000",
"premiumStreamingOnly": false,
"trackNumber": 7,
"volumeNumber": 1,
"version": null,
"popularity": 55,
"copyright": "℗ 1986 Hollywood Records, Inc.",
"bpm": 122,
"key": "D",
"keyScale": "MAJOR",
"url": "http://www.tidal.com/track/37160635",
"isrc": "GBCEE9200016",
"editable": false,
"explicit": false,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mediaMetadata": {
"tags": [
"LOSSLESS"
]
},
"upload": false,
"accessType": "PUBLIC",
"spotlighted": false,
"artist": {
"id": 8992,
"name": "Queen",
"handle": null,
"type": "MAIN",
"picture": "6ac97166-8aae-458a-b1ea-cfcc9d3cfabf"
},
"artists": [
{
"id": 8992,
"name": "Queen",
"handle": null,
"type": "MAIN",
"picture": "6ac97166-8aae-458a-b1ea-cfcc9d3cfabf"
}
],
"album": {
"id": 37160628,
"title": "Live At Wembley Stadium",
"cover": "c810ba36-a324-4f11-ac82-ab7eeacefb64",
"vibrantColor": "#c49839",
"videoCover": null
},
"mixes": {
"TRACK_MIX": "0013f3c9f7ced02e0d9a90e41d95a8"
}
},
"sources": [
"SUGGESTED_TRACKS"
]
},
<truncated>
]
}
}Specify only one of the following query fields:
s:str- track querya:str- artist queryal:str- album queryv:str- video queryp:str- playlist queryi:str- ISRC query
Pagination:
offset:int(optional, default0, min0)limit:int(optional, default25, min1, max500)
200 OK
{
"version": "2.6",
"data": {
"limit": 25,
"offset": 0,
"totalNumberOfItems": 300,
"items": [
{
"id": 427520487,
"title": "Azizam",
"duration": 162,
"replayGain": -9.95,
"peak": 0.988554,
"allowStreaming": true,
"streamReady": true,
"payToStream": false,
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"streamStartDate": "2025-04-04T00:00:00.000+0000",
"premiumStreamingOnly": false,
"trackNumber": 1,
"volumeNumber": 1,
"version": null,
"popularity": 80,
"copyright": "Gingerbread Man Records and Atlantic Records UK release, under exclusive licence to Warner Music UK Limited, ℗ 2025 Ed Sheeran Limited",
"bpm": 128,
"key": "F",
"keyScale": "MAJOR",
"url": "http://www.tidal.com/track/427520487",
"isrc": "GBAHS2500081",
"editable": false,
"explicit": false,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mediaMetadata": {
"tags": [
"LOSSLESS",
"HIRES_LOSSLESS"
]
},
"upload": false,
"accessType": null,
"spotlighted": false,
"artist": {
"id": 3995478,
"name": "Ed Sheeran",
"handle": null,
"type": "MAIN",
"picture": "05d72ae4-319f-4237-821f-1d7af9ec8acf"
},
"artists": [
{
"id": 3995478,
"name": "Ed Sheeran",
"handle": null,
"type": "MAIN",
"picture": "05d72ae4-319f-4237-821f-1d7af9ec8acf"
}
],
"album": {
"id": 427520486,
"title": "Azizam",
"cover": "5a2d656d-f965-48ba-a241-bce5ad432015",
"vibrantColor": "#db899c",
"videoCover": null
},
"mixes": {
"TRACK_MIX": "001098c806426de17f57eb9d79b8ec"
}
},
<truncated>
]
}
}{
"version": "2.6",
"data": {
"artists": {
"limit": 25,
"offset": 0,
"totalNumberOfItems": 73,
"items": [
{
"id": 8812,
"name": "Coldplay",
"artistTypes": [
"ARTIST",
"CONTRIBUTOR"
],
"url": "http://www.tidal.com/artist/8812",
"picture": "b4579672-5b91-4679-a27a-288f097a4da5",
"selectedAlbumCoverFallback": null,
"popularity": 92,
"artistRoles": [
{
"categoryId": -1,
"category": "Artist"
},
{
"categoryId": 1,
"category": "Producer"
},
{
"categoryId": 11,
"category": "Performer"
},
{
"categoryId": 2,
"category": "Songwriter"
},
{
"categoryId": 10,
"category": "Production team"
},
{
"categoryId": 99,
"category": "Misc"
}
],
"mixes": {
"ARTIST_MIX": "000d63462309f499a611e73b4992bd"
},
"handle": null,
"userId": null,
"spotlighted": false
},
{
"id": 39476431,
"name": "Coldplay Piano Covers",
"artistTypes": [
"ARTIST",
"CONTRIBUTOR"
],
"url": "http://www.tidal.com/artist/39476431",
"picture": "3e88ec5b-0058-4185-8c1c-385098528f40",
"selectedAlbumCoverFallback": "3e88ec5b-0058-4185-8c1c-385098528f40",
"popularity": 28,
"artistRoles": [
{
"categoryId": -1,
"category": "Artist"
}
],
"mixes": {
},
"handle": null,
"userId": null,
"spotlighted": false
},
<truncated>
]
}
}id:int(required) - album ID.limit:int(optional, default100, min1, max500) - number of album items.offset:int(optional, default0, min0) - item offset.
200 OK
{
"version": "2.6",
"data": {
"id": 58990510,
"title": "OK Computer",
"duration": 3216,
"streamReady": true,
"payToStream": false,
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"streamStartDate": "2023-11-21T00:00:00.000+0000",
"allowStreaming": true,
"premiumStreamingOnly": false,
"numberOfTracks": 12,
"numberOfVideos": 0,
"numberOfVolumes": 1,
"releaseDate": "1997-07-01",
"copyright": "XL Recordings Ltd",
"type": "ALBUM",
"version": null,
"url": "http://www.tidal.com/album/58990510",
"cover": "e77e4cc0-6cd0-4522-807d-88aeac488065",
"vibrantColor": "#a8cada",
"videoCover": null,
"explicit": false,
"upc": "634904078164",
"popularity": 83,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mediaMetadata": {
"tags": [
"LOSSLESS"
]
},
"upload": false,
"artist": {
"id": 64518,
"name": "Radiohead",
"handle": null,
"type": "MAIN",
"picture": "600a6117-32bb-4f9a-ac2b-206cbf1db419"
},
"artists": [
{
"id": 64518,
"name": "Radiohead",
"handle": null,
"type": "MAIN",
"picture": "600a6117-32bb-4f9a-ac2b-206cbf1db419"
}
],
"items": [
{
"item": {
"id": 58990511,
"title": "Airbag",
"duration": 287,
"replayGain": -10.77,
"peak": 0.980682,
"allowStreaming": true,
"streamReady": true,
"payToStream": false,
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"streamStartDate": "2023-11-21T00:00:00.000+0000",
"premiumStreamingOnly": false,
"trackNumber": 1,
"volumeNumber": 1,
"version": null,
"popularity": 74,
"copyright": "XL Recordings Ltd",
"bpm": 166,
"key": "A",
"keyScale": null,
"url": "http://www.tidal.com/track/58990511",
"isrc": "GBAYE9701274",
"editable": false,
"explicit": false,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mediaMetadata": {
"tags": [
"LOSSLESS"
]
},
"upload": false,
"accessType": "PUBLIC",
"spotlighted": false,
"artist": {
"id": 64518,
"name": "Radiohead",
"handle": null,
"type": "MAIN",
"picture": "0968a9dd-9536-4bc2-84a2-ab65c8926bdc"
},
"artists": [
{
"id": 64518,
"name": "Radiohead",
"handle": null,
"type": "MAIN",
"picture": "0968a9dd-9536-4bc2-84a2-ab65c8926bdc"
}
],
"album": {
"id": 58990510,
"title": "OK Computer",
"cover": "e77e4cc0-6cd0-4522-807d-88aeac488065",
"vibrantColor": "#a8cada",
"videoCover": null
},
"mixes": {
"TRACK_MIX": "0015963a9a23be922134195a634872"
}
},
"type": "track"
},
<truncated>
]
}
}Kind of like recommendations, except they are usually 60 tracks.
id:str(required) - mix ID.
200 OK
{
"version": "2.6",
"mix": {
"id": "0019a6f811ccf59fd0346967a1dea7",
"title": "Subterranean Homesick Alien",
"subTitle": "Radiohead",
"description": null,
"graphic": {
"type": "SQUARES_GRID",
"text": "Subterranean Homesick Alien",
"images": [
{
"id": "dummy-placeholder",
"vibrantColor": "#FFFFFF",
"type": "ARTIST"
}
]
},
"images": {
"SMALL": {
"width": 320,
"height": 320,
"url": "https://images.tidal.com/0/EMACGMACIKABKKAB/CAEQBhokZTc3ZTRjYzAvNmNkMC80NTIyLzgwN2QvODhhZWFjNDg4MDY1GiRiMjFmZDJmYy8yZDc2LzRlYmMvYTQzNC84Njg2YzQ3NWZjMTAaJDY4NWYxZjRjLzI5NTYvNDBlNi9iODFjL2ZmYzU0MGQ2NjA2ZCILVHJhY2sgUmFkaW8iG1N1YnRlcnJhbmVhbiBIb21lc2ljayBBbGllbioHI0E4Q0FEQTAC?token=8414f91d1fe7b2e31719b2567707cab310bbe2e9"
},
"MEDIUM": {
"width": 640,
"height": 640,
"url": "https://images.tidal.com/0/EIAFGIAFIMACKMAC/CAEQBhokZTc3ZTRjYzAvNmNkMC80NTIyLzgwN2QvODhhZWFjNDg4MDY1GiRiMjFmZDJmYy8yZDc2LzRlYmMvYTQzNC84Njg2YzQ3NWZjMTAaJDY4NWYxZjRjLzI5NTYvNDBlNi9iODFjL2ZmYzU0MGQ2NjA2ZCILVHJhY2sgUmFkaW8iG1N1YnRlcnJhbmVhbiBIb21lc2ljayBBbGllbioHI0E4Q0FEQTAC?token=518de937f6ae775faec893fdc709d4ad146b5e34"
},
"LARGE": {
"width": 1500,
"height": 1500,
"url": "https://images.tidal.com/0/ENwLGNwLIO4FKO4F/CAEQBhokZTc3ZTRjYzAvNmNkMC80NTIyLzgwN2QvODhhZWFjNDg4MDY1GiRiMjFmZDJmYy8yZDc2LzRlYmMvYTQzNC84Njg2YzQ3NWZjMTAaJDY4NWYxZjRjLzI5NTYvNDBlNi9iODFjL2ZmYzU0MGQ2NjA2ZCILVHJhY2sgUmFkaW8iG1N1YnRlcnJhbmVhbiBIb21lc2ljayBBbGllbioHI0E4Q0FEQTAC?token=cbfbe06ee9b1e54e59ffb4bd4eaca73b027b7842"
}
},
"sharingImages": null,
"mixType": "TRACK_MIX",
"mixNumber": null,
"contentBehavior": "UNRESTRICTED",
"master": false,
"titleColor": "#A8CADA",
"subTitleColor": "#A8CADA",
"descriptionColor": null,
"detailImages": {
"SMALL": {
"width": 320,
"height": 320,
"url": "https://images.tidal.com/0/EMACGMACIKABKKAB/CAEQBhokZTc3ZTRjYzAvNmNkMC80NTIyLzgwN2QvODhhZWFjNDg4MDY1GiRiMjFmZDJmYy8yZDc2LzRlYmMvYTQzNC84Njg2YzQ3NWZjMTAaJDY4NWYxZjRjLzI5NTYvNDBlNi9iODFjL2ZmYzU0MGQ2NjA2ZCILVHJhY2sgUmFkaW8iG1N1YnRlcnJhbmVhbiBIb21lc2ljayBBbGllbioHI0E4Q0FEQTACOAE?token=daf8f7b393c2285944a7e0c05eb79c2a47b027df"
},
"MEDIUM": {
"width": 640,
"height": 640,
"url": "https://images.tidal.com/0/EIAFGIAFIMACKMAC/CAEQBhokZTc3ZTRjYzAvNmNkMC80NTIyLzgwN2QvODhhZWFjNDg4MDY1GiRiMjFmZDJmYy8yZDc2LzRlYmMvYTQzNC84Njg2YzQ3NWZjMTAaJDY4NWYxZjRjLzI5NTYvNDBlNi9iODFjL2ZmYzU0MGQ2NjA2ZCILVHJhY2sgUmFkaW8iG1N1YnRlcnJhbmVhbiBIb21lc2ljayBBbGllbioHI0E4Q0FEQTACOAE?token=3405ef092d0afa08bebb431aa7489b0399470b50"
},
"LARGE": {
"width": 1500,
"height": 1500,
"url": "https://images.tidal.com/0/ENwLGNwLIO4FKO4F/CAEQBhokZTc3ZTRjYzAvNmNkMC80NTIyLzgwN2QvODhhZWFjNDg4MDY1GiRiMjFmZDJmYy8yZDc2LzRlYmMvYTQzNC84Njg2YzQ3NWZjMTAaJDY4NWYxZjRjLzI5NTYvNDBlNi9iODFjL2ZmYzU0MGQ2NjA2ZCILVHJhY2sgUmFkaW8iG1N1YnRlcnJhbmVhbiBIb21lc2ljayBBbGllbioHI0E4Q0FEQTACOAE?token=af709901ccac4866e329df7d082a6601d73bf10a"
}
},
"shortSubtitle": "Created by TIDAL"
},
"items": [
{
"id": 58990513,
"title": "Subterranean Homesick Alien",
"duration": 267,
"version": null,
"url": "https://tidal.com/browse/track/58990513",
"artists": [
{
"id": 64518,
"name": "Radiohead",
"type": "MAIN",
"picture": "0968a9dd-9536-4bc2-84a2-ab65c8926bdc",
"handle": null,
"userId": null
}
],
"album": {
"id": 58990510,
"title": "OK Computer",
"cover": "e77e4cc0-6cd0-4522-807d-88aeac488065",
"vibrantColor": "#a8cada",
"videoCover": null,
"url": "https://tidal.com/browse/album/58990510",
"releaseDate": "1997-07-01"
},
"explicit": false,
"volumeNumber": 1,
"trackNumber": 3,
"popularity": 76,
"doublePopularity": 0.7603010414769,
"allowStreaming": true,
"streamReady": true,
"streamStartDate": "2023-11-21T00:00:00.000+0000",
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"editable": false,
"replayGain": -10.77,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mixes": {
"TRACK_MIX": "0019a6f811ccf59fd0346967a1dea7"
},
"mediaMetadata": {
"tags": [
"LOSSLESS"
]
},
"upload": false,
"payToStream": false,
"accessType": "PUBLIC",
"spotlighted": false
},
<truncated>
]
}id:str(required) - playlist UUID.limit:int(optional, default100, min1, max500) - number of playlist items.offset:int(optional, default0, min0) - item offset.
200 OK
{
"version": "2.6",
"playlist": {
"uuid": "626d146b-04f6-4936-bbf6-a65318f740a1",
"title": "2010s Pop Hits",
"numberOfTracks": 100,
"numberOfVideos": 0,
"creator": {
"id": 0
},
"description": "The biggest, brightest, and baddest pop hits from the past decade. (Cover: Bruno Mars // Photo: Atlantic Records/Press)",
"duration": 22651,
"lastUpdated": "2025-01-27T17:15:24.016+0000",
"created": "2019-12-13T05:38:27.800+0000",
"type": "EDITORIAL",
"publicPlaylist": true,
"url": "http://www.tidal.com/playlist/626d146b-04f6-4936-bbf6-a65318f740a1",
"image": "dafff826-e77d-4847-bf56-ad5e2f5c377c",
"popularity": 0,
"squareImage": "b15bb487-dd6e-45ff-9e50-ee5083f20669",
"customImageUrl": null,
"promotedArtists": [
{
"id": 8722,
"name": "Mark Ronson",
"handle": null,
"type": "MAIN",
"picture": null
},
{
"id": 4332277,
"name": "Ariana Grande",
"handle": null,
"type": "MAIN",
"picture": null
},
{
"id": 3531205,
"name": "Katy Perry",
"handle": null,
"type": "MAIN",
"picture": null
},
{
"id": 10665,
"name": "Rihanna",
"handle": null,
"type": "MAIN",
"picture": null
}
],
"lastItemAddedAt": "2025-01-22T04:12:16.941+0000"
},
"items": [
{
"item": {
"id": 39249713,
"title": "Uptown Funk (feat. Bruno Mars)",
"duration": 270,
"replayGain": -7.79,
"peak": 0.94406,
"allowStreaming": true,
"streamReady": true,
"payToStream": false,
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"streamStartDate": "2015-01-13T00:00:00.000+0000",
"premiumStreamingOnly": false,
"trackNumber": 4,
"volumeNumber": 1,
"version": null,
"popularity": 91,
"copyright": "(P) 2014 Mark Ronson under exclusive licence to Sony Music Entertainment UK Limited",
"bpm": 115,
"key": "C",
"keyScale": "MAJOR",
"description": null,
"url": "http://www.tidal.com/track/39249713",
"isrc": "GBARL1401524",
"editable": false,
"explicit": false,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mediaMetadata": {
"tags": [
"LOSSLESS",
"HIRES_LOSSLESS"
]
},
"upload": false,
"accessType": "PUBLIC",
"spotlighted": false,
"artist": {
"id": 8722,
"name": "Mark Ronson",
"handle": null,
"type": "MAIN",
"picture": "94adc4e5-b2ab-475d-b2e6-ecb96a77ebcc"
},
"artists": [
{
"id": 8722,
"name": "Mark Ronson",
"handle": null,
"type": "MAIN",
"picture": "94adc4e5-b2ab-475d-b2e6-ecb96a77ebcc"
},
{
"id": 3658521,
"name": "Bruno Mars",
"handle": null,
"type": "FEATURED",
"picture": "12139dfb-f192-4481-9794-c9fb7d1e2476"
}
],
"album": {
"id": 39249709,
"title": "Uptown Special",
"cover": "2f507eba-07f8-4bf5-a32b-9aa5c1a9840d",
"vibrantColor": "#f0e76a",
"videoCover": null,
"releaseDate": "2015-01-26"
},
"mixes": {
"TRACK_MIX": "001f7dfc4bcd0b25da782de2e5045f"
},
"dateAdded": "2023-03-01T23:23:53.167+0000",
"index": 25000,
"itemUuid": "729ba2c2-cad0-4e90-a0c3-dd8d1f76c069"
},
"type": "track",
"cut": null
},
<truncated>
]
}id:int(required) - artist ID.cursor:int | str(optional) - cursor for paginated results.
200 OK
{
"version": "2.6",
"artists": [
{
"name": "Beyoncé",
"popularity": 0.958293782719296,
"externalLinks": [
{
"href": "https://tidal.com/browse/artist/1566",
"meta": {
"type": "TIDAL_SHARING"
}
}
],
"spotlighted": false,
"contributionsEnabled": false,
"ownerType": "LABEL",
"id": 1566,
"picture": "3e712fb2-9610-4cab-ac20-fb63cfcaa45f",
"url": "http://www.tidal.com/artist/1566",
"relationType": "SIMILAR_ARTIST"
},
<truncated>
]
}id:int(required) - album ID.cursor:int | str(optional) - cursor for paginated results.
200 OK
{
"version": "2.6",
"albums": [
{
"title": "The College Dropout",
"barcodeId": "00602567922186",
"numberOfVolumes": 1,
"numberOfItems": 21,
"duration": "PT1H16M24S",
"explicit": true,
"releaseDate": "2004-02-10",
"copyright": {
"text": "© 2004 UMG Recordings, Inc."
},
"popularity": 0.849979392325809,
"accessType": "PUBLIC",
"availability": [
"STREAM",
"DJ"
],
"mediaTags": [
"LOSSLESS"
],
"externalLinks": [
{
"href": "https://tidal.com/browse/album/92099357",
"meta": {
"type": "TIDAL_SHARING"
}
}
],
"type": "ALBUM",
"albumType": "ALBUM",
"createdAt": "2018-07-16T21:57:06Z",
"id": 92099357,
"cover": "cc77193c-a074-4538-a8b5-307b2a44169e",
"artists": [
{
"id": 25022,
"name": "Kanye West"
}
],
"url": "http://www.tidal.com/album/92099357"
},
<truncated>
]
}Provide id or f.
id:int(optional) - fetch artist metadata and generated cover URL.f:int(optional) - fetch artist releases and aggregate tracks.skip_tracks:bool(optional, defaultfalse) - withf, skip album-track aggregation and return top tracks.
200 OK
{
"version": "2.6",
"artist": {
"id": 25022,
"name": "Kanye West",
"artistTypes": [
"ARTIST",
"CONTRIBUTOR"
],
"url": "http://www.tidal.com/artist/25022",
"picture": "0948decd-5591-4b83-b188-8314bfbe7fd3",
"selectedAlbumCoverFallback": null,
"popularity": 96,
"artistRoles": [
{
"categoryId": -1,
"category": "Artist"
},
{
"categoryId": 2,
"category": "Songwriter"
},
{
"categoryId": 1,
"category": "Producer"
},
{
"categoryId": 11,
"category": "Performer"
},
{
"categoryId": 10,
"category": "Production team"
},
{
"categoryId": 3,
"category": "Engineer"
},
{
"categoryId": 99,
"category": "Misc"
}
],
"mixes": {
"ARTIST_MIX": "000a58346749c76f7f6f58bf9cef7a"
},
"handle": null,
"userId": null,
"spotlighted": false
},
"cover": {
"id": 25022,
"name": "Kanye West",
"750": "https://resources.tidal.com/images/0948decd/5591/4b83/b188/8314bfbe7fd3/750x750.jpg"
}
}Response on this endpoint is much slower because it has to fetch much more metadata.
200 OK
{
"version": "2.6",
"albums": {
"items": [
{
"id": 440425318,
"title": "DONDA 2",
"duration": 3490,
"streamReady": true,
"payToStream": false,
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"streamStartDate": "2025-06-06T00:00:00.000+0000",
"allowStreaming": true,
"premiumStreamingOnly": false,
"numberOfTracks": 21,
"numberOfVideos": 0,
"numberOfVolumes": 1,
"releaseDate": "2025-05-10",
"copyright": "2025 YZY",
"type": "ALBUM",
"version": null,
"url": "http://www.tidal.com/album/440425318",
"cover": "e7a15eaf-494a-4535-ae0e-25f7221ba527",
"vibrantColor": null,
"videoCover": null,
"explicit": true,
"upc": "0692788674308",
"popularity": 68,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mediaMetadata": {
"tags": [
"LOSSLESS",
"HIRES_LOSSLESS"
]
},
"upload": false,
"artist": {
"id": 5775484,
"name": "Donda",
"handle": null,
"type": "MAIN",
"picture": null
},
"artists": [
{
"id": 5775484,
"name": "Donda",
"handle": null,
"type": "MAIN",
"picture": null
},
{
"id": 25022,
"name": "Kanye West",
"handle": null,
"type": "MAIN",
"picture": "0948decd-5591-4b83-b188-8314bfbe7fd3"
},
{
"id": 5909698,
"name": "Ye",
"handle": null,
"type": "MAIN",
"picture": null
}
]
},
<truncated>
]
},
"tracks": [
{
"id": 440425319,
"title": "TRUE LOVE",
"duration": 137,
"version": null,
"url": "https://tidal.com/browse/track/440425319",
"artists": [
{
"id": 5775484,
"name": "Donda",
"type": "MAIN",
"picture": null,
"handle": null,
"userId": null
},
{
"id": 25022,
"name": "Kanye West",
"type": "MAIN",
"picture": "0948decd-5591-4b83-b188-8314bfbe7fd3",
"handle": null,
"userId": null
},
{
"id": 5909698,
"name": "Ye",
"type": "MAIN",
"picture": null,
"handle": null,
"userId": null
}
],
"album": {
"id": 440425318,
"title": "DONDA 2",
"cover": "e7a15eaf-494a-4535-ae0e-25f7221ba527",
"vibrantColor": null,
"videoCover": null,
"url": "https://tidal.com/browse/album/440425318",
"releaseDate": "2025-05-10"
},
"explicit": true,
"volumeNumber": 1,
"trackNumber": 1,
"popularity": 49,
"doublePopularity": 0.494079662855111,
"allowStreaming": true,
"streamReady": true,
"streamStartDate": "2025-06-06T00:00:00.000+0000",
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"editable": false,
"replayGain": -9.41,
"audioQuality": "LOSSLESS",
"audioModes": [
"STEREO"
],
"mixes": {
"TRACK_MIX": "00135a8af60167df440a30b939ce26"
},
"mediaMetadata": {
"tags": [
"LOSSLESS",
"HIRES_LOSSLESS"
]
},
"upload": false,
"payToStream": false,
"accessType": "PUBLIC",
"spotlighted": false
},
<truncated>
]
}Provide id or q.
id:int(optional) - track ID.q:str(optional) - track search query.
200 OK
{
"version": "2.6",
"covers": [
{
"id": 311222965,
"name": "Broke with Expensive Taste",
"1280": "https://resources.tidal.com/images/c50c9146/3c7a/44e6/a1bc/55b20516eb29/1280x1280.jpg",
"640": "https://resources.tidal.com/images/c50c9146/3c7a/44e6/a1bc/55b20516eb29/640x640.jpg",
"80": "https://resources.tidal.com/images/c50c9146/3c7a/44e6/a1bc/55b20516eb29/80x80.jpg"
}
]
}id:int(required) - track ID.
200 OK
{
"version": "2.6",
"lyrics": {
"trackId": 39249713,
"lyricsProvider": "MUSIXMATCH",
"providerCommontrackId": "190482820",
"providerLyricsId": "37850929",
"lyrics": "Doh\nDoh-doh-doh, doh-doh-doh, doh-doh\nDoh-doh-doh, doh-doh-doh, doh-doh\nDoh-doh-doh, doh-doh-doh, doh-doh\nDoh-doh-doh, doh-doh (ah, ow)\n\nThis hit, that ice-cold <truncated>",
"subtitles": "[00:00.04] Doh\n[00:01.98] Doh-doh-doh, doh-doh-doh, doh-doh\n[00:05.93] Doh-doh-doh, doh-doh-doh, doh-doh\n[00:10.22] Doh-doh-doh, doh-doh-doh, doh-doh\n[00:14.44] Doh-doh-doh, doh-doh (ah, ow)\n[00:16.70] This hit, that ice-cold <truncated>",
"isRightToLeft": false
}
}countryCode:str(optional, defaultUS) - Tidal country code.locale:str(optional, defaulten_US) - locale.deviceType:str(optional, defaultBROWSER) - device type.limit:int(optional, default25, min1, max100) - videos per page.offset:int(optional, default0, min0) - pagination offset.
200 OK
{
"version": "2.6",
"videos": [
{
"id": "eyJwIjoiZmE1MjQ1ZTItYzgyYi00YWE2LTgwN2UtNDE5OTgyOGEyMmU1IiwicFYiOjQsIm0iOiIxMjNiMmI5Mi02NTkwLTQ2ZjMtOGE2Ny1jYjBjNmZlZDljYTMiLCJtViI6MSwibUgiOiJlZTYyYTZjYSJ9",
"type": "VIDEO_LIST",
"width": 100,
"scroll": "VERTICAL",
"title": "",
"description": "",
"showMore": null,
"pagedList": {
"dataApiPath": "pages/data/85db1b03-a853-4628-8836-9e883c6fa4bb",
"limit": 100,
"offset": 0,
"totalNumberOfItems": 100,
"items": [
{
"id": 402643865,
"title": "Winter Ahead (with PARK HYO SHIN)",
"duration": 372,
"version": null,
"url": "https://tidal.com/browse/video/402643865",
"artists": [
{
"id": 29927033,
"name": "V",
"type": "MAIN",
"picture": "fc9f21fd-0384-49c9-921c-ddbfce335156",
"handle": null,
"userId": null
},
{
"id": 4239174,
"name": "Park Hyo Shin",
"type": "MAIN",
"picture": "4f43f34e-7c53-4b24-9596-d25ce157f048",
"handle": null,
"userId": null
}
],
"album": null,
"explicit": false,
"volumeNumber": 0,
"trackNumber": 0,
"popularity": 52,
"doublePopularity": 0.519117817177637,
"allowStreaming": true,
"streamReady": true,
"streamStartDate": "2024-11-29T00:00:00.000+0000",
"adSupportedStreamReady": true,
"djReady": true,
"stemReady": false,
"imageId": "efba0086-c3b8-40bd-9b45-721945816ed3",
"vibrantColor": "#f0090f",
"releaseDate": "2024-11-29",
"type": "Music Video",
"adsUrl": null,
"adsPrePaywallOnly": true
},
<truncated>
]
},
"supportsPaging": false,
"showTableHeaders": false,
"listFormat": null,
"layout": null,
"quickPlay": false,
"preTitle": null
}
],
"total": 1
}Warning
This endpoint is - for some reason - heavily rate limited on Tidal's end. Take care.
id:int(required) - video ID.quality:str(optional, defaultHIGH) -HIGH,MEDIUM,LOW.mode:str(optional, defaultSTREAM) -STREAM,OFFLINE.presentation:str(optional, defaultFULL) -FULL,PREVIEW.
200 OK
{
"version": "2.6",
"video": {
"videoId": 48204106,
"streamType": "ON_DEMAND",
"assetPresentation": "FULL",
"videoQuality": "HIGH",
"manifestMimeType": "application/vnd.tidal.emu",
"manifestHash": "fU3b2NNlidH7ZvUhBSKbJCuDlTeOay1RPqptFQLTt1U=",
"manifest": "eyJtaW1lVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5hcHBsZS5tcGVndXJsIiwidXJscyI6WyJodHRwczovL2ltLWZhLm1hbmlmZXN0LnRpZGFsLmNvbS8xL21hbmlmZXN0cy9DQUVTQ0RRNE1qQTBNVEEySWhaWFJXcDJVVUowWjB4aFgxaGpjMGMxTkdkcmEzWkJJaFkyTURWcFR6RnBPREJPVm5sRmVuWlVkRk41TmtwQkloWTRkWGx4ZVVaamJETmtPVWxyTW5wU1ozZDJSRmhuSWhaRVRVNVJkRU4yY2xOcWFFZEJXbk53TlVWbmFIcG5JaFkwTm1KMVozaGtXRXBPWTBJNFptUmpZbVJrWWpSUktBRXdBbEFCLm0zdTg/dG9rZW49MTc3MjU3NDYzMH5NalV5T0RRelpqRmpOakJsWWpSaE5qSmxZV1UwTVRFek56TXdNRFEyWm1Nek56RXhabVkwT0E9PSJdfQ=="
}
}where manifest is base64-encoded JSON containing HLS video.
{
"mimeType":"application/vnd.apple.mpegurl","urls":[
"https://im-fa.manifest.tidal.com/1/manifests/CAESCDQ4MjA0MTA2IhZXRWp2UUJ0Z0xhX1hjc0c1NGdra3ZBIhY2MDVpTzFpODBOVnlFenZUdFN5NkpBIhY4dXlxeUZjbDNkOUlrMnpSZ3d2RFhnIhZETU5RdEN2clNqaEdBWnNwNUVnaHpnIhY0NmJ1Z3hkWEpOY0I4ZmRjYmRkYjRRKAEwAlAB.m3u8?token=1772574630~MjUyODQzZjFjNjBlYjRhNjJlYWU0MTEzNzMwMDQ2ZmMzNzExZmY0OA=="
]
}#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=466000,AVERAGE-BANDWIDTH=465999,CODECS="mp4a.40.2,avc1.42C00D",RESOLUTION=320x180
https://im-fa.manifest.tidal.com/1/manifests/CAESCDQ4MjA0MTA2GAEiFjQ2YnVneGRYSk5jQjhmZGNiZGRiNFEoATACUAE.m3u8?token=1772574889~YjIxODgzM2JmOTcwNjU0NGE1ZGU4OGE2ZGZkZmI1NDA4MjYwNmI4Zg==
#EXT-X-STREAM-INF:BANDWIDTH=735000,AVERAGE-BANDWIDTH=734999,CODECS="mp4a.40.2,avc1.4D401E",RESOLUTION=640x360
https://im-fa.manifest.tidal.com/1/manifests/CAESCDQ4MjA0MTA2GAEiFkRNTlF0Q3ZyU2poR0Fac3A1RWdoemcoATACUAE.m3u8?token=1772574889~Y2FmNTU4MTY1OTlkMzJlMWUwZTczN2FiNmQxYTNkMTUxZDhhZWM2Yg==
#EXT-X-STREAM-INF:BANDWIDTH=1425000,AVERAGE-BANDWIDTH=1424999,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=854x480
https://im-fa.manifest.tidal.com/1/manifests/CAESCDQ4MjA0MTA2GAEiFjh1eXF5RmNsM2Q5SWsyelJnd3ZEWGcoATACUAE.m3u8?token=1772574889~N2RiMzZiMzI4YWJhMzQ2ZTliMTA2ZDQzN2I3YmE4YjEzZTlhZWVlZg==
#EXT-X-STREAM-INF:BANDWIDTH=2740000,AVERAGE-BANDWIDTH=2740000,CODECS="mp4a.40.2,avc1.64001F",RESOLUTION=1280x720
https://im-fa.manifest.tidal.com/1/manifests/CAESCDQ4MjA0MTA2GAEiFjYwNWlPMWk4ME5WeUV6dlR0U3k2SkEoATACUAE.m3u8?token=1772574889~MzE4YzVjNGM2Njc5YjAxY2E5OWIzYzc5NWExMTExMDc2ZjdmMWM3ZQ==
#EXT-X-STREAM-INF:BANDWIDTH=5447000,AVERAGE-BANDWIDTH=5447000,CODECS="mp4a.40.2,avc1.640028",RESOLUTION=1920x1080
https://im-fa.manifest.tidal.com/1/manifests/CAESCDQ4MjA0MTA2GAEiFldFanZRQnRnTGFfWGNzRzU0Z2trdkEoATACUAE.m3u8?token=1772574889~NGYzNmJjNjU4ZjQwNjZkODVhNThhZWI3Y2MwNTU3NzEzMWUzMWI0MQ==
Removed: playback requests execute directly with no queue, so these endpoints no longer exist (stale polls get 404 — just re-request the track). Each request still uses the normal multi-account failover, bounded by a 120s op timeout.