Google Sheets
Google Sheets has GOOGLEFINANCE for exchange rates, and for a quick conversion it's fine. The catch is the source: an unnamed market blend you can't inspect or choose. Frankfurter blends central bank rates you can inspect, and when the source has to be exact you can pin one authority: the ECB reference rate for EU VAT, Poland's NBP, or Brazil's PTAX. A pinned provider's history stays as published. The formulas below go wherever you'd put GOOGLEFINANCE.
Quick Start
No setup and no API key. Drop a live rate into a cell with IMPORTDATA and the CSV endpoint:
=IMPORTDATA("https://api.frankfurter.dev/v2/rates.csv?base=usd"es=eur") Sheets fills in a small date,base,quote,rate table. The date column arrives as a serial number. Select it and pick Format, Number, Date to read it back. Ask for several quotes at once by separating them with commas:
=IMPORTDATA("https://api.frankfurter.dev/v2/rates.csv?base=usd"es=eur,gbp,jpy")Convert an Amount
IMPORTDATA returns the rate, not a converted total. Multiply your amount by the imported rate cell, or use the custom function below for a single clean call.
Custom Function
For a reusable =FRANKFURTER() function, add a short Apps Script. In your sheet, open Extensions, Apps Script, paste this, and save:
/**
* Converts an amount between currencies, at today's rate or on a date.
* @customfunction
*/
function FRANKFURTER(amount, from, to, date) {
let url = `https://api.frankfurter.dev/v2/rate/${from}/${to}`;
if (date) {
const tz = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
url += `?date=${Utilities.formatDate(date, tz, "yyyy-MM-dd")}`;
}
const data = JSON.parse(UrlFetchApp.fetch(url).getContentText());
return amount * data.rate;
}Then call it from any cell:
=FRANKFURTER(100, "usd", "eur")Pass a date for a historical rate:
=FRANKFURTER(100, "usd", "eur", DATE(2020, 1, 2))Pin an Official Provider
By default you get the blend across every provider. Add providers to pin a single authority. This matters for tax and accounting: many countries require their own central bank's published rate when converting foreign-currency amounts.
=IMPORTDATA("https://api.frankfurter.dev/v2/rates.csv?base=usd"es=eur&providers=ecb")ECB- European Central Bank reference rate, the standard for EU VAT and customs.
NBP- Narodowy Bank Polski. Polish VAT and CIT convert at the NBP rate.
CNB- Czech National Bank fixing, used for Czech accounting and tax.
BCB- Banco Central do Brasil PTAX, the reference for Brazilian contracts and tax.
BANXICO- Banco de México FIX rate for settling US dollar obligations.
Browse all providers. A pinned provider follows its own publishing schedule, so its latest rate can trail the blended latest by a day.
Historical Series
Use from for a date range and group=month to collapse it to one row per month, ready to chart. Blended history can shift slightly as new data comes in, so pin a provider when figures must stay fixed.
=IMPORTDATA("https://api.frankfurter.dev/v2/rates.csv?from=1949-12-01&base=usd"es=gbp&providers=bbk&group=month") That pulls the US dollar against the pound back to 1949 from the Deutsche Bundesbank archive. You can watch the $2.80 cable peg hold flat for years, then break in 1967. Deep history runs through the Bundesbank's Frankfurt fixings: the dollar against the mark from 1948, most other dollar crosses from 1949 to 1970. The European Central Bank takes over from 1999, so a continuous modern series uses the default blend or providers=ecb.