Currency Exchange Rates Scraper - ECB Reference Rates & History
Pricing
from $5.84 / 1,000 exchange rate returneds
Currency Exchange Rates Scraper - ECB Reference Rates & History
Official ECB euro foreign exchange reference rates for about 30 currencies since 1999: the latest day or any date range, against EUR or any base currency (cross rates computed via EUR and marked as computed). One row per day and currency with the ECB series key. No API key.
Pricing
from $5.84 / 1,000 exchange rate returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Get the official euro foreign exchange reference rates of the European Central Bank (ECB) as a clean table: the latest day for every currency, or the daily history of any currencies since 1999, against the euro or against any base currency (USD, GBP, JPY...). One row per day and currency. No API key, no account, no proxy.
The data comes from the ECB's own statistical API (data-api.ecb.europa.eu, dataset EXR, series D.<currency>.EUR.SP00.A). The ECB sets these rates at 14:15 CET on every TARGET business day and publishes them around 16:00 CET.
What you get
| Column | Meaning |
|---|---|
date | The ECB reference day (YYYY-MM-DD). |
baseCurrency, quoteCurrency | The pair: 1 base = rate x quote. Names in baseCurrencyName, quoteCurrencyName. |
rate | Units of the quote currency per 1 unit of the base currency. With base EUR this is the ECB value itself, unrounded. |
rateIsComputed | false when rate is the ECB's published value; true when it is a cross rate calculated from ECB values (any base other than EUR). |
inverseRate | Units of the base currency per 1 unit of the quote currency. |
inverseRateIsComputed | true when inverseRate is calculated (1 / rate, 10 significant digits) - which is every row except one kind: with a base other than EUR, the row whose quote is EUR, where inverseRate is the ECB value itself (false). |
rateText | The rate in words, for example 1 EUR = 1.1592 USD. |
calculation | For computed rates, the exact formula and the ECB numbers used, for example (JPY per EUR) / (USD per EUR) = 185.63 / 1.159. |
ecbSeriesKey, ecbQuotePerEur | The ECB series of the quote currency and its published value for that day. |
ecbBaseSeriesKey, ecbBasePerEur | The ECB series of the base currency and its published value (only when the base is not EUR). |
source | Source: ECB statistics. - the attribution the ECB asks for. |
status, note, input, checkedAt | ok for a rate row. Any other status is an explanation row (see below). input records what was asked. |
Example rows (real output):
{ "date": "2026-09-03", "baseCurrency": "USD", "quoteCurrency": "JPY", "rate": 156.0137753, "rateIsComputed": true,"inverseRate": 0.006409690414, "inverseRateIsComputed": true, "rateText": "1 USD = 156.0137753 JPY","calculation": "(JPY per EUR) / (USD per EUR) = 181.21 / 1.1615","ecbSeriesKey": "EXR.D.JPY.EUR.SP00.A", "ecbQuotePerEur": 181.21, "ecbBaseSeriesKey": "EXR.D.USD.EUR.SP00.A", "ecbBasePerEur": 1.1615 }{ "date": "2026-09-11", "baseCurrency": "EUR", "quoteCurrency": "USD", "rate": 1.1592, "rateIsComputed": false,"inverseRate": 0.8626639061, "inverseRateIsComputed": true, "rateText": "1 EUR = 1.1592 USD", "calculation": null,"ecbSeriesKey": "EXR.D.USD.EUR.SP00.A", "ecbQuotePerEur": 1.1592 }
Input
| Field | What it does |
|---|---|
currencies | Three-letter ISO 4217 codes, for example ["USD", "JPY", "GBP", "CHF"]. Leave it empty to get every currency the ECB publishes (29 on 2026-09-11; older ones such as HRK or RUB appear on the dates they were published). |
baseCurrency | Default EUR. Any other code (for example USD) returns cross rates computed from the two ECB euro rates of the same day, marked rateIsComputed: true. EUR can then be one of the currencies. |
startDate, endDate | A date range (YYYY-MM-DD, both days included). Without endDate the range runs to the latest published day. The series start on 1999-01-04. |
latestDays | Used when no dates are given: the latest N ECB reference days (default 1 = the latest published rates). 5 usually covers one working week. |
maxResults | The most rate rows per run. Leave it empty for the default: 1,000 when currencies is empty, 10,000 when you name currencies. Up to 300,000. |
How many rows (and what it costs). Rows = currencies x ECB reference days (about 255 a year). All currencies are about 30 rows per reference day, so all currencies over one year is about 7,500 rows (about $60 at $8 per 1,000 rows), and the default of 1,000 rows covers about the last 34 reference days. One currency's full history since 1999 is about 7,100 rows.
Order. With currencies empty, rows come newest date first, every currency of a day together (alphabetical within the day; with another base, EUR first). When maxResults or your spending limit stops the run, you have complete recent days and only the oldest dates are missing; an explanation row names the dates that were not returned. With named currencies, rows come currency by currency in the order you gave, oldest date first.
Examples:
{}
The latest ECB rates of all currencies against the euro (one row each, about 30 rows).
{ "currencies": ["USD", "GBP", "JPY"], "startDate": "2025-01-01", "endDate": "2025-12-31" }
Every 2025 reference day for three currencies (765 rows).
{ "baseCurrency": "USD", "currencies": ["EUR", "JPY", "GBP", "CNY"], "latestDays": 5 }
The last five reference days quoted per US dollar (20 rows).
Weekends and holidays have no rows
The ECB publishes reference rates only on TARGET business days: never on Saturdays or Sundays, and not on TARGET holidays (1 January, Good Friday, Easter Monday, 1 May, 25 and 26 December). This actor does not invent rows for those days and does not carry the previous day forward: a week gives 5 rows per currency, a range over Christmas gives fewer. If you need a value for every calendar day, fill the gaps yourself with the rule your accounting uses (most use the last available rate).
A range that contains no reference day at all (a weekend, or dates before today's publication) returns an explanation row instead of an empty dataset.
The ECB's API also lists some days with an empty value (for the US dollar 62 days between 1999 and 2012, 13 of them in 1999-2001, for example 1999-12-31 and 2000-12-25). Those are not rates: they are left out, never turned into zero, and the full history matches the ECB's own history file day for day (7,091 US dollar rows on 2026-09-11).
Cross rates are computed, and say so
The ECB publishes rates against the euro only. For any other base currency this actor divides the two ECB euro rates of the same day: USD -> JPY = (JPY per EUR) / (USD per EUR). Those rows carry rateIsComputed: true, the formula in calculation, and both ECB values in ecbQuotePerEur and ecbBasePerEur, so you can always tell an ECB figure from a derived one. Computed values have 10 significant digits; the ECB values they come from have about 5, so a cross rate is not more precise than that. A day on which the ECB has a rate for the quote currency but not for the base currency gets no row (it is counted in an explanation row, never filled with zero).
Turkish lira and Romanian leu before 2005
The ECB has no separate series for the old Turkish lira (TRL) or the old Romanian leu (ROL). Their rates are in the TRY and RON series, converted to the new units: TRY rows up to 2004-12-31 are old lira divided by 1,000,000, and RON rows up to 2005-06-30 are old lei divided by 10,000 (TRY on 1999-01-04 is 0.372274, where the ECB's history file lists 372274 old lira). Multiply by 1,000,000 or 10,000 to get the old units. Asking for TRL or ROL returns an explanation row that says this.
Explanation rows (never charged)
Every row whose status is not ok explains something and is not charged:
bad-input- a code that is not three letters, a date that does not exist, a start date after today, a start after the end, or a currency equal to the base. Nothing is sent to the ECB for it.currency-not-found- the ECB has no reference rate series for that code (it answered "no such series"). For TRL and ROL the row points to TRY and RON.no-rates-in-range- the currency exists but has no rate in your dates, and the row says why: the ECB stopped publishing it (for example RUB after 2022-03-01), its series starts later, or the range holds no reference day.incomplete/not-looked-up- the run stopped atmaxResultsor at the spending limit you set, and the row names what was not returned.failed- the ECB did not answer after several retries. Nothing is guessed; running again later usually works.refused- the ECB refused the query (HTTP 400). It is not retried, because the same query gets the same answer.
When some lookups failed, the run's status message says how many. When every lookup failed, the run ends as failed with the first problem in its status message, so a scheduled run or an integration can notice.
How accurate is it
Checked on 2026-09-12 against the ECB's other official publication of the same rates, the full-history file eurofxref-hist.zip: named currencies over six weeks, a range across the 2025-26 new year holidays, September-October 2008, cross rates on a USD base, HRK and RUB in 2022, TRY and RON across their 2005 change of unit, all currencies over three months, the default input and the full US dollar history since 1999 matched in number of days, dates and values: 0 differences. The check script is kept with the source so it can be re-run.
Currencies
Currently published (2026-09-11): AUD, BRL, CAD, CHF, CNY, CZK, DKK, GBP, HKD, HUF, IDR, ILS, INR, ISK, JPY, KRW, MXN, MYR, NOK, NZD, PHP, PLN, RON, SEK, SGD, THB, TRY, USD, ZAR.
Discontinued, history available up to the date shown: RUB (2022-03-01), HRK (2022-12-30), BGN (2025-12-31), ARS, DZD, MAD, TWD (2020-10-30), and the former national currencies of euro area members (CYP, EEK, GRD, LTL, LVL, MTL, SIT, SKK).
Data source and terms
Source: ECB statistics. The ECB's policy on reusing ESCB statistics (https://www.ecb.europa.eu/stats/ecb_statistics/governance_and_quality_framework/html/usage_policy.en.html) allows free reuse, including commercial use, on the condition that the source is quoted and the statistics are not modified. This actor passes ECB values through unchanged (ecbQuotePerEur, ecbBasePerEur, and rate when the base is EUR), and every value it calculates is marked (rateIsComputed, inverseRateIsComputed). Each row carries the source line in source. Keep it when you republish the data. The ECB notes that its statistics may be revised.
The ECB reference rates are published for information purposes only; they are not the rates at which you can trade.
Pricing
You pay per rate row returned. Explanation rows are free. The default input (all currencies, latest day) returns about 30 rows. See "How many rows" above before asking for all currencies over a long period.