Authentication
The Better Lyrics API uses a cache-first authentication model. Anyone can read a cached response. A fresh fetch may need an API key.
When you need an API key
| Scenario | API key required? |
|---|---|
| Cache hit (lyrics already cached) | No |
| Cache miss (fresh fetch needed) | Yes* |
Revalidation (/revalidate endpoint) | Yes |
| Rate limit bypass | Yes |
*Only on /getLyrics and /ttml/getLyrics, and only when API_KEY_REQUIRED is enabled on the server. /kugou/getLyrics and /qq/getLyrics never need a key. Keys are currently not being issued to new users.
Using your API key
Pass your API key in the X-API-Key header:
curl -H "X-API-Key: your-api-key" \
"https://api.betterlyrics.org/getLyrics?s=E85&a=Don%20Toliver&al=OCTANE&d=154"const res = await fetch("https://api.betterlyrics.org/getLyrics?s=E85&a=Don%20Toliver&al=OCTANE&d=154", {
headers: { "X-API-Key": "your-api-key" },
});
const data = await res.json();import requests
res = requests.get(
"https://api.betterlyrics.org/getLyrics?s=E85&a=Don%20Toliver&al=OCTANE&d=154",
headers={"X-API-Key": "your-api-key"},
)
data = res.json()package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, err := http.NewRequest(http.MethodGet, "https://api.betterlyrics.org/getLyrics?s=E85&a=Don%20Toliver&al=OCTANE&d=154", nil)
if err != nil {
panic(err)
}
req.Header.Set("X-API-Key", "your-api-key")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
} API key benefits
- Fetch lyrics for songs that are not in the cache yet
- Skip rate limiting entirely
- Force a refresh of cached lyrics with the
/revalidateendpoint
Response headers
The API reports authentication state in these headers:
| Header | Description |
|---|---|
X-Auth-Mode |
Current auth mode: authenticated (valid API key), invalid (invalid API key provided), or
cache (no API key, so only cached lyrics are served). Sent only on JSON responses from /getLyrics,
/ttml/getLyrics and /revalidate, and only when the server enforces API keys.
|
X-RateLimit-Bypass | Set to true on every response when rate limits are bypassed via API key |
Error responses
Missing API key (cache miss)
{
"error": "API key required",
"message": "Uncached queries require a valid API key via X-API-Key header"
} Status: 401 Unauthorized
Invalid API key
{
"error": "Invalid API key",
"message": "The provided API key is not valid"
} Status: 401 Unauthorized
Loading uncached songs
First check that your request sends all four parameters: the cache key includes album and duration, so a request without them often misses an entry that is already cached. If a song you need still isn't cached, play it once with the Better Lyrics extension installed. The extension fetches lyrics through the same upstream the API uses, so after that one playback the response is cached and any caller can get it without a key.
This only works if the song exists upstream. If the extension can't find it either, playing it again won't help.
If you have the lyrics yourself, you can upload them directly at unison.boidu.dev.
Cache-first model explained
Each request goes through these steps:
- Request comes in for lyrics
- API checks if lyrics are already cached
- If cached: return immediately (no API key needed)
- If not cached: check for valid API key
- With valid API key: fetch from source, cache, and return
- Without API key: return 401 error
So anyone can read a song that is already cached. Only fresh fetches, which cost an upstream request, need a key.