GET /getLyrics

GET /getLyrics

Try it in the playground

Fetch synced lyrics for a song, with syllable-level timing in TTML format.

Parameters

Name Type Required Description
s, song, songName string Always send Song name.
a, artist, artistName string Always send Artist name.
al, album, albumName string Always send Album name. Improves matching.
d, duration string of digits Always send Track duration in whole seconds. Improves matching.
videoId, v string No Video ID. Links the video to the song so downstream caches can be revalidated.

The API rejects a request (422) only when both song and artist are missing. Send all four anyway: the cache key includes album and duration, so a request without them often misses the cached entry and, without an API key, returns 401.

If you send more than one alias of a parameter (for example s and song), the values are joined together. Send only one alias of each.

Headers

Name Required Description
X-API-Key Conditional Needed for cache misses when the server enforces API keys. A valid key also skips rate limiting.

Example request

curl "https://api.betterlyrics.org/getLyrics?s=E85&a=Don%20Toliver&al=OCTANE&d=154"

Success response

Status: 200 OK, Content-Type: application/json

{
  "ttml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tt xmlns=\"http://www.w3.org/ns/ttml\">\n  <body>\n    <div>\n      <p begin=\"00:00:18.234\" end=\"00:00:21.891\">\n        <span begin=\"00:00:18.234\" end=\"00:00:18.567\">The </span>\n        ...\n      </p>\n    </div>\n  </body>\n</tt>",
  "score": 0.97
}

Response fields

Field Type Always present Description
ttml string Yes TTML document with syllable or line timing.
score number No Match confidence. Present only on fresh fetches.

Response headers

Header Description
X-Cache-Status HIT cached lyrics. MISS fetched from upstream (or nothing found). STALE upstream failed and an older entry was served. NEGATIVE_HIT a cached "no lyrics" result.
X-RateLimit-Type normal full service. cached normal tier exhausted, only cached lyrics are served. exceeded both tiers exhausted. bypass valid API key.
X-RateLimit-Limit Burst size of the current rate limit tier. Absent with a valid API key.
X-RateLimit-Remaining Requests left in the current tier. Absent with a valid API key.
X-RateLimit-Bypass true when a valid API key skipped rate limiting.
X-Auth-Mode Set only when the server enforces API keys on this path. authenticated valid key, invalid wrong key, cache no key (cache hits only).
Retry-After Seconds to wait before retrying.

/getLyrics does not send X-Provider. See Provider-specific endpoints for the endpoints that do.

Error responses

All error responses are JSON, except 422 and the 429 sent when both rate limit tiers are exhausted, which are plain text.

Missing parameters (422)

Sent when neither song nor artist is given. Content-Type: text/plain:

Song name or artist name not provided

API key required (401)

The query is not cached, the server enforces API keys, and the request has no key:

{
  "error": "API key required",
  "message": "Uncached queries require a valid API key via X-API-Key header"
}

With a wrong key:

{
  "error": "Invalid API key",
  "message": "The provided API key is not valid"
}

Not found (404)

{
  "error": "Lyrics not available for this track"
}

The error text depends on why no lyrics were found. This result is cached, and later requests for the same query get X-Cache-Status: NEGATIVE_HIT.

Rate limited (429)

Both rate limit tiers are exhausted. Content-Type: text/plain, Retry-After: 1, X-RateLimit-Type: exceeded:

Too Many Requests

The normal tier is exhausted and the query is not cached, so the cached tier cannot serve it. JSON, Retry-After: 60, X-RateLimit-Type: cached:

{
  "error": "Rate limit exceeded. This request requires cached data, but no cache is available for this query.",
  "message": "Please try again later or reduce your request rate."
}

Upstream error (500)

The upstream fetch failed and no cached fallback exists. The error text is the upstream error:

{
  "error": "<upstream error message>"
}

Cache-only mode (503)

The server is temporarily serving only cached lyrics and the query is not cached:

{
  "error": "Service running in cache-only mode. No cached lyrics available for this query."
}

Provider-specific endpoints

These endpoints select one provider. They take the same s, a, al and d parameters (but not videoId), and return the same 422 and rate limit responses.

Endpoint Format Timing API key for cache misses
/ttml/getLyrics TTML Syllable-level When the server enforces API keys
/kugou/getLyrics LRC-style text Line-level Never
/qq/getLyrics QRC Word-level Never
{
  "lyrics": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>...",
  "provider": "ttml"
}

They differ from /getLyrics in these ways:

  • The body is lyrics and provider, not ttml. There is no score.
  • Every JSON response, errors included, has an X-Provider header with the provider name. JSON error bodies also have a provider field.
  • Cache lookups use the exact cache key. There is no duration tolerance and no STALE fallback.
  • /ttml/getLyrics builds its cache keys in a different format from /getLyrics. When you send an album or a duration, the two endpoints do not share cache entries.
  • X-Auth-Mode is sent only by /ttml/getLyrics, and only when the server enforces API keys.