Questions or problems? Post in GitHub Discussions.

You don't need an SDK. fetch ships with every browser, Node, Deno, Bun, and edge runtime. CORS is open and there's no key to leak, so you can call the API straight from client code.

Quick Start

Fetch a rate and convert:

const res = await fetch("https://api.frankfurter.dev/v2/rate/USD/EUR");
const data = await res.json();
const total = 100 * data.rate;

The response is one flat object: {"date": "2026-07-17", "base": "USD", "quote": "EUR", "rate": 0.8739}. fetch resolves on HTTP errors, so check res.ok; an invalid currency code returns a 422 with a JSON message.

Format with Intl

Don't place currency symbols by hand. Intl.NumberFormat knows the symbol, its position, and the decimal places for every currency, in every locale:

const res = await fetch("https://api.frankfurter.dev/v2/rate/USD/EUR");
const { rate } = await res.json();

const eur = new Intl.NumberFormat("en", {
  style: "currency",
  currency: "EUR",
});
eur.format(100 * rate); // "€87.39"

Symbols and Decimal Places

No need to vendor a metadata table for subunits or symbols. Ask the formatter:

const yen = new Intl.NumberFormat("en", {
  style: "currency",
  currency: "JPY",
});

yen.resolvedOptions().maximumFractionDigits; // 0, the yen has no subunits
yen.formatToParts(1).find((part) => part.type === "currency").value; // "¥"

Browse all currencies Frankfurter serves, with their codes and symbols.

Several Quotes at Once

/v2/rates returns a flat array, one row per quote. Reshape it into a lookup with Object.fromEntries. Omit quotes to get every currency.

const api = "https://api.frankfurter.dev";
const res = await fetch(`${api}/v2/rates?base=USD&quotes=EUR,GBP,JPY`);
const rows = await res.json();

const rates = Object.fromEntries(rows.map((row) => [row.quote, row.rate]));
// { EUR: 0.8739, GBP: 0.74388, JPY: 162.33 }

Pin an Official Provider

By default you get the blend across every provider. Add providers to pin one named authority, which matters when a jurisdiction requires its central bank's published rate, like the ECB reference rate for EU VAT.

const api = "https://api.frankfurter.dev";
const res = await fetch(`${api}/v2/rate/USD/EUR?providers=ECB`);

Browse all providers. A pinned provider follows its own publishing schedule, so its latest rate can trail the blended latest by a day.

Try It Live

Compose queries and see responses without leaving the browser in the playground.