Skip to content

Morse Code API

Four read-only endpoints over HTTPS. No account, no key, no sign-up form - just a URL that returns JSON.

No key, but not unlimited. Requests are counted per address and per endpoint. Answers carry a Cache-Control header - honour it and you will never come near the limit, because the same question always has the same answer.

Encode

Text to Morse. Words are separated by a slash.

GET https://www.morse-code.info/api/encode?text=HELLO
{
  "ok": true,
  "text": "HELLO",
  "morse": ".... . .-.. .-.. ---",
  "unbekannt": []
}

unbekannt lists any characters that have no Morse code. They are left out of the result, but you are told about them - an emoji or a Chinese character silently disappearing would turn a wrong input into an apparently correct answer.

Decode

Morse back to text. Accepts a slash or three spaces as the word separator.

GET /api/decode?morse=....%20.%20.-..%20.-..%20---
{
  "ok": true,
  "morse": ".... . .-.. .-.. ---",
  "text": "HELLO",
  "unbekannt": []
}

A sequence with no meaning becomes a question mark in text and is also listed in unbekannt. That way the position is preserved and you still know what was wrong. Anything other than dot, dash, slash and whitespace is rejected with 400 rather than interpreted generously.

Timing

How long a text takes, and what the individual elements last. Speed follows PARIS: 50 units per reference word, one unit is 1.2/WPM seconds.

GET /api/timing?text=PARIS&wpm=20
{
  "dit_ms": 60,
  "dah_ms": 180,
  "pause_zeichen_ms": 180,
  "pause_wort_ms": 420,
  "dauer_s": 2.58,
  "einheiten": { "punkte": 10, "striche": 4, "zeichen": 5, "woerter": 1 }
}

Add &effektiv= for Farnsworth timing: characters stay at full speed, the gaps between them get longer. effektiv is capped at wpm - Farnsworth stretches pauses, it never shortens characters.

dauer_s measures from the first sound to the last. It does not include a trailing word gap, so PARIS at 20 WPM comes out as 43 units and not 50.

Alphabet

A full code table. Six sets are available: international (the default), american, wabun (Japanese), thai, hangul (Korean) and russisch (Cyrillic).

GET /api/alphabet?set=international

The answer separates three things: zeichen holds the character groups, zeit the timing ratios where the set defines its own, and hinweise carries the source and any notes. Every table on this site is parsed from a cited source, and that citation travels with the data.

Limits, CORS and errors

  • Rate: 120 requests per minute per address for encode, decode and timing; 30 for alphabet, because one answer is several kilobytes and changes almost never. Over the limit you get 429 and a Retry-After header.
  • CORS: open. Access-Control-Allow-Origin: *, so you can call these directly from a browser. They hold public reference data and no user data, so there is nothing a foreign page could obtain in a visitor's name.
  • Methods: GET and OPTIONS. A POST returns 405 rather than being quietly accepted.
  • Errors are JSON too, never an HTML error page: {"ok": false, "fehler": "text-fehlt"}.
  • Length: 1000 characters per request, 200 for timing.

If you need this offline or at higher volume, the JavaScript library does the same work in the browser with no requests at all - and it is the same code that runs here.

Frequently asked questions

  • Do I need an API key?

    No. There is no registration and no key. The rate limit works per address, which is enough for a service that only calculates and stores nothing.

  • May I use this in a commercial product?

    Yes, within the rate limit and without implying that this site endorses your product. If your volume is higher than the limit, use the JavaScript library instead - it runs on your side and has no limit at all.

  • Why are some field names German?

    Because the code is written in German throughout, and renaming fields only at the boundary would create two vocabularies for the same thing. unbekannt is unknown, zeichen characters, einheiten units, fehler error.

  • Is there a decode endpoint for audio?

    Not over the API. Audio decoding runs in the browser, in a worker, on the live signal - sending sound files to a server would be slower, worse and would mean handling recordings that are none of our business.