# tidalapi: an unofficial Python client for the TIDAL streaming service

> tidalapi is a Python library for the TIDAL music streaming service, wrapping the service's own endpoints rather than shipping a player, with a session model that handles the OAuth flow and the subscription, catalogue, playlist and playback endpoints behind a typed API. It is a community project with a history of maintainers, and it is licensed LGPL rather than permissive.

**EbbLabs/python-tidal** — Python API for TIDAL music streaming service

- Repository: https://github.com/EbbLabs/python-tidal
- Stars: 568 · Forks: 124
- Language: Python
- License: LGPL-3.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/ebblabs-python-tidal

## What a TIDAL client has to handle underneath

The reason a wrapper library like this needs more than a requests session is visible in the dependency list and the example set, and it is worth spelling out because it explains the shape of the API.

A streaming service is not a file server. The catalogue is not a static list, it is a search index with filters, facets and paging. Playback is not a download, it is a session negotiation that returns a manifest, and the manifest format matters, which is why mpegdash is a runtime dependency and not an optional one. And the account is not a password, it is an OAuth grant, and a public client needs a browser-based flow, which is why the PKCE example is a first-class example rather than a footnote.

The library's job is to make those three things callable. A session object handles the OAuth exchange and holds the credentials, the catalogue methods turn your query into the request shape the service expects and hand back typed results, and the playback helpers produce the stream description a player can consume.

The transfers example, transfer_favorites.py, points at a fourth thing that has nothing to do with audio: the service's data is portable in ways that matter to users, and favourites are one of them. Moving favourites between accounts is a task people genuinely want, and the fact that the library makes it a short script is the clearest evidence that it models the service's data rather than just its audio.

So the practical scope is a client for the service as a data source and a control surface, not a player. If you want a player you bring your own, and what you want from this library is the catalogue, the playlists, the account and the stream description.

## An unofficial client, and what that means

tidalapi is an unofficial Python API for the TIDAL music streaming service, and it requires Python 3.10 or higher.

The word unofficial is the most important word in that sentence, and it governs everything else about the project. There is no relationship with the service operator, the endpoints are not a documented public API, and they can change without notice. A library like this is a reverse engineering of a service's internal interface, maintained by volunteers, and the service is free to alter it whenever the underlying applications need it.

That does not make it a bad project. It makes it a specific kind of project, with a specific risk profile, and the honest way to evaluate it is to ask what breaks when the service changes. The answer is that the library needs a release, which is why the release history matters, and it is why a project with several maintainers over its life and an LGPL licence is arguably the most responsible shape such a client can take.

The maintainer list is a good indicator of continuity. The current maintainer is tehkillerbee, and two former maintainers are credited, tamland and morguldir. The original author in the packaging metadata is Thomas Amland, and the package name on PyPI is tidalapi even though the repository is EbbLabs/python-tidal, which is the sort of rename that a project goes through when it moves from one person's namespace into an organisation's.

The licence is LGPL-3.0-or-later, which the classifiers record as the GNU Lesser General Public License v3. That is a meaningful difference from the MIT and Apache projects that dominate this set of reviews, and it is the first thing to read if you intend to ship the library inside a product.

## The dependency set tells you what the library does

The runtime dependencies are short and they describe the shape of the library accurately.

requests at 2.32.3 or newer is the HTTP client, which is unsurprising for a wrapper around a web service. python-dateutil and isodate are the date handling libraries, and their presence tells you that the service's payloads carry timestamps in more than one format, which they do. And mpegdash at 0.4.1 is the more revealing entry, since that is the library for building and parsing MPEG-DASH manifests, which is how a streaming service describes its DASH content.

The mpegdash dependency is the one that says this is more than a catalogue scraper. A library that can produce a DASH manifest is a library that can hand a player a playable stream description rather than just a list of track identifiers, and that is what separates this from the simplest kind of API wrapper.

The development dependencies are a much longer list and they show a project with real quality practices. mypy with check_untyped_defs enabled and the packages option set to tidalapi, type stubs for the date and request libraries, pytest, pytest-mock, tox, keyring, pillow and ffmpeg-python. The formatting and linting stack is isort with the black profile, black, ruff with a narrow rule selection of E4, E7, E9 and F, and docformatter configured to be recursive and to follow black.

The narrow ruff selection is the same choice seen in other well-run Python projects,. The mypy configuration is more unusual, because check_untyped_defs with the packages option set to tidalapi means the type checker is run over the library rather than only over the places where annotations happen to exist, which is a stricter bar than most projects set for themselves.

The typing classifier is present, Typing:: Typed, so the package ships type information to consumers.

## The three examples show what people actually do with it

The examples directory holds three files, and the set is small enough to be worth reading as a description of the intended use.

There is simple.py, which is the obvious starting point and presumably shows the session setup and a basic query. There is transfer_favorites.py, which moves favourites between accounts or exports them, and that is a task that only makes sense if you already have a working session and want to work with account data. And there is pkce_example.py, which is the OAuth example.

That last one is the most informative. PKCE, proof key for code exchange, is the OAuth extension that lets a public client, an application with no client secret, obtain tokens safely. Its presence as a worked example means the library supports the PKCE flow, which is what you need for a desktop or command line application talking to the service directly, and it means the session object can complete an interactive login where the browser hands a code back to a local listener.

The readme points at an examples directory in another repository for more of these, and the documentation is published at tidalapi.netlify.app with a Netlify deploy badge in the readme. The docs site and the repository are separate, which is a common arrangement for a library with a lot of prose.

The project also uses poetry for dependency management and packaging, and the readme gives the development setup as three commands. The first installs pipx, the second uses pipx to install poetry, and the third runs poetry install with the no-root option. The pipx route is the recommended way to get a poetry that does not pollute the system Python, and the no-root option skips installing the project itself into the environment, which is what you want when you are about to run the code from the checkout.

The repository also carries a flake.nix and flake.lock, a netlify.toml for the documentation site, a tox.ini, a Makefile, a pylintrc, a HISTORY.rst that is used as the long description alongside the readme, and an .envrc for direnv users.

## The Makefile, and how the project checks itself

The Makefile is a small task runner with a help target, and the target list is a good description of the project's workflow.

The help target prints the options with their descriptions, and the options are develop, shell, install, format, lint and test. The develop target runs poetry install to set up the development virtual environment with the required dependencies, and the shell target starts a shell inside that environment.

The install target is the one to look at closely, because it contains a flag that should make you pause. It removes the dist directory, runs poetry build, and then runs pip install dist/*.whl with the break-system-packages option. The comment above the target explains what that means, and it says not to run this from within the virtual environment, since installing into the system Python while a project environment is active is exactly the situation the flag exists to force.

The format target runs isort, black and docformatter over the tidalapi and tests directories, and it has a commented-out ruff check with a fix flag, with a note that ruff should not autofix because it can break things. The lint target runs the same tools in check mode, isort and black and docformatter and ruff, without the fix flags, and it is what a pre-commit hook would call.

The test target runs pytest over the tests directory, with a help description that warns it will fail if the development environment has not already been created. That is a makefile that expects the environment to be a prerequisite rather than a step.

Taken together, the tooling describes a project that runs four formatters and a linter, has type checking switched on across the package, tests with mocking, and a tox configuration for environments. For a library wrapping somebody else's service, that is a lot of care applied to a codebase whose main risk is not its own quality but the service changing underneath it.

## Conclusion

Adopt tidalapi if you are building a tool that needs TIDAL catalogue and playlist data, for instance a metadata utility or a personal library tool, and you are prepared to deal with an unofficial client. Do not adopt it as the basis of a commercial player, because it is not affiliated with the service and the terms of use of the service itself will be the binding constraint. Before you commit, read the license, because it is LGPL rather than MIT and the obligations differ, and check the recent release history, since the published version and the repository version differ.

## FAQ

### What is tidalapi?

It is an unofficial Python API for the TIDAL music streaming service, requiring Python 3.10 or higher and published on PyPI as tidalapi. It provides a typed session model with calls for the catalogue, playlists, favourites and playback, and it is licensed LGPL-3.0-or-later.

### How do I install tidalapi?

With pip install tidalapi from PyPI. The development setup uses poetry, installed through pipx, followed by poetry install with the no-root option. The library requires Python 3.10 or higher.

### What does the tidalapi example set show?

Three examples: simple.py for the basic flow, transfer_favorites.py for moving favourites between accounts, and pkce_example.py for the OAuth PKCE flow that lets a public client authenticate without a client secret.

### What are the runtime dependencies of tidalapi?

Four: requests for HTTP, python-dateutil and isodate for the date formats the service returns, and mpegdash for MPEG-DASH manifest handling, which is what lets the library hand a player a playable stream description rather than only track identifiers.

### Is tidalapi actively maintained?

The recent releases are v0.8.11 from 2026-01-19, v0.8.10 from 2025-12-17 and v0.8.9 from 2025-12-03, and the last push was on 2026-10-13. The package metadata lists version 0.9.0, and the maintainer has changed hands over time, with tehkillerbee current and tamland and morguldir credited as former maintainers.

## Sources

- [EbbLabs/python-tidal on GitHub](https://github.com/EbbLabs/python-tidal)
- [Issues](https://github.com/EbbLabs/python-tidal/issues)
- [License: LGPL-3.0](https://github.com/EbbLabs/python-tidal/blob/main/LICENSE)
- [README](https://github.com/EbbLabs/python-tidal/blob/main/README.md)
- [Releases](https://github.com/EbbLabs/python-tidal/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ebblabs-python-tidal
