Frankfurter's CSV endpoint loads straight into a DataFrame, so pulling rates is one line. The reason to reach for it over a quick market-rate lookup is reproducibility: pin a single authority and your notebook is auditable, and the history doesn't get silently revised, so a backtest you run today still matches the one you ran last year.

Quick Start

Point read_csv at the CSV endpoint:

import pandas as pd

df = pd.read_csv("https://api.frankfurter.dev/v2/rates.csv?base=USD&quotes=EUR,GBP")

You get a date,base,quote,rate frame, one row per quote.

Convert an Amount

The CSV gives you the rate, not a converted total. Multiply your amount by the rate column. For a single scalar without pandas, hit the flat rate endpoint with requests:

import requests

rate = requests.get("https://api.frankfurter.dev/v2/rate/USD/EUR").json()["rate"]
total = 100 * rate

Pin an Official Provider

By default you get the blend across every provider. Add providers to pin a single authority, which keeps an analysis auditable: many jurisdictions require their own central bank's published rate when converting foreign-currency amounts.

df = pd.read_csv("https://api.frankfurter.dev/v2/rates.csv?base=USD&quotes=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 for one row per month. Parse the date column and set it as the index, then chart or resample. This is where Frankfurter earns its place in a notebook: long, stable series that don't get silently revised.

df = pd.read_csv(
    "https://api.frankfurter.dev/v2/rates.csv?from=1949-12-01&base=USD&quotes=GBP&providers=BBK&group=month",
    parse_dates=["date"],
    index_col="date",
)
df["rate"].plot()

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.