šµ Self-hosted Tidal downloader with Docker ⢠Multi-service integration ⢠Lidarr-compatible pr
100K+
Tidarr is a Docker image that provides a web interface to download up to 24-bit 192.0 kHz media (tracks, albums, playlists, music videos) from Tidal using Tiddl python binary. Format on the fly with Beets, automatically update your Plex library, push notifications, or use it as a Lidarr provider.
Warning
**Disclaimer**
- Need an official (shared ?) Tidal account
- For educational purposes and personal use only
- Do not forget to support your local artists (merch, live, ...) šā¤ļø
linux/amd64 and linux/arm64linux/amd64 and linux/arm64)Example docker-compose.yml :
services:
tidarr:
image: cstaelen/tidarr
container_name: "tidarr"
ports:
- 8484:8484
volumes:
- /any/folder/to/tidarr/config:/shared
- /any/folder/to/library:/music
restart: "unless-stopped"
or
docker run \
--rm \
--name tidarr \
-p 8484:8484 \
-v /any/folder/to/tidarr/config:/shared \
-v /any/folder/to/library:/music \
cstaelen/tidarr:latest
Tip
**Separate processing drive**Tidarr uses
/shared/.processing/as a temporary folder during downloads. On setups where/sharedis on a small drive (e.g. SSD config drive), large downloads (like discographies) can fill it up. You can remap the processing folder to a separate drive:volumes: - ... - /path/to/media-drive/processing:/shared/.processing # Separate drive for temp downloads
(if no tiddl.json file provided) :
Authorize your device using the UI token dialog
or
docker compose exec -it -e tidarr tiddl auth login
or
docker exec -it -e tidarr tiddl auth
ā ļø Beware to set the right template path
To set your download options you can :
/your/docker/path/to/tidarr/config/.tiddl/config.toml.environment:
- ...
- PUID=1234
- PGID=123
- UMASK=0022
Default listening port is 8484 but you can override it using :
environment:
- ...
- PORT=9999
If not set, no password is required to access the app.
environment:
- ...
- ADMIN_PASSWORD=<string> # if not set, no password are required to access
Tidarr supports OIDC authentication for integration with identity providers like Keycloak, PocketID, Authentik, etc.
When OIDC is configured, the login page will display a "Login with OpenID" button instead of the password field.
environment:
- ...
- OIDC_ISSUER=https://your-oidc-provider.com
- OIDC_CLIENT_ID=tidarr
- OIDC_CLIENT_SECRET=your-client-secret
- OIDC_REDIRECT_URI=https://your-tidarr-domain.com/api/auth/oidc/callback
Note
**OIDC Configuration**
- OIDC_ISSUER: The URL of your OpenID Connect provider
- OIDC_CLIENT_ID: The client ID registered in your OIDC provider
- OIDC_CLIENT_SECRET: The client secret for your application
- OIDC_REDIRECT_URI: The callback URL (must match the one configured in your OIDC provider)
- OIDC authentication takes precedence over password authentication if both are configured
- JWT tokens are valid for 12 hours after successful authentication
Force use of tiddl.json quality value and disable quality selector in app
environment:
- ...
- LOCK_QUALITY=true
Default base path used in .m3u : ./
You can custom base path used by track path in .m3u file :
environment:
- ...
- M3U_BASEPATH_FILE="../../"
Automatically download complete albums for all tracks in a playlist. When enabled, Tidarr will extract unique album IDs from each track in the playlist and add them to the download queue.
environment:
- ...
- PLAYLIST_ALBUMS=true
Note
This feature processes playlists and mixes after the playlist download completes. Albums are added to the queue automatically, eliminating the need to manually download each album. Duplicates are avoided by tracking unique album IDs + Tiddl "skip existing" feature.
By default, Tidarr expands an artist download into individual album queue items (one item per album). This allows better control, error isolation, and retry per album.
To download an entire discography as a single tiddl job instead:
environment:
- ...
- ARTIST_SINGLE_DOWNLOAD=true
Note
When `ARTIST_SINGLE_DOWNLOAD=true`, the artist is passed directly to tiddl as a single download job. This is faster but provides less granular error handling ā if one album fails, the entire job may be affected.
Throttle downloads to avoid being rate-limited by Tidal: automatically pause the queue after N items have been downloaded, and optionally resume it after a delay.
environment:
- ...
- DOWNLOAD_BATCH_SIZE=10 # Pause queue after 10 completed downloads
- DOWNLOAD_BATCH_DELAY=60 # Auto-resume after 60 minutes
Note
`DOWNLOAD_BATCH_SIZE` and `DOWNLOAD_BATCH_DELAY` can be used independently: - `DOWNLOAD_BATCH_SIZE` alone: queue auto-pauses after N downloads, resume manually via the UI - Both together: fully automated rate-limited downloading (e.g. 10 albums every hour)
Default value is daily sync at 3 am (0 3 * * *).
You can set a custom cron expression using SYNC_CRON_EXPRESSION env var.
To run task at midnight (00:00) every Monday :
environment:
- ...
- SYNC_CRON_EXPRESSION="0 0 * * 1"
* Syntax:
You can customize Tidarr's appearance using the UI in settings dialog, or by editing the custom.css file. This file is automatically created in your config folder on first launch.
File location: /your/docker/path/to/tidarr/config/custom.css
Track your downloaded items with the history feature. When enabled, Tidarr will maintain a list of all downloaded content and mark items as already downloaded in the UI.
environment:
- ...
- ENABLE_HISTORY=true
Features:
Enable automatic Replay Gain analysis for your music library. When activated, Tidarr will scan audio files and add loudness normalization metadata using FFmpeg and rsgain.
environment:
- ...
- REPLAY_GAIN=true
Note
Replay Gain scanning happens after Beets tagging (if enabled) and before moving files to your library. The process adds minimal overhead to downloads while ensuring consistent playback volume across your music collection.
Add to your docker-compose file in environment: section :
environment:
- ...
- ENABLE_BEETS=true
Beets options in </mounted/config/folder/>beets-config.yml:
Note
Beets is locked to version **2.5.1**Starting from 2.6.0, beets added
numbaas an unconditional dependency, which requiresllvmliteto compile from source.llvmlitehas no pre-built wheels for Alpine Linux (musl libc), making installation fail on bothamd64andarm64. Upgrading beets requires switching the base image to a glibc-based distribution (e.g. Debian).
You can active:
Add to your docker-compose file in environment: section :
environment:
- ...
- PLEX_URL=<url|ip:port>
- PLEX_PUBLIC_URL=<public_url> # optional, for frontend links (if different from internal URL)
- PLEX_LIBRARY=<music_library_id>
- PLEX_TOKEN=<x-plex-token>
# Plex path to the library root
- PLEX_PATH=/path/to/music/library
source= in the URL
http://192.168.1.20:32400/web/index.html#!/media/abcdef12345678/com.plexapp.plugins.library?**source=3ā **Note
All Plex API queries are proxied through the Tidarr backend to avoid CORS issues and keep your Plex token secure. The search button displays real-time result counts (artists, albums, tracks) from your Plex library.
Doc : https://www.plexopedia.com/plex-media-server/api/library/scan-partial/ā
You can active:
Add to your docker-compose file in environment: section :
environment:
- ...
- JELLYFIN_URL=<url|ip:port>
- JELLYFIN_PUBLIC_URL=<public_url> # optional, for frontend links (if different from internal URL)
- JELLYFIN_API_KEY=<X-Emby-Token>
Note
All Jellyfin API queries are proxied through the Tidarr backend to avoid CORS issues and keep your Jellyfin API Key secure. The search button displays real-time result counts (artists, albums, tracks, videos) from your Jellyfin library.
You can activate:
Add to your docker-compose file in environment: section :
environment:
- ...
- NAVIDROME_URL=http://navidrome.url
- NAVIDROME_PUBLIC_URL=https://navidrome.public.url # optional, for frontend links (if different from internal URL)
- NAVIDROME_USER=navidrome_user
- NAVIDROME_PASSWORD=navidrome_password
Note
All Navidrome API queries are proxied through the Tidarr backend to avoid CORS issues and keep your credentials secure. The search button displays real-time result counts (artists, albums, tracks) from your Navidrome library using the Subsonic API. Library scan is triggered automatically after each download.
Add to your docker-compose file in environment: section :
environment:
- ...
- GOTIFY_URL=<url|ip:port>
- GOTIFY_TOKEN=<gotify_app_token>
Add to your docker-compose file in environment: section:
environment:
- ...
- NTFY_URL=<url|ip:port>
- NTFY_TOPIC=<ntfy_topic>
- NTFY_TOKEN=<ntfy_token_security> # optional if it is not public
- NTFY_PRIORITY=<ntfy_priority> # optional (default=3)
Add to your docker-compose file in environment: section :
environment:
- ...
- APPRISE_API_ENDPOINT=http://{apprise_api_url}:{port}/notify/{config_id}
- APPRISE_API_TAG=tidarr # optional
If no tag is defined, default tag value will be "all".
Many push over services can be used as an URL to curl with a payload. Example with MatterMost :
curl -i -X POST -H 'Content-Type: application/json' -d '{"text": "Hello, this is some text\nThis is more text. š"}' https://your-mattermost-server.com/hooks/xxx-generatedkey-xxx
You can set URL in Tidarr env vars
environment:
- ...
- PUSH_OVER_URL=https://your-mattermost-server.com/hooks/xxx-generatedkey-xxx
It should also works with other services using the same payload format {"text": "..."}.
Tidarr can be integrated with Lidarr as both a Newznab indexer and a SABnzbd download client. This allows you to leverage Lidarr's powerful library management while using Tidarr for high-quality music downloads from Tidal.
What you can do:
Note
**Quick Setup**Step 1: Configure shared volumes between Tidarr and Lidarr
services: tidarr: volumes: - ... - /path/to/lidarr/downloads:/shared/nzb_downloads # Shared download location lidarr: volumes: - .... - /path/to/lidarr/downloads:/downloads # Same physical folderStep 2: Add Tidarr as Indexer (Lidarr settings ā Indexers)
Step 3: Add Tidarr as Download Client (Lidarr settings ā Download Clients)
Notes:
- The shared download folder allows Tidarr to download files that Lidarr can then import
š Complete Setup Guideā - Detailed configuration, troubleshooting, and advanced topics
Tidarr supports two custom shell scripts during the post-processing pipeline:
custom-script.sh - Runs before files are moved to the librarycustom-post-script.sh - Runs after files are moved to the libraryYou can also install additional Python packages by placing a requirements.txt file in your root config folder.
Note
**Interact with Tidarr download process**
- Create shell scripts in your config folder (the mounted
shared/volume)- Scripts will be automatically detected and executed during post-processing
- Use
custom-post-script.shto move playlists to a separate folder, sync to external storage, etc.
If you want to use Tidarr only as UI and not download files, you can set NO_DOWNLOAD=true in the environment variables.
This way you can use Tidarr to manage your download history, watchlist, and keep benefits of json DB (sync_list.json, queue.json) to manage download via custom scripts.
Queue items are set to no_download status and never processed automatically. You can still trigger a one-off download for any individual item directly from the queue UI using the single download button.
Note
**Unecessary configurations**In NO_DOWNLOAD mode those configurations are unecessary:
- Docker library volume can be omit
.tiddl/config.tomlhas no effect
If you want to interact with Tidarr from other applications (scripts, external services, automations), you can use the Express API.
Note
**Integration with other applications**Tidarr's REST API allows you to:
- Secure API requests using
X-API-KEYheader (available in configuration dialog)- Add downloads (albums, tracks, playlists, etc.)
- Manage the queue (pause, resume, delete)
- Synchronize playlists
- Manage Tidal authentication
- Customize configuration
As I'm the only maintainer for now, user requested features can take time.
enhancement or bug tag.If you would like to support this project, please do not hesitate to make a donation. It contributes a lot to motivation, gives me the energy to continue maintaining the project and adding the features requested by the users :)
Want more features and/or contribute ? Be my guest, fork and dev <3
Check docker environment variables in compose.yml before running :
make dev
Open http://localhost:3000ā with your browser to see the result.
The docker-build Makefile target now relies on Docker Buildxā so you can produce images for several architectures in one command.
linux/amd64 and linux/arm64):make docker-build IMAGE_TAG=latest BUILD_VERSION=1.2.3
linux/arm64):make docker-build PLATFORMS=linux/arm64 IMAGE_TAG=dev BUILD_VERSION=0.0.0-dev
Run tests :
make testing-build
make testing-run
Content type
Image
Digest
sha256:7e0399cefā¦
Size
162.7 MB
Last updated
9 days ago
docker pull cstaelen/tidarr