rspotify: a Rust wrapper for the Spotify Web API in maintenance mode
Spotify Web API SDK implemented on Rust
At a glance
- What is it?
- RSpotify is a Rust crate that wraps the Spotify Web API, covering every authorization flow and endpoint, with sync and async clients and a WebAssembly build. The project has entered maintenance mode, and the crate version in Cargo.toml runs ahead of the published releases.
- Who is it for?
- RSpotify suits a Rust team that needs typed Spotify endpoints, several authorization flows and a choice of blocking or async client without hand writing request code. It is the wrong choice for a new integration, because the project has entered maintenance mode and the newest published release, v0.14.0, dates from 2025-01-01 while the crate version in Cargo.toml is already 0.16.1.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Rust, 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 typed Rust surface over the Spotify Web API
RSpotify is a wrapper for the Spotify Web API, written in Rust and inspired by spotipy, the Python library with a similar shape. The project states that it includes support for all the authorization flows and helper functions for all endpoints, which is the two things a caller has to build before touching the API by hand.
The audience is Rust developers who want the Spotify API without writing request plumbing: a bot that manages playlists, a library analysis tool, a service that reads a user's saved tracks. The value of a wrapper here is not that the HTTP calls are hard, it is that the responses are typed, so a playlist object has fields rather than a JSON blob, and that the authorization dance, which is genuinely fiddly, is already implemented in several shapes.
The crate is published on crates.io as `rspotify`, documented on docs.rs, and the repository carries a changelog that the README points to for release history and for indications on how to upgrade from one version to another. The licence is MIT.
The repository is also a workspace, and the split is visible in the top level tree: `src/` for the main crate, `rspotify-model/` for the data types, `rspotify-macros/` for the procedural macros, `rspotify-http/` for the HTTP layer, plus `examples/`, `tests/`, `tools/` and a `doc/` directory with the trait and crate hierarchy diagrams.
The Rust edition is 2021 and the minimum supported Rust version is declared as 1.56, which is a floor low enough that a crate from a few years ago can still consume it.
The workspace splits model, macros and transport
The packaging metadata describes the crate and its three siblings in one file, and it explains the dependency direction.
name = "rspotify"
version = "0.16.1"
rust-version = "1.56"
edition = "2021"The workspace members are `rspotify-macros`, `rspotify-model` and `rspotify-http`, and each is also published as its own crate with a path dependency and a matching version, so the main crate and the parts can be versioned together. The `examples/webapp` directory is explicitly excluded from the workspace, which is what lets a browser example with its own dependency set live in the same repository without disturbing the build.
The transport crate is declared with `default-features = false`, which is the mechanism behind the client selection described below. Features such as `async-stream`, `async-trait`, `futures`, `dotenvy` and `webbrowser` are all optional, and the last two matter for the shape of a typical program: `dotenvy` loads a local `.env` file, which is why the repository has one at the top level, and `webbrowser` opens the authorization page in a browser during the interactive login flow.
The data model is separated for a reason. Serde derives and the model types are the part of an API wrapper that changes when Spotify changes its responses, and keeping them in their own crate means a consumer who only needs the types does not have to pull in the HTTP machinery.
Only one HTTP client can be compiled in at a time
RSpotify uses the `maybe_async` crate to switch between async and blocking clients, and that switch is triggered inside Cargo.toml rather than at runtime. The default is `client-reqwest`, so the ordinary build is unremarkable.
$ cargo buildThe blocking interface is `client-ureq`, which needs a TLS backend named explicitly.
$ cargo build --no-default-features --features client-ureq,ureq-rustls-tlsAnd here is the part that trips people up. Building with every feature enabled does not work.
$ cargo build --all-featuresThe reason is that the different clients have to implement the same base trait, defined in `src/http/mod.rs`. Enabling two clients at once produces duplicate definitions of that trait, so the build fails. The project puts it plainly: you can only have one side of the coin at a time, not all sides of it.
That constraint is a real design consequence rather than a packaging oversight. A single trait is what lets the rest of the crate be written once and run against either a blocking or an async transport, and the price is that the two transports cannot coexist in one binary. Anyone who reaches for `--all-features` by habit, which is a common reflex in Rust projects, will get a confusing error rather than a helpful one.
WebAssembly builds for browser side clients
RSpotify supports building for the `wasm32-unknown-unknown` target, which is what makes a browser side client possible.
$ cargo build --target wasm32-unknown-unknownThe dependency configuration reflects the split between platforms. For the wasm32 target, `getrandom` is pulled in with the `wasm_js` feature, because that is how randomness is sourced in a browser, while the non wasm32 target takes a different `getrandom` version.
The repository includes an `examples/webapp` directory for this path, and it is excluded from the workspace, which is a sensible arrangement: a web application needs a bundler, a wasm toolchain and browser specific dependencies, and folding that into the main workspace would force every contributor to install them. The README points at the WebAssembly section of the docs for the details of how the build is used.
The practical caveat is that the crate is not trying to make the browser path featureless. A browser client cannot hold a client secret, so the authorization flow available there is the one that does not need one, and the shipped example set makes that visible, with separate examples for the authorization code flow, the PKCE variant and client credentials.
The example directory shows which authorization flows matter
The `examples/` directory is the most useful part of the repository for a newcomer, and its file names map directly onto the decisions a caller has to make. There is an authorization code example and an authorization code with PKCE example, a client credentials example, an example that works from OAuth tokens directly, an example with a refresh token, one with automatic re-authentication, and one that takes a token callback function.
The pagination examples come in three forms, `pagination_async.rs`, `pagination_sync.rs` and `pagination_manual.rs`, which is a small but telling detail. The Spotify API paginates, and a wrapper that hides the cursor is convenient while a wrapper that exposes it lets you decide when to stop. The manual example exists for the case where you want to drive that yourself.
There is also an `examples/ureq/` directory for the blocking transport and a `examples/tasks.rs` for running work concurrently, and the `examples/webapp/` directory for the browser case described above.
The `CHANGELOG.md` is the other file to read, because the README says it carries the release history and indications on how to upgrade from one version to another. For an API wrapper, that matters more than it would for a library with a stable interface, since the Spotify API itself moves and the wrapper has to follow.
Maintenance mode, and a version ahead of the releases
The README opens with a one line notice that RSpotify enters maintenance mode, and it links to a discussion for detail. That is a different status from archived. The repository is not archived, the last push was on 2026-10-19, and the project still invites issues, pull requests, code review and feedback. What maintenance mode means in practice is that new development is slow, so a new Spotify API field may wait a long time before it appears in the model crate.
The release history is uneven. The most recent GitHub release is v0.14.0, published on 2025-01-01, before that came v0.12.0 on 2023-08-26 and v0.11.0 on 2021-10-14 with the note that it was a new look. Meanwhile the version in the workspace Cargo.toml is 0.16.1, and the sibling crates are published at the same version, so the crates.io version line has moved past the tagged releases. A user pinning a version has to decide which of those two they are tracking, and the CHANGELOG is the place to find out what changed between them.
The rest of the engineering setup is conventional and healthy. GitHub Actions keeps the code consistent with `cargo fmt` and continuously tested with `cargo test`, the project asks for comments to stay within 80 characters and code within 120, and the repository carries a `clippy.toml` for lint configuration. The licence is MIT, and the crate metadata classifies it under api-bindings and multimedia::audio.
Where a direct HTTP call differs from a typed wrapper
The alternative is to skip the wrapper and call the Spotify Web API with an HTTP client directly, using `reqwest` or the standard library, and to deserialize the responses into your own types. The difference in approach is what happens when the API grows a field or changes a shape. With a direct call, that change is invisible until the code that reads the field fails at runtime, and it is invisible in every project that made the call. With a typed wrapper, the change lands in one model crate and every consumer sees a compile error at the same moment.
The second difference is the authorization. The Web API supports several flows, and each has its own refresh semantics. The wrapper implements all of them, including the automatic re-authentication and refresh token paths, and the example set documents how each one is wired up. Reproducing that in an application means dealing with token expiry, refresh tokens and the browser redirect yourself.
The trade runs the other way when the wrapper is behind or ahead of what you need. A wrapper that does not yet expose an endpoint means waiting for a release, and a project in maintenance mode is a slower source of that. For a one off script that needs three endpoints and no refresh handling, the direct call is smaller and easier to throw away. For a service that reads many endpoints, the typed model and the shared authorization code are usually worth the dependency.
Editorial conclusion
RSpotify suits a Rust team that needs typed Spotify endpoints, several authorization flows and a choice of blocking or async client without hand writing request code. It is the wrong choice for a new integration, because the project has entered maintenance mode and the newest published release, v0.14.0, dates from 2025-01-01 while the crate version in Cargo.toml is already 0.16.1. Before depending on it, read the maintenance mode issue linked from the README, check the CHANGELOG for the upgrade path between versions, and confirm that the Web API endpoints you need are covered by the version you pin.
Frequently asked questions
What is the rspotify crate for Rust?
RSpotify is a wrapper for the Spotify Web API, inspired by the Python library spotipy. The project states that it supports all the authorization flows and provides helper functions for all endpoints, and the crate is published on crates.io as `rspotify` under the MIT licence.
Why does cargo build --all-features fail for rspotify?
The different HTTP clients have to implement the same base trait in src/http/mod.rs, so enabling more than one client produces duplicate definitions. The README recommends building either the default `client-reqwest` setup or, for the blocking interface, `--no-default-features --features client-ureq,ureq-rustls-tls`.
Can rspotify be built for the browser?
Yes, the crate supports the `wasm32-unknown-unknown` target with `cargo build --target wasm32-unknown-unknown`, and the getrandom dependency is configured with the wasm_js feature for that platform. The repository includes an examples/webapp directory, which is excluded from the workspace.
Is rspotify still being developed?
The README states that RSpotify enters maintenance mode and links to a discussion for detail. The repository is not archived and the last push was on 2026-10-19, and issues and pull requests are still welcome.
Which version of rspotify should I depend on?
The most recent GitHub release is v0.14.0 from 2025-01-01, while the version declared in the workspace Cargo.toml is 0.16.1 and the sibling crates are published at that version. The CHANGELOG in the repository carries the release history and indications on how to upgrade between versions.
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/ramsayleung-rspotify)Was this useful?