Currency Exchange Rates API avatar

Currency Exchange Rates API

Pricing

from $0.50 / 1,000 exchange rates

Go to Apify Store
Currency Exchange Rates API

Currency Exchange Rates API

Get latest or historical exchange rates for any currency pairs, with amount conversion: ECB and 100+ central-bank reference rates via Frankfurter, data back to 1948. $0.50 per 1,000 rates; invalid pairs and dates without data are free.

Pricing

from $0.50 / 1,000 exchange rates

Rating

0.0

(0)

Developer

SFOLN LLC

SFOLN LLC

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Currency Exchange Rates API gets latest or historical exchange rates for any list of currency pairs and converts an amount in the same call. Rates are mid-market reference rates published by the European Central Bank and 100+ other central banks and official sources, blended by the open-source Frankfurter service (data back to 1948). Ideal for invoicing, e-commerce price lists, accounting exports, spreadsheets and AI agents that need a reliable, citable rate.

  • $0.50 per 1,000 rates, charged only per returned rate – malformed pairs, unknown currencies and dates without data are free.
  • Pairs that share a base currency and date are fetched together, so large lists finish fast.
  • Same JSON for the sync API, async runs and the Console; per-run spend cap honoured (Maximum cost per run).

Input

FieldTypeDefaultDescription
pairsstring[] or object[]–BASE/QUOTE ISO 4217 codes (USD/EUR, usd eur, USDEUR), optional @YYYY-MM-DD for a historical rate. Objects: { "base": "USD", "quotes": ["EUR","JPY"], "date": "2024-01-05", "amount": 250 }.
amountstring"1"Amount in the base currency to convert (applies to pairs without their own amount): a plain number written as a string, with a decimal point ("100", "99.95"); the API rejects a bare number here. Thousands separators, decimal commas, currency signs or negative values make the pair skipped_invalid.
datestringlatestHistorical date for pairs without their own @date.
maxPairsinteger1000Safety cap for this run; pairs beyond it are ignored and counted as inputItemsDropped in the OUTPUT record.
concurrencyinteger5Parallel workers.
includeRawbooleanfalseAttach the raw upstream row.
{
"pairs": ["USD/EUR", "EUR/GBP", "GBP/JPY@2024-01-05"],
"amount": "100"
}

Output

One dataset record per pair:

{
"input": { "pair": "USD/EUR", "base": "USD", "quote": "EUR", "amount": 100 },
"pair": "USD/EUR",
"base": "USD",
"quote": "EUR",
"rate": 0.89273,
"inverseRate": 1.120159511,
"date": "2026-10-14",
"requestedDate": null,
"amount": 100,
"converted": 89.273,
"status": "ok",
"charged": true,
"chargedEvent": "fx-rate",
"source": "frankfurter (ECB and other central banks)",
"fetchedAt": "2026-10-14T10:00:00.000Z"
}
FieldDescription
rateUnits of quote per 1 base (mid-market reference rate).
inverseRate1 / rate, rounded to 10 significant digits.
dateDate of the reference rate. Latest rates are updated once per working day.
requestedDateThe date you asked for (null = latest).
amount, convertedAmount in base currency and amount × rate in quote currency (6 decimals; round for display).

status: ok – rate returned, charged. not_found – the rate service has no rate for that pair or date, not charged. skipped_invalid – not a valid pair, an unsupported currency code, an impossible or future date (e.g. 2024-02-30) or an invalid amount; never sent upstream, not charged. error – upstream unavailable or the request was blocked, not charged. skipped_budget / skipped_free_plan – not processed because of your cost cap or the free-plan limit. The key-value store record OUTPUT holds run totals.

Pricing

EventPriceWhen charged
Exchange rate (fx-rate)$0.0005 per rate ($0.50 / 1,000)once per pair (and date) with status: "ok"

Set Maximum cost per run to cap spend; when the cap is reached the remaining pairs are returned with status: "skipped_budget" and are not charged. Accounts on the Apify free plan can process up to 10 items per run; upgrade to any paid plan for full batches.

Use with AI agents (MCP)

Use this Actor from Claude, ChatGPT, Cursor, VS Code or any other MCP client through the Apify MCP server. Add this server URL to your client and sign in with your Apify account when asked:

https://mcp.apify.com?tools=sfoln/fx-rates

To run the MCP server locally instead, start npx -y @apify/actors-mcp-server --tools sfoln/fx-rates with your APIFY_TOKEN in the environment.

Example prompt:

Get today's USD/EUR, EUR/GBP and GBP/JPY exchange rates and convert 2,500 USD to EUR.

Runs started by an agent are billed like any other run (see Pricing). Agents can cap what a run may spend with maxTotalChargeUsd.

API usage

Run the Actor and get its dataset items in one call (the call waits up to 5 minutes for the run to finish):

curl -X POST "https://api.apify.com/v2/acts/sfoln~fx-rates/run-sync-get-dataset-items" \
-H "Authorization: Bearer <APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"pairs": ["USD/EUR", "EUR/GBP", "GBP/JPY@2024-01-05"]}'

For large inputs, start the run asynchronously and download the dataset when it has finished:

# 1. Start a run: the response holds the run ID (data.id) and its dataset ID (data.defaultDatasetId)
curl -X POST "https://api.apify.com/v2/acts/sfoln~fx-rates/runs" \
-H "Authorization: Bearer <APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"pairs": ["USD/EUR", "EUR/GBP", "GBP/JPY@2024-01-05"]}'
# 2. Repeat until data.status is SUCCEEDED (each call waits up to 60 s)
curl "https://api.apify.com/v2/actor-runs/<runId>?waitForFinish=60" -H "Authorization: Bearer <APIFY_TOKEN>"
# 3. Download the results (format=json, csv or xlsx)
curl "https://api.apify.com/v2/datasets/<defaultDatasetId>/items?format=json" -H "Authorization: Bearer <APIFY_TOKEN>"

Python (apify-client):

from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("sfoln/fx-rates").call(run_input={"pairs": ["USD/EUR", "EUR/GBP", "GBP/JPY@2024-01-05"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

Instead of polling, you can attach a webhook to the run (see Integrations). The API tab of this page shows the same calls for JavaScript and the Apify CLI.

More API examples

Synchronous:

curl -X POST "https://api.apify.com/v2/acts/sfoln~fx-rates/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"pairs": ["USD/EUR", "EUR/GBP@2024-01-05"], "amount": "100"}'

Asynchronous (large lists):

curl -X POST "https://api.apify.com/v2/acts/sfoln~fx-rates/runs?token=<APIFY_TOKEN>" \
-H "Content-Type: application/json" -d '{"pairs": [{"base": "USD", "quotes": ["EUR", "GBP", "JPY", "CHF"]}]}'
# → poll /v2/actor-runs/<runId>, then GET /v2/datasets/<defaultDatasetId>/items

Python:

from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("sfoln/fx-rates").call(run_input={"pairs": ["USD/EUR", "USD/JPY"], "amount": "250"})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["pair"], item["rate"], item["converted"], item["date"])

Integrations

  • Make, Zapier and n8n: run sfoln/fx-rates with the Apify app (in n8n, the Apify node) and pass the dataset items to the next step of your workflow.
  • Google Sheets: add the items to a sheet with the Google Sheets step of Make, Zapier or n8n, or download them as CSV or Excel from the run's Storage tab or the API (format=csv or format=xlsx).
  • Webhooks: get a POST request when a run succeeds or fails: add a webhook in the Actor's Integrations tab, or pass webhooks when you start a run through the API.
  • Schedules: run it hourly, daily or weekly with the same input from Apify Schedules; every run keeps its results in its own dataset.
  • More: Slack, Google Drive, GitHub, LangChain, LlamaIndex and other Apify integrations.

See all our Actors on Apify Store.

FAQ

How much does it cost, and am I charged for failed items?

You pay per event at the prices under Pricing above, plus a run start fee of $0.00005 per GB of memory, with no subscription; platform usage is included. Errors and skipped items (skipped_… statuses) are never charged; a lookup that finds nothing is charged only where Pricing says so, and every record's charged field shows whether it was billed. Set Maximum cost per run to cap what a single run can spend.

How fresh is the data?

Each run queries its source while it runs, so you get what the source returns at that moment. Source-specific details, such as how often a provider refreshes its own database, are under Limits & notes.

What are the limits?

Per-run caps (for example the maximum number of items) are listed under Input, source limits under Limits & notes, and the free-plan limit under Pricing. For big batches, start the run asynchronously (see API usage) and read the dataset when it has finished.

Can I schedule runs or get results by webhook?

Yes. Create a schedule in Apify Console to run it hourly, daily or weekly with the same input, and add a webhook to get a POST request when a run finishes (see Integrations).

What does this Actor record about my runs?

This Actor records operational metrics about each run (item counts, duration, charges, error codes and a pseudonymous hash of your Apify user ID) to monitor reliability and costs. It never stores your input or results.

How do I get help?

Open an issue in the Actor's Issues tab and include the link to the run, so we can reproduce the problem. Feature requests are welcome there too.

Limits & notes

  • Data source: Frankfurter (frankfurter.dev), which blends reference rates from the European Central Bank and other central banks and official sources. Blended rates are free to use commercially; for compliance use cases that require one official source, note that this Actor returns the blended rate.
  • Rates are daily mid-market reference rates, not live trading quotes, bid/ask prices or card-network rates. Weekend and holiday dates return the rate published for that date by Frankfurter.
  • Single dates only (no time series in one record). Currency codes are checked against Frankfurter's currency list (loaded at the start of each run, see frankfurter.dev); unsupported codes are returned as skipped_invalid.