This guide uses the official forexrateapi Python package. It covers authentication, current rates,
historical dates, pandas ingestion, OHLC data, and the error shape returned by the API.
Get a free API key before running the examples.
Install the package and pandas:
python -m pip install forexrateapi pandas
The SDK source and package documentation are also available in the ForexRateAPI Python repository.
Pass your API key when creating the client. The SDK attaches it to each request.
import os
from forexrateapi.client import Client
api_key = os.environ["FOREXRATEAPI_KEY"]
client = Client(api_key)
Set the environment variable before running your script:
export FOREXRATEAPI_KEY="YOUR_API_KEY"
Use Client(api_key, server="eu") if your application should call the European API server.
Do not commit API keys to source control.
fetchLive accepts a base currency and a list of target currencies. USD is the default base.
payload = client.fetchLive(
base="USD",
currencies=["EUR", "GBP", "JPY"],
)
if not payload.get("success"):
raise RuntimeError(payload.get("error", {}).get("info", "Forex API request failed"))
rates = payload["rates"]
print(f"1 USD = {rates['EUR']} EUR")
print(f"1 USD = {rates['GBP']} GBP")
print(f"1 USD = {rates['JPY']} JPY")
Refresh frequency depends on your subscription plan. See plans and quotas.
Pass a date in YYYY-MM-DD format to fetchHistorical.
from datetime import date, timedelta
historical_date = (date.today() - timedelta(days=2)).isoformat()
payload = client.fetchHistorical(
date=historical_date,
base="USD",
currencies=["EUR", "GBP", "JPY"],
)
if not payload.get("success"):
raise RuntimeError(payload.get("error", {}).get("info", "Historical request failed"))
print(payload["base"])
print(payload["rates"])
For endpoint availability, date ranges, hourly data, and OHLC limits, see the historical Forex data API page.
The timeframe response stores rates under date keys. Convert that mapping directly into a DataFrame:
import pandas as pd
from datetime import date, timedelta
end_date = date.today() - timedelta(days=1)
start_date = end_date - timedelta(days=4)
payload = client.timeframe(
start_date=start_date.isoformat(),
end_date=end_date.isoformat(),
base="USD",
currencies=["EUR"],
)
if not payload.get("success"):
raise RuntimeError(payload.get("error", {}).get("info", "Timeframe request failed"))
frame = pd.DataFrame.from_dict(payload["rates"], orient="index")
frame.index = pd.to_datetime(frame.index)
frame.index.name = "date"
frame = frame.sort_index()
print(frame.head())
print(frame.dtypes)
The resulting frame has one row per date and one numeric column per requested currency. The example works with a free key. Free plans support recent ranges up to 5 days and one quote currency; paid plans support multiple quote currencies and ranges up to 365 days.
The hourly endpoint accepts one quote currency per request:
from datetime import date, timedelta
hourly_date = (date.today() - timedelta(days=1)).isoformat()
payload = client.hourly(
base="USD",
currency="EUR",
start_date=hourly_date,
end_date=hourly_date,
)
if not payload.get("success"):
raise RuntimeError(payload.get("error", {}).get("info", "Hourly request failed"))
hourly_frame = pd.DataFrame(
{
"timestamp": point["timestamp"],
"EUR": point["rates"]["EUR"],
}
for point in payload["rates"]
)
hourly_frame["timestamp"] = pd.to_datetime(
hourly_frame["timestamp"],
unit="s",
utc=True,
)
print(hourly_frame.head())
Free plans can query up to 2 days within the latest 2 days. Paid plans can query stored hourly history from June 19, 2025 in windows up to 7 days. Future dates and multiple quote currencies are not accepted.
Use ohlc for one base/quote pair and date:
from datetime import date, timedelta
ohlc_date = (date.today() - timedelta(days=1)).isoformat()
payload = client.ohlc(
base="EUR",
currency="USD",
date=ohlc_date,
)
if not payload.get("success"):
raise RuntimeError(payload.get("error", {}).get("info", "OHLC request failed"))
candle = payload["rate"]
print(candle["open"], candle["high"], candle["low"], candle["close"])
OHLC values use a 00:00–23:59:59 GMT trading day. The previous day becomes available at 00:05 GMT. Free plans can query the latest 5 days; older stored OHLC dates require a paid plan.
The SDK returns the decoded JSON response. API errors use success: false with an error object, so
check the response before reading rates or rate.
def require_success(payload):
if payload.get("success"):
return payload
error = payload.get("error", {})
code = error.get("code", "unknown")
message = error.get("info", "Forex API request failed")
raise RuntimeError(f"ForexRateAPI error {code}: {message}")
payload = require_success(
client.fetchLive(base="USD", currencies=["EUR"])
)
Common errors include a missing or invalid API key, invalid currency codes or dates, exhausted quota, and endpoint-specific range limits. Review the complete API errors reference.
Network exceptions raised by the underlying requests library should be handled separately when your
application needs retries or custom timeout behavior.