Importing songs#

You don't have to type charts in. chords can import:

  • a link to a chord or tab page. chords opens the page in a headless browser on the server and parses what it finds. A page that lists many songs is recognised as a playlist;
  • a paste, a chart copied from anywhere. Chords written above the lyrics in a monospaced layout are moved inline, onto the syllable they sat over;
  • a photo or screenshot of a chord sheet, read like a paste;
  • a title: a web search finds candidate pages, and you choose one.

Each import ends as an ordinary chart (see Charts) that you can check and edit before you save it.

The OpenRouter key#

The parsing is done by language models on OpenRouter, with a key you provide. Set it on the server with:

python butler.py server key --local      # prompts, writes it on this machine
python butler.py server key --clear      # removes it

The key is stored in secrets.json in the data directory and read on every request, so changing it needs no restart. An OPENROUTER_API_KEY environment variable on the server takes precedence.

Each step uses a cheap model that does that job well. An import costs well under a cent:

StepDefault modelAbout per call
find sources for a titlegoogle/gemini-2.5-flash-lite$0.006
map a playlist page to its songsgoogle/gemini-2.5-flash-lite$0.002
parse page text or a pastegoogle/gemini-3.1-flash-lite$0.006
read a photogoogle/gemini-3.1-flash-lite$0.003

Override any of them with CHORDS_MODEL_SEARCH, CHORDS_MODEL_SCAN, CHORDS_MODEL_PARSE or CHORDS_MODEL_VISION, set to any OpenRouter model.

Sites that block servers#

Some sites refuse pages to a server. The browser extension imports from your own browser instead: open the song there and send it to chords. See Apps and the extension.

Scraping a website may break its terms of service. Through the extension the request comes from your own browser and session, which is usually fine for personal use, but make sure you may import from a site before you do.

What the server will fetch#

The import fetches only http and https pages. Every connection its browser makes goes through a proxy that refuses loopback, private and link-local addresses and the server's own, including redirects and the page's own requests. In Docker the browser runs in a container of its own, with no access to chords' data.