You are building a price converter or an international reporting dashboard, and you need exchange rates before you need another paid subscription. Frankfurter is an appealing starting point: it provides currency data over HTTPS without an API key. The important question is whether its data and update schedule fit the feature you are building.
The short answer: Frankfurter is useful for daily reference rates, historical analysis and prototypes. Start new integrations with v2, check the rate's observation date, and verify coverage for your actual currency pairs. For an application that needs a different refresh cadence, commercial support or a dedicated conversion endpoint, compare those requirements with alternatives before committing.
Here is how to make that decision and build a small conversion example without confusing a reference rate with the price a customer will actually pay.
What is the Frankfurter API?
Frankfurter is an open-source API that collects exchange-rate data from central banks and other official sources. Its public service needs no account or key. The current v2 API combines multiple providers by default; it is no longer accurate to describe the whole service as simply an ECB-only feed.
The project publishes daily data rather than a streaming trading feed. It has no daily or monthly request quota, but does apply abuse protection. Cache shared responses instead of making one request for every visitor. You can also self-host the software, although operating the service then becomes your responsibility.
The software's MIT license and data terms are separate: source-provider terms still apply to the rates. A blended rate is Frankfurter's calculation, rather than an official publication by a single institution.
Start with v2, especially if you found an older tutorial
Older examples commonly use /v1/latest and a symbols parameter. Frankfurter's v1 documentation says that version is deprecated but remains available. Existing integrations therefore need a considered migration, not an emergency rewrite.
For a new integration, these are the key request shapes:
|
Task |
v2 request path |
|---|---|
|
One pair |
|
|
Several quotes |
|
|
One historical day |
|
|
A date range |
|
|
Check pair history |
|
Add each path to https://api.frankfurter.dev. In v2, a single-pair request returns an object; the rates endpoint returns an array of records. Do not reuse a v1 parser that expects a nested rates map. The OpenAPI specification describes the response fields and accepted parameters.
For example, this requests the EUR-to-USD rate:
curl --fail-with-body \ 'https://api.frankfurter.dev/v2/rate/eur/usd'
These request paths were checked against the current documentation. Our direct live requests were blocked with HTTP 403 in the test environment, so the examples below use labelled fixture data rather than claiming a successful live response.
Convert an amount without losing the original value
A rate of 1.08 USD per EUR means that 100 EUR converts to 108 USD before any fees or spread. Multiplication is the easy part. Your application also needs to retain the original amount, currency and rate date so that the result remains explainable later.

Illustrative example. The rate is a test fixture, not a current market quote.
Frankfurter's Python integration guide explains how to parse rates using decimal arithmetic. This small example uses only Python's standard library and makes the rounding policy explicit for a USD result:
from decimal import Decimal, ROUND_HALF_UPimport json# Illustrative fixture, not a captured API response.payload = '{"base":"EUR","quote":"USD","rate":1.08}'rate_data = json.loads(payload, parse_float=Decimal)amount = Decimal("100.00")converted = (amount * rate_data["rate"]).quantize( Decimal("0.01"), rounding=ROUND_HALF_UP)print(f'{amount} EUR = {converted} USD')
This prints 100.00 EUR = 108.00 USD. We ran the calculation locally. It checks the arithmetic, not the public API's availability. When connecting it to a real response, validate the HTTP status, expected pair, positive finite rate and observation date before using the value.
The two-decimal rounding in this example is specific to the selected output currency and application policy. Do not copy that assumption into every currency. Our guide to handling multiple currencies in a SaaS app explains why amounts and currency codes need to travel together.
Historical coverage needs a pair-specific check
Suppose you need to backfill an EUR-to-USD report. A headline saying the API has many decades of history does not establish that your chosen pair is available for every day in that period.
Use /v2/coverage with the same base, quotes and provider filters as your rate request. The project's coverage guidance explains that the returned bounds identify eligible observations and can contain gaps. Currency catalogue dates describe publication coverage; they are not a substitute for checking the pair.
For a chart, decide how to display days without a new observation. For a report, keep both the requested date and the returned rate date. Silently treating a previous observation as a fresh rate can make a correct multiplication produce a misleading result.
If your workflow requires a named source, select that provider and preserve its identity with the record. Confirm the source and date policy with the person responsible for the report before using it for formal accounting or tax work.
Frankfurter versus The Currency API
The useful comparison is the work each service needs to do for your application. A free public API can be the right long-term choice when its data fits; paying does not automatically make a particular rate appropriate.
|
Decision |
Frankfurter |
The Currency API |
|---|---|---|
|
Authentication |
Public API needs no key |
API key required |
|
Conversion |
Fetch a rate and calculate in your code |
Documented |
|
History |
Query pair and provider coverage |
Documented |
|
Usage model |
No monthly quota; abuse protection applies |
Monthly request allowances by plan |
|
Operations |
Public service or self-hosting |
Hosted service with support options listed by plan |
The Currency API's endpoint documentation covers latest rates, historical rates, conversion and the currency list. Its pricing page lists the included requests and support for each plan. Check the currencies and update cadence you actually need before choosing a tier.
For a wider shortlist, our currency API comparison provides further options. Then run the same small evaluation against each candidate: your pairs, your dates, the response timestamps and your expected request volume.
A practical checklist before shipping
- Cache by request meaning. Include the base, quotes, date and provider in the cache key so one result cannot masquerade as another.
- Store provenance. Keep the original amount, rate, source and observation date with any saved conversion.
- Choose a failure policy. For an indicative display, an explicitly dated cached value may be acceptable. A workflow that requires fresh data should stop or request review when that condition is unmet.
- Test edge cases. Cover unsupported pairs, empty history, timeouts, malformed JSON and changes in rounding precision. A single successful pair does not establish complete coverage.
- Keep the displayed claim accurate. An API conversion is a reference calculation. Bank spreads, payment fees and settlement timing can change the amount received.
Is Frankfurter the right starting point?
Choose Frankfurter when a no-key daily reference feed fits your project and you are comfortable owning the conversion and failure-handling logic. Its v2 provider and coverage controls make it worth assessing on its current capabilities rather than an old tutorial's description.
If your requirements point toward a hosted plan with a conversion endpoint and defined request allowances, start with The Currency API documentation and test the smallest endpoint set your feature needs. The best choice is the one that meets your data requirements and remains understandable when a rate is missing, late or revised.