Best practices

These habits get you better matches from the API and a smoother experience for your users.

Always include duration

The duration parameter makes a big difference to matching. It helps tell apart:

  • Radio edits vs album versions
  • Live vs studio recordings
  • Different songs with similar names
# Good - includes duration
/getLyrics?s=Bohemian%20Rhapsody&a=Queen&al=A%20Night%20at%20the%20Opera&d=354

# Less accurate - missing duration
/getLyrics?s=Bohemian%20Rhapsody&a=Queen&al=A%20Night%20at%20the%20Opera

Always include it, together with the album. The cache key includes both, so a request without them often misses the cached entry and, without an API key, returns 401.

Always include the album name

Including the album name helps the API find the correct version of a song, especially when:

  • The song appears on multiple albums
  • There are remastered or deluxe editions
  • The artist has re-recorded songs
# Recommended - includes album
/getLyrics?s=Yesterday&a=The%20Beatles&al=Help!&d=125

# Less specific - may return wrong version
/getLyrics?s=Yesterday&a=The%20Beatles&d=125

The API accepts a request without an album, but the cache key includes it, so a request without it often misses the cached entry and, without an API key, returns 401. Always send it.

Trim whitespace from input

The API normalizes input on the server, but trimming leading and trailing whitespace before you send can still improve cache hit rates:

// Before
song = "  E85  "

// After
song = song.trim() // "E85"

Implement client-side caching

Reduce API calls by caching responses locally:

const lyricsCache = new Map();

async function getLyrics(song, artist, album, duration) {
  const key = `${song.toLowerCase()}|${artist.toLowerCase()}|${album.toLowerCase()}|${duration}`;

  if (lyricsCache.has(key)) {
    return lyricsCache.get(key);
  }

  const result = await fetchFromAPI(song, artist, album, duration);
  lyricsCache.set(key, result);

  return result;
}

To keep it across sessions, persist the cache to localStorage or IndexedDB.

Handle negative cache hits

When you receive X-Cache-Status: NEGATIVE_HIT, the API previously searched for this song and found no lyrics. Don't retry immediately.

  • Store negative results locally to avoid repeat requests
  • Show a "lyrics not available" message to users
  • If you know lyrics should exist, use /revalidate (requires API key)

Respect rate limits

For production applications:

  • Play uncached songs through the Better Lyrics extension first to populate the cache
  • Queue requests to avoid bursts
  • Add delays between batch requests
  • Back off when you get a 429

Pre-fetch upcoming songs

If you know which songs play next, fetch their lyrics early:

  • Fetch lyrics when a playlist loads, not when each song starts
  • Limit concurrent requests to avoid rate limiting
  • Prioritize songs near the current playback position
// Pre-fetch next 3 songs in playlist
async function prefetchPlaylist(playlist, currentIndex) {
  const toFetch = playlist.slice(currentIndex, currentIndex + 3);

  for (const track of toFetch) {
    // Stagger requests to avoid bursts
    await fetchLyrics(track.song, track.artist, track.album, track.duration);
    await sleep(200);
  }
}

Parse TTML efficiently

TTML parsing can be expensive. A few ways to keep it cheap:

  • Parse once and cache the structured result
  • Use a Web Worker for parsing if it blocks the main thread
  • Pre-compute the next few lines during playback
  • Use @braccato/parsers (built from the Better Lyrics parsers) instead of writing your own

Handle missing timing

Timing data can be incomplete in some documents:

  • Check that begin and end attributes exist
  • Validate that times are parseable
  • Fall back to line-level display if syllable timing is missing

Test with edge cases

Test your integration with:

  • Songs with special characters in names
  • Very long songs (10+ minutes)
  • RTL languages (Arabic, Hebrew)
  • Songs with no lyrics available
  • Songs with instrumental sections

Monitor your usage

Track these to see how your integration behaves:

  • Cache hit rate (from X-Cache-Status header)
  • Error rate by status code
  • Response times
  • Rate limit encounters

Attribute Better Lyrics

If your project uses this API, consider adding a link to Better Lyrics in your app or README. It helps other people find the project and keeps development going.