A Rust-based API server that fetches synchronized lyrics from Spotify and provides them in multiple formats. This is a complete rewrite in Rust of spotify-lyrics-api.
- Fetch time-synchronized lyrics from Spotify's internal API
- Support for multiple output formats (ID3, LRC, SRT, raw text)
- Simple HTTP endpoint for easy integration with other applications
- CORS support for web applications
- Configurable via config file or environment variables
- Automatic token management and caching
- Extract track IDs from full Spotify URLs
The authorization flow and response formats are aligned with
spotify-lyrics-api at e158b96
(main as checked on 2026-09-06). The Rust port previously hardcoded TOTP version 5;
Spotify rejecting that obsolete token request could produce HTTP 400 errors.
On token refresh, the server now fetches Spotify's server time and the latest
numeric version from upstream's
secret dictionary.
It applies upstream's secret transformation, generates the six-digit TOTP, and
sends reason, productType, totp, totpVer, and ts to the token endpoint.
The dictionary request does not receive your SP_DC cookie. Outbound HTTPS
certificate verification stays enabled, and requests have bounded timeouts.
A valid SP_DC cookie is still required. This update cannot renew an expired or
revoked cookie. Token responses are validated before being cached; an anonymous
response reports that the cookie needs replacing. Corrupt cache files are
refreshed, and completed token files are published atomically. HTTP 401 lyrics
responses trigger at most one token refresh and retry.
After updating, rebuild and restart the deployed server (for Compose:
docker compose up -d --build). Changing only the client URL does not update an
already running backend. Outbound access is needed to open.spotify.com,
spclient.wg.spotify.com, and raw.githubusercontent.com.
- Rust (latest stable version recommended)
- A valid Spotify cookie (SP_DC) from a premium account
- Clone the repository:
git clone https://github.com/GlideClient/spotify-lyrics-api-rust.git
cd spotify-lyrics-api-rust- Build the project:
cargo build --release --locked- The compiled binary will be available at
target/release/spotifylyricsapi
You can run the application using Docker in two ways:
- Build the Docker image:
docker build -t spotifylyricsapi .- Run the container:
docker run -d -p 8080:8080 -e SP_DC=your_spotify_cookie_value spotifylyricsapi- Set your SP_DC environment variable:
export SP_DC=your_spotify_cookie_value- Run with docker-compose:
docker-compose up -dThis will build the image if it doesn't exist and start the container.
Create a config.toml file in one of these locations:
- Current directory (
./config.toml) - User's config directory (
~/.config/spotifylyricsapi/config.toml) - System-wide (
/etc/spotifylyricsapi/config.toml)
# Spotify Lyrics API Configuration
# Your Spotify cookie value (required)
# This is the value of the SP_DC cookie from your Spotify web session
sp_dc = "YOUR_SP_DC_COOKIE_VALUE_HERE"
# Server port (optional, defaults to 8080 if not specified)
# port = 8080Alternatively, you can set these environment variables:
SP_DC: Your Spotify cookie valuePORT: The port to run the server on (defaults to 8080)
- Log in to Spotify Web Player
- Open your browser's developer tools (F12 or right-click > Inspect)
- Go to the Application/Storage tab
- Find Cookies > https://open.spotify.com
- Copy the value of the
sp_dccookie
./spotifylyricsapiThe server will start on port 8080 by default (or the configured port).
Fetches lyrics for a Spotify track.
Query Parameters:
trackid: The Spotify track ID (Required if URL is not provided)url: A Spotify track URL (Required if trackid is not provided)format: Output format -id3,lrc,srt, orraw(Default:id3)
Examples:
- Using track ID:
http://localhost:8080/?trackid=4cOdK2wGLETKBW3PvgPWqT - Using URL:
http://localhost:8080/?url=https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT - Using LRC format:
http://localhost:8080/?trackid=4cOdK2wGLETKBW3PvgPWqT&format=lrc
Response Format (ID3):
{
"error": false,
"syncType": "LINE_SYNCED",
"lines": [
{
"startTimeMs": "1230",
"words": "Look at the stars",
"syllables": [],
"endTimeMs": "0"
}
]
}Response Format (LRC):
{
"error": false,
"syncType": "LINE_SYNCED",
"lines": [
{
"timeTag": "00:01.23",
"words": "Look at the stars"
}
]
}Additional formats:
format=srt: JSONlinescontains entries withindex,startTime,endTime, andwords. Each entry ends when the following line starts, matching upstream.format=raw: JSONlinescontains one newline-separated string.- The default
id3format preserves Spotify's original line fields, including syllables and end times.
400 Bad Request:
{
"error": true,
"message": "url or trackid parameter is required!"
}404 Not Found:
{
"error": true,
"message": "lyrics for this track is not available on spotify!"
}429 Too Many Requests: Spotify rate limits are returned as HTTP 429, with
Retry-After forwarded when the upstream response provides it. Missing lyrics
return HTTP 404; other upstream failures return a JSON error rather than lyrics.
cargo fmt --check
cargo test --locked
cargo clippy --locked --all-targetsTests use a local mock server and synthetic credentials. They cover dynamic secret selection, known TOTP vectors, token parameters and caching, invalid cookies, refresh-on-401, error status propagation, and response formats. They do not verify live account authorization.
curl "http://localhost:8080/?trackid=4cOdK2wGLETKBW3PvgPWqT"fetch('http://localhost:8080/?trackid=4cOdK2wGLETKBW3PvgPWqT')
.then(response => response.json())
.then(data => console.log(data));This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
This project is not affiliated with, maintained, authorized, endorsed, or sponsored by Spotify. This is an independent project that uses Spotify's internal API, which may change without notice.