Issue Nº 03 — Aug 14, 2026
Frankfurter: exchange rates from 84 central banks, no key required
Issue three covers a currency-conversion API that blends official rates instead of leaning on one source. Every number below came from calling the live host this week, including its move off the old frankfurter.app domain.
What it covers
Frankfurter blends daily rates from 84 central banks and official sources rather than just the European Central Bank, across 201 currencies with history reaching back to 1948. Its /rates endpoint returns the newest published rates with no parameters at all; adding a date narrows it to that day's snapshot, and a from/to range turns the same call into a time series. A providers parameter goes further still and pins the answer to one named source instead of Frankfurter's own blend. We called it with providers=ECB and got back a rate sourced from just the European Central Bank.
We hit both hero endpoints on file for this entry with a browser-style Origin header this week: GET /rates and GET /rate/{base}/{quote}. Both came back over HTTPS with access-control-allow-origin: *, matching the CORS flag already recorded, and /rate/EUR/USD returned a live rate rather than a stale cached one.
No key, no quota — with self-hosting as the release valve
Every call above worked without an API key or login. The docs are direct about limits: there are no monthly or daily caps, only rate limiting aimed at abuse rather than ordinary traffic. Their own advice for high-volume use is to cache responses, self-host, or query the underlying datasets directly rather than lean harder on the shared public instance.
They back that advice with a real option: an official Docker image is published to Docker Hub as lineofflight/frankfurter, built from the same open-source code that runs the public API. Outgrowing the shared host doesn't mean switching providers, just running the same thing yourself.
JSON by default, CSV and streaming NDJSON on request
The default response is JSON, but the same endpoint switches format based on the Accept header: text/csv returns comma-separated rows, and application/x-ndjson streams one JSON object per line instead of one large array. We requested both directly. The CSV came back as date,base,quote,rate rows, and the NDJSON request for a two-week USD/EUR range streamed thirteen single-line records rather than a buffered blob.
One thing it deliberately doesn't have: a GraphQL layer. The FAQ says plainly that the REST surface is simple enough already that GraphQL would add complexity without much benefit, and would also complicate the CDN caching the public host relies on.
Why it's worth a look
For a budgeting app, a weekend script, or a Discord bot that just needs a currency rate without signup friction, Frankfurter clears the usual hurdles in one pass: no key, a blended rate that isn't hostage to a single central bank's uptime, and a CSV or NDJSON export when a spreadsheet or a streaming pipeline fits better than raw JSON. It also just moved its canonical site from frankfurter.app to frankfurter.dev; the old domain still resolves but now redirects rather than serving its own copy of the docs.
It recently picked up an MCP server too, published at frankfurter.dev/mcp, so an agent can call it as a tool instead of going through hand-rolled HTTP requests.
Frankfurter, by the numbers
No fixed quota — abuse-prevention rate limiting only
- GET/rates
- GET/rate/{base}/{quote}