yandex-music-api and the shape of an unofficial client
Неофициальная Python библиотека для работы с API сервиса Яндекс.Музыка
At a glance
- What is it?
- yandex-music is a Python library for the Yandex Music API, an interface that is undocumented and was reverse engineered by the library's author. It ships a synchronous client, an asyncio client, a player synchronisation protocol called Ynison, radio sessions and an OpenAPI reference, and it leaves token storage entirely to the calling code.
- Who is it for?
- Adopt yandex-music if you are building a personal tool, a bot or a media application against Yandex Music and would rather not reverse engineer the API yourself, since the library carries the whole schema and the wrapper objects.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A client for an API nobody documented
yandex-music provides a Python interface to the Yandex Music API, and the README is precise about what that means. The API is undocumented and was made for the company's own use, and the library's documentation was written from scratch based on logical analysis during the reverse engineering of the API. The project states in bold that it is an unofficial library, and it opens with a line from the author saying they are doing what the Yandex company did not do for certain reasons.
What that means for an adopter is that the library is the accumulated knowledge of one person studying a service from the outside, and it is a moving target in both directions. The API can change without notice, and the library can change with it, and there is no vendor contract behind either.
The scope, on the other hand, is broad. Beyond the plain HTTP API the library supports Ynison, the protocol that synchronises a player between devices, covering the current track, the queue, the list of devices and remote control of playback. There are also radio sessions, including the personalised My Wave, waves by topic, and generative stations with listening feedback. The whole API surface the library covers is described in OpenAPI format, with an interactive reference at ym.marshal.dev/api/ that gives parameters, request bodies, response schemas and examples.
The audience is developers building personal tools, bots, players and media applications against the service, and the library is careful to say that it supports both synchronous code and asynchronous code with asyncio.
Device flow authentication, and who stores the token
For most accounts the token can be obtained from the library itself through the OAuth device flow. The pattern is short, and the callback is where the user completes the login:
from yandex_music import Client
client = Client()
token = client.device_auth(on_code=on_code)
client.init()The device_auth method is blocking, which means it waits until you confirm the login on the Yandex page, and it returns an OAuthToken object with access_token, refresh_token, expires_in and token_type fields. The README then states the part that trips people up, in bold: storing the token is the responsibility of the calling code. The library does not save it to disk and does not refresh it when it expires, and the reason for that is obvious once stated, since a library that silently persisted your account token would be a different kind of project.
The practical consequence is that your application has to hold the token somewhere, an environment variable, a file or a database, as the README's own comment suggests, so that it does not have to re-authorise on every run. And it has to handle expiry, because the library will not.
If the device flow does not work for your account, the documentation points to alternative ways of getting a token. That is the one detail in the whole authentication story that a team should test before building anything, because it is the step that can block a project outright, and the fallback paths are documented rather than obvious.
Two clients, one source, and generated aliases
The library offers a synchronous client and an asynchronous one, and the way they relate is visible in the repository rather than only in the API.
The synchronous client is created with Client(), and the asynchronous one with ClientAsync() followed by an awaited init(). Either way, init() has to be called, because it fetches the information that later requests reuse, and the README shows both the two step and the chained form of the call. The synchronous and asynchronous surfaces are kept in step by generated code: the repository has generate_sync_version.py and generate_camel_case_aliases.py, and the Makefile has targets that run them, with a gen target that runs both and an all target that regenerates, then runs ruff check with --fix and ruff format.
The type checker is pyrefly, and the test runner is pytest, both invoked through uv run so the versions come from the lock file. The Makefile is small and readable, which is a good sign for a project whose API surface is generated.
What the generation actually buys is consistency. Writing a synchronous client and an asynchronous client by hand means every new endpoint is written twice and the two drift. Here one client version is generated from the other, and camel case aliases are generated too, which is why the import style is camelCase in the README even though the Python internals are snake case.
The library is also typed, which the package metadata declares, and it supports both CPython and PyPy with Python versions from 3.8 through 3.14, and it is marked as production and stable in its classifiers.
Extras as a dependency budget
The installation story is the clearest sign of how the library is designed. The base install is one command:
pip install -U yandex-musicEverything else is an extra, and the extras are grouped by capability rather than by convenience. The async extra brings aiohttp and aiofiles for the asynchronous client. The ynison extra brings websockets and betterproto for the player synchronisation protocol. The crypto extra brings cryptography, and it is needed to decrypt tracks delivered with the encraw method, for example lossless files obtained through tracks_file_info. The JSON backends are extras too, with orjson, pydantic-core and ujson available separately, and the README notes that the fastest installed library is used to parse JSON, or you can select one explicitly or plug in your own.
The extras can be combined, and the README shows the form for the two most likely to be wanted together:
pip install -U "yandex-music[async,ynison]"That design has a real advantage for a library that talks to a service with a large surface. A script that only reads metadata does not need a websocket stack or a cryptography library, and a user who installs the base package does not inherit them.
Installing from source follows the same pattern, with a clone and then pip install for the synchronous client, or pip install ".[async]", ".[ynison]" or ".[crypto]" for the extras. The package itself depends only on requests with the socks extra and typing-extensions, which is a small base for something this size.
Ynison, radio sessions and the parts that are not plain HTTP
Two features take this library beyond a wrapper around a REST interface, and both are the kind of thing that is normally hidden inside a vendor's own client.
Ynison is the player synchronisation protocol. The README lists what it covers: the current track, the queue, the list of devices, and remote control of playback. That is a websocket protocol with protobuf style messages, given the betterproto dependency, and it is what lets a second device see and control what the first one is playing. For a library aimed at building clients and scripts, that is a capability you would otherwise have to reverse engineer separately, and it is the part most likely to break silently when the service changes.
The radio sessions are the second feature, and they include the personalised My Wave, waves by topic, and generative stations with feedback on what was listened to. The feedback loop is what makes a generative station interesting, and exposing it through the library means a script can build its own listening behaviour.
Both features are documented on the project's own site, and the OpenAPI reference covers the HTTP surface. The distinction matters for an adopter, because the reference is a description of the API as the library understands it, written by the same person who reverse engineered it, and it will reflect the library's view rather than an official contract.
What you get without a token
The README is clear that working without authorisation is limited, and it gives a concrete example: for downloads, only the first 30 seconds of the audio file are available. To understand all the restrictions, it suggests visiting the Yandex Music site in incognito mode and using the service there, which is a neat trick for seeing what an unauthenticated session is actually allowed to do.
Personal data needs authorisation, and that is done with an account token, either passed to the constructor or obtained through the device flow.
The API shape itself is small to learn, because the methods return wrapper objects. The example in the README fetches the first track from the My Likes playlist and downloads it:
client = Client('token').init()
client.users_likes_tracks()[0].fetch_track().download('example.mp3')The chain is the API's design in miniature. users_likes_tracks() returns a TracksList of TrackShort objects, which carry the essential information about a track and no detail, so fetch_track() is needed for the full version, and download() writes the file. The same pattern applies to fetching tracks by identifier, where an id is a track number and an album number joined by a colon, for example the pair given in the README.
For a team, the practical point is that the library is not just a thin HTTP client. The wrapper objects are the part that saves you from writing the same fetch_by_id dance for every entity type, and the class hierarchy is what the documentation site is organised around.
LGPL-3.0, a 3.2.2 release, and the day the code last moved
The licence is LGPL-3.0-only, declared in the package metadata with the licence text in the LICENSE file, and the project ships a SECURITY.md, a CODE_OF_CONDUCT.md and a CONTRIBUTING.md alongside a CHANGES.md.
The choice of LGPL rather than a permissive licence is worth a note. This is a library that other people's applications link against, and LGPL is a reasonable position for that: a commercial application can use it, and a modification to the library itself has to be shared. For a project whose code is a reverse engineered interface to a service, that is a sensible default.
The maintenance record is active. The recent releases are v3.2.2 on 2026-10-10, v3.2.1 on 2026-10-07 and v3.2.0 on 2026-10-06, so a patch every few days at the time of writing, and the last push was on 2026-10-10 as well. The repository is not archived, and the version in the package metadata is dynamic, which means it comes from the tag at build time rather than from a hand edited field.
The repository layout supports the picture of an actively worked on project. There is a yandex_music/ package directory, a tests/ directory, docs/, and a long examples/ directory that includes device_auth.py, a synchronous and an asynchronous device auth example, player.py, proxy.py, search.py, wave_radio.py, a radio_example/ directory, ynison_remote.py, chart.py, like_and_dislike.py, get_album_with_tracks.py and a daily_playlist_updater.py. The examples are the fastest way to see how a given feature is meant to be used, and the presence of a proxy example and a remote control example says the library is meant to be embedded in applications rather than used from a prompt.
Editorial conclusion
Adopt yandex-music if you are building a personal tool, a bot or a media application against Yandex Music and would rather not reverse engineer the API yourself, since the library carries the whole schema and the wrapper objects. Do not adopt it as the foundation of a product that needs a support contract, because the API is undocumented and the library is explicit that it is unofficial, and treat the 30 second download limit for unauthenticated use as a design constraint rather than a bug. Verify three things first: that the device flow works for your account, since the documentation points to alternative token methods if it does not, that you store and refresh the token yourself, because the library will not do either, and which extras you need, since the async client, Ynison, the encraw decryption and the faster JSON backends are all optional. The last push was on 2026-10-10 and the newest release is v3.2.2 from the same day.
Frequently asked questions
What is the yandex-music Python library?
An unofficial Python interface to the Yandex Music API, which is undocumented and was reverse engineered by the author. It supports Python 3.8 and newer, works with both synchronous and asyncio code, and is licensed under LGPL-3.0-only.
How do I install yandex-music and its optional features?
The base install is pip install -U yandex-music, which is enough for the synchronous client. The async extra needs aiohttp and aiofiles, the ynison extra needs websockets and betterproto, the crypto extra brings cryptography for encraw tracks, and the orjson, pydantic-core and ujson extras select a faster JSON backend. Extras combine, as in pip install -U "yandex-music[async,ynison]".
How do I get a Yandex Music token with yandex-music?
For most accounts the library can obtain one itself through the OAuth device flow with client.device_auth(on_code=...), which is a blocking call that returns an OAuthToken with access_token, refresh_token, expires_in and token_type. The library does not store the token or refresh it, so the calling code has to do both, and the documentation lists alternatives if the device flow does not work for your account.
What can I do with yandex-music without authenticating?
Access is limited, and the README gives the example that downloads are restricted to the first 30 seconds of the audio file. It suggests visiting the Yandex Music site in incognito mode to see the full set of restrictions that apply to an unauthenticated session.
What is Ynison in the yandex-music library?
Ynison is the protocol that synchronises a player between devices, covering the current track, the queue, the list of devices and remote control of playback. It is supported alongside the HTTP API and needs the websockets and betterproto dependencies from the ynison extra.
How current is the yandex-music library?
The newest release is v3.2.2 from 2026-10-10, preceded by v3.2.1 on 2026-10-07 and v3.2.0 on 2026-10-06, and the last push was on 2026-10-10. The whole API surface it covers is documented in OpenAPI format with an interactive reference at ym.marshal.dev/api/.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/marshalx-yandex-music-api)Was this useful?