Tidalarr is a Lidarr plugin that indexes and downloads lossless and hi-res audio from the Tidal streaming service. It ships as a single merged DLL (Lidarr.Plugin.Tidalarr.dll) targeting net8.0.
- Version: 1.2.9
- Repository: https://github.com/RicherTunes/Tidalarr
- License: MIT
Who is this for? Lidarr users with a Tidal HiFi or HiFi Plus subscription who want automatic, high-quality audio imports. The plugin handles search, download, format conversion, metadata, and lyrics — all from within the Lidarr UI.
- Search & index — Tidal albums and tracks appear as Lidarr search results via the indexer. Queries are sanitized by Common's
SearchQuerySanitizer(special-character folding + combined → artist-only → album-only fallback tiers) and run through Common'sSearchPlanExecutor(stop-after-first-tier-with-results) via theTidalSearchPlanrequest generator. - Chunked DASH downloads — Tidal's streaming manifest is parsed into chunks, downloaded in parallel, and assembled into M4A or FLAC.
- Quality tiers — Low (AAC 96 kbps), High (AAC 320 kbps), Lossless (FLAC 16-bit/44.1 kHz), and Hi-Res (FLAC up to 24-bit/192 kHz).
- FLAC extraction — optionally extracts FLAC from M4A containers (
ExtractFlac, on by default). - Synced lyrics — best-effort
.lrcfetch via LRCLIB (SaveSyncedLyrics/UseLRCLIB). - ISRC tag writing — writes ISRC tags on downloaded tracks to anchor Lidarr import matching when Tidal returns them.
- Favorites import list — mirror your Tidal library (favorite albums and/or artists) into Lidarr as an import list. Reuses the indexer's OAuth session, so no separate login.
- OAuth 2.0 + PKCE — secure, token-based authentication; no stored passwords.
Tidalarr builds on the shared Lidarr.Plugin.Common library (vendored at ext/Lidarr.Plugin.Common). Foundation topics — architecture, extension points, shared helpers, and submodule versioning — are documented in Common's wiki, not duplicated here:
| Common wiki page | Why follow it |
|---|---|
| Home | Overview of the shared library and the five-plugin ecosystem |
| Architecture Overview | Base classes, DI container, and the plugin lifecycle that Tidalarr inherits |
| SDK and Extension Points | How to extend BaseStreamingIndexer, BaseStreamingDownloadClient, and other service interfaces |
| Shared Helpers Catalog | Ready-made utilities (caching, auth gates, health probes, lyrics enrichment) that Tidalarr consumes |
| Versioning and Submodule Pinning | How ext-common-sha.txt and the gitlink stay in sync (re-pin manually; no scheduled auto-bump) |
Ecosystem contract:
- Common is vendored at
ext/Lidarr.Plugin.Common; the exact pin is tracked byext-common-sha.txtand must be committed with the submodule gitlink. - Gitea is the primary CI surface (
.gitea/workflows/ci.yml):CI / secret-scanruns Gitleaks with checksum verification,CI / lintruns Common's shared plugin lint runner, andCI / verifyrunsscripts/verify-local.ps1, which delegates toext/Lidarr.Plugin.Common/scripts/local-ci.ps1. The repo also carries.github/workflows/ci.ymlas a guarded GitHub mirror; Gitea remains authoritative for merges. - Tidal album search uses Common's
SearchQuerySanitizerandSearchPlanExecutorthrough the thinTidalSearchPlan/TidalAlbumSearchseam.
- Lidarr v3.1.2.4913 or higher on the plugins/nightly branch (
.NET 8image, e.g.pr-plugins-3.1.2.4913). The declared minimum is checked against the package's compiled host references. - A Tidal subscription (HiFi or HiFi Plus for lossless/hi-res quality).
- Settings → Plugins → paste
https://github.com/RicherTunes/Tidalarr→ Install → restart Lidarr. - Add Tidalarr under Settings → Indexers and Settings → Download Clients.
- Complete the Tidal OAuth 2.0 PKCE sign-in from the plugin settings.
To build from source, see the Getting Started section below.
Settings are available in the Lidarr UI under the plugin's Settings panel. Advanced items are hidden by default — click Show Advanced to reveal them.
| Setting | Default | Range | Description |
|---|---|---|---|
| Config Path | auto | — | Directory for Tidal OAuth tokens. Defaults to /config/Tidalarr (Docker) or ~/.config/Tidalarr (Linux). |
| OAuth Redirect URL | — | — | Paste the redirect URL from your browser after OAuth sign-in. Overwrite if stale. |
| Market (adv) | US |
US UK DE FR CA AU JP |
Tidal API market code. |
| Early Release Limit (adv) | 14 | 0–365 days | Skip pre-release downloads beyond this many days before release. 0 = include all. |
| Enable Cache (adv) | on | — | Cache search results to reduce API calls. |
| Cache Duration (adv) | 15 min | 0–1440 min | Cached search result lifetime. |
OAuth Authorization URL is a read-only convenience field derived from Config Path — use it to copy the auth link without digging through logs.
| Setting | Default | Range | Description |
|---|---|---|---|
| Config Path | auto | — | Must match the indexer's Config Path to reuse the same OAuth tokens. |
| Download Path | — | — | Destination folder for downloaded albums. |
| Preferred Quality | Lossless | Low / High / Lossless / HiRes | Audio quality tier. Falls back to the highest your subscription allows; HiFi Plus required for Lossless+. |
| Extract FLAC (adv) | on | — | Extract FLAC from M4A containers. |
| Chunk Delay (adv) | 0 ms | 0–60 000 ms | Delay between chunk requests. Increase if rate-limited. |
| Max Concurrent Track Downloads (adv) | 2 | 1–3 | Parallel tracks per album. |
| Max Concurrent Chunk Downloads (adv) | 2 | 1–8 | Parallel chunk requests per track. Effective parallelism is capped so that tracks × chunks ≤ 6. Disabled when Chunk Delay > 0. |
| Save Synced Lyrics (adv) | on | — | Save .lrc lyrics alongside downloaded tracks. |
| Use LRCLIB (adv) | off | — | Fall back to lrclib.net for lyrics when Tidal has none. Sends artist/track/album names. |
Add under Settings → Import Lists → Add → Tidalarr Favorites to mirror your Tidal favorites into Lidarr. Authentication is shared with the indexer — authenticate the Tidalarr indexer first, then this import list reuses the same session (no separate login).
| Setting | Default | Range | Description |
|---|---|---|---|
| Config Path | auto | — | Directory holding the Tidal OAuth tokens. Point it at the same directory the indexer uses. |
| Favorites To Import | Albums and artists | Albums and artists / Albums only / Artists only | Which slice of your Tidal library to mirror. Favorite albums become artist + album entries; favorite artists become artist entries. |
| Market (adv) | US |
2-letter ISO 3166-1 code | Tidal API market code. |
Lidarr resolves import-list entries by name (then MusicBrainz); Tidal favorites are matched by artist/album name rather than a Tidal catalog id.
Some tracks are permanently unavailable on Tidal (rights removed / catalog delisting) even though they still appear on an album's tracklist. No quality tier of such an album can ever complete, and Lidarr's blocklist does not fire for this failure mode — so without intervention the same album would be re-grabbed on every scheduled search, forever.
Tidalarr suppresses these automatically:
- When an album download fails because at least one track is permanently unavailable (an HTTP 404 from Tidal's playback-info endpoint — the only signal classified as permanent), the album is recorded in a bounded, disk-persisted suppression store with a 30-day TTL.
- Suppressed albums are withheld from automatic/RSS search results, which stops the re-grab loop.
- An interactive (user-initiated) search still offers suppressed albums, so you can recover an album immediately if it becomes available again — no need to wait out the TTL.
- Transient failures (auth, region/tier restrictions, rate limits, server errors, network) are never suppressed — classification deliberately errs on the transient side so a recoverable album is never hidden.
# Clone with submodules
git clone --recursive https://github.com/RicherTunes/Tidalarr.git
# Restore and build
dotnet restore Tidalarr.sln
dotnet build Tidalarr.sln
# Run tests
pwsh scripts/test.ps1- Core plugin (
src/Tidalarr): hostless runtime used by CLI and tests; no NzbDrone/Lidarr references. Ships in the plugin zip. - Host bridge (
src/Tidalarr.HostBridge): host-only wrappers with NzbDrone annotations and pretty enum labels; translates host UI models to core settings viaIHostSettingsMapper. Not shipped in the plugin zip. - See
docs/hostbridge-integration.mdfor wiring details. - Framework rationale:
docs/TFM_RATIONALE.md.
TidalCLI/ provides manual verification helpers and named-argument commands:
dotnet run --project TidalCLI -- search "Miles Davis Kind of Blue"
dotnet run --project TidalCLI -- download-album AlbumId=<id> OutputDir=<dir> Quality=HiRessrc/Tidalarr/
├── Application/ # Application-level services
├── Core/ # Constants, exceptions, DTOs
├── Diagnostics/ # Diagnostic helpers
├── Domain/ # API clients, streaming, manifest parsing
├── Infrastructure/ # Caching, resilience, storage
├── Integration/ # Lidarr integration (indexer, download client, DI module)
└── Properties/ # Assembly metadata
| Page | Description |
|---|---|
| Home | Plugin overview, navigation, and performance tuning |
| Authentication | OAuth 2.0 + PKCE sign-in (UI & CLI), token refresh, region/market |
| Quality & Formats | Quality tiers, chunked DASH/BTS assembly, FLAC extraction, ISRC tags, lyrics |
| Troubleshooting | Typed errors mapped to cause + fix |
| Document | Description |
|---|---|
CHANGELOG.md |
Release history (Keep a Changelog format) |
CLAUDE.md |
Full development guide for contributors and automation |
docs/hostbridge-integration.md |
Host bridge wiring guide |
docs/TFM_RATIONALE.md |
Why the core plugin and CLI target net8.0 |
docs/packaging-closure.md |
Plugin packaging validation |
docs/ci-gates-verification.md |
CI gate details |
docs/SETTINGS-MIGRATION.md |
Settings migration notes |
docs/operations/deployment-smoke-test.md |
Deployment and smoke-test playbook |
docs/operations/multi-plugin-alignment.md |
Multi-plugin coexistence checklist |
AGENTS.md |
Repository guidelines for coding, testing, and reviews |
For the full docs index, see docs/README.md.
Tidalarr is an independent, open-source project by RicherTunes for educational and research purposes — to study plugin architecture, streaming protocols, and the Lidarr ecosystem.
- Not affiliated with, authorized, or endorsed by TIDAL. "TIDAL" and related marks are trademarks of their respective owners; used here descriptively only.
- Intended for personal use with your own valid TIDAL subscription. You are solely responsible for complying with TIDAL's Terms of Service and all applicable laws.
- Provided "as is", without warranty of any kind (see LICENSE). Report security issues via SECURITY.md.
Open a GitHub issue with detailed logs and reproduction steps.