|
| 1 | +# exchangerateapi |
| 2 | + |
| 3 | +[](https://pypi.org/project/exchangerateapi/) |
| 4 | +[](https://github.com/Exchange-RateAPI/exchange-rateapi-python/blob/main/LICENSE) |
| 5 | +[](https://pypi.org/project/exchangerateapi/) |
| 6 | +[](https://pypi.org/project/exchangerateapi/) |
| 7 | + |
| 8 | +**The most elegant way to access real-time mid-market exchange rates in Python** |
| 9 | + |
| 10 | +## Why Choose This Client? |
| 11 | + |
| 12 | +- **Lightning Fast** -- Zero dependencies, pure Python standard library |
| 13 | +- **Real-Time Data** -- Rates updated every 60 seconds from Reuters (Refinitiv) and interbank feeds |
| 14 | +- **Mid-Market Rates** -- The true interbank rate -- no hidden spread or markup |
| 15 | +- **160+ Currencies** -- Major, minor, and exotic currency pairs |
| 16 | +- **Type Hints** -- Full type annotations for IDE autocomplete |
| 17 | +- **Zero Dependencies** -- Uses only `urllib` and `json` from the standard library |
| 18 | + |
| 19 | +## Get Your API Key |
| 20 | + |
| 21 | +Ready to start? Get your free API key from [exchange-rateapi.com/register](https://exchange-rateapi.com/register). |
| 22 | + |
| 23 | +## Installation |
| 24 | + |
| 25 | +```bash |
| 26 | +pip install exchangerateapi |
| 27 | +``` |
| 28 | + |
| 29 | +## Quick Start |
| 30 | + |
| 31 | +Get up and running in seconds: |
| 32 | + |
| 33 | +```python |
| 34 | +from exchangerateapi import ExchangeRateAPI |
| 35 | + |
| 36 | +# Set your API key |
| 37 | +client = ExchangeRateAPI(api_key="era_live_YOUR_API_KEY") |
| 38 | + |
| 39 | +# Get latest exchange rates |
| 40 | +data = client.latest(base="USD", symbols=["EUR", "GBP", "JPY"]) |
| 41 | +print(data["rates"]) # {"EUR": 0.9234, "GBP": 0.7891, "JPY": 151.42} |
| 42 | + |
| 43 | +# Convert an amount |
| 44 | +result = client.convert("USD", "EUR", 1000) |
| 45 | +print(f"$1,000 = EUR {result['result']}") |
| 46 | +``` |
| 47 | + |
| 48 | +## API Reference |
| 49 | + |
| 50 | +- [Latest Rates](#latest-exchange-rates) -- Get current exchange rates |
| 51 | +- [Historical Data](#historical-exchange-rates) -- Fetch rates for specific dates |
| 52 | +- [Currency Conversion](#currency-conversion) -- Convert between currencies |
| 53 | +- [Time Series](#time-series-data) -- Get rates over date ranges |
| 54 | +- [Available Currencies](#available-currencies) -- List all supported currencies |
| 55 | +- [Single Rate](#single-rate) -- Get one currency pair |
| 56 | +- [Historical by Period](#historical-rates-by-period) -- Preset period lookups |
| 57 | + |
| 58 | +--- |
| 59 | + |
| 60 | +### Latest Exchange Rates |
| 61 | + |
| 62 | +Get the most current exchange rates with a single call: |
| 63 | + |
| 64 | +```python |
| 65 | +# All rates from USD (default base) |
| 66 | +data = client.latest() |
| 67 | +print(data["rates"]) |
| 68 | + |
| 69 | +# Target specific currencies with EUR base |
| 70 | +data = client.latest(base="EUR", symbols=["USD", "GBP", "JPY"]) |
| 71 | +print(data["rates"]) |
| 72 | +# {"USD": 1.083, "GBP": 0.8546, "JPY": 163.92} |
| 73 | +``` |
| 74 | + |
| 75 | +**Response:** |
| 76 | + |
| 77 | +```python |
| 78 | +{ |
| 79 | + "base": "EUR", |
| 80 | + "date": "2026-04-09T14:30:00Z", |
| 81 | + "rates": {"USD": 1.083, "GBP": 0.8546, "JPY": 163.92} |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +### Historical Exchange Rates |
| 88 | + |
| 89 | +Travel back in time to get rates from any date: |
| 90 | + |
| 91 | +```python |
| 92 | +# Using a string date |
| 93 | +data = client.for_date("2026-01-15", base="USD", symbols=["EUR"]) |
| 94 | +print(data["rates"]) # {"EUR": 0.9187} |
| 95 | + |
| 96 | +# Using a date object |
| 97 | +from datetime import date |
| 98 | +data = client.for_date(date(2026, 1, 15), base="EUR", symbols=["USD", "GBP"]) |
| 99 | + |
| 100 | +# Using a datetime object |
| 101 | +from datetime import datetime |
| 102 | +data = client.for_date(datetime(2026, 1, 15, 12, 0, 0)) |
| 103 | +``` |
| 104 | + |
| 105 | +**Response:** |
| 106 | + |
| 107 | +```python |
| 108 | +{ |
| 109 | + "base": "USD", |
| 110 | + "date": "2026-01-15", |
| 111 | + "rates": {"EUR": 0.9187} |
| 112 | +} |
| 113 | +``` |
| 114 | + |
| 115 | +--- |
| 116 | + |
| 117 | +### Currency Conversion |
| 118 | + |
| 119 | +Convert any amount between currencies -- including historical conversions: |
| 120 | + |
| 121 | +```python |
| 122 | +# Current conversion |
| 123 | +result = client.convert("USD", "EUR", 1000) |
| 124 | +print(result) |
| 125 | +# {"from": "USD", "to": "EUR", "amount": 1000, "result": 923.4, "rate": 0.9234} |
| 126 | + |
| 127 | +# Historical conversion -- what was $1,000 worth on Jan 15? |
| 128 | +result = client.convert("USD", "EUR", 1000, date="2026-01-15") |
| 129 | +print(f"Rate on Jan 15: {result['rate']}") |
| 130 | +# {"from": "USD", "to": "EUR", "amount": 1000, "result": 918.7, "rate": 0.9187, "date": "2026-01-15"} |
| 131 | + |
| 132 | +# Using a date object |
| 133 | +from datetime import date |
| 134 | +result = client.convert("GBP", "JPY", 500, date=date(2025, 12, 31)) |
| 135 | +``` |
| 136 | + |
| 137 | +--- |
| 138 | + |
| 139 | +### Available Currencies |
| 140 | + |
| 141 | +Discover all 160+ supported currency symbols and names: |
| 142 | + |
| 143 | +```python |
| 144 | +data = client.symbols() |
| 145 | +print(data["symbols"]) |
| 146 | +# { |
| 147 | +# "USD": "United States Dollar", |
| 148 | +# "EUR": "Euro", |
| 149 | +# "GBP": "British Pound Sterling", |
| 150 | +# "JPY": "Japanese Yen", |
| 151 | +# ...160+ currencies |
| 152 | +# } |
| 153 | + |
| 154 | +# Build a currency list |
| 155 | +for code, name in data["symbols"].items(): |
| 156 | + print(f"{code}: {name}") |
| 157 | +``` |
| 158 | + |
| 159 | +--- |
| 160 | + |
| 161 | +### Time Series Data |
| 162 | + |
| 163 | +Get exchange rates over a date range for trend analysis and charting: |
| 164 | + |
| 165 | +```python |
| 166 | +data = client.time_series( |
| 167 | + "2026-01-01", "2026-03-31", |
| 168 | + base="USD", |
| 169 | + symbols=["EUR", "GBP"], |
| 170 | +) |
| 171 | +print(data["rates"]["2026-01-15"]) |
| 172 | +# {"EUR": 0.9187, "GBP": 0.7834} |
| 173 | + |
| 174 | +# Using date objects |
| 175 | +from datetime import date |
| 176 | +data = client.time_series( |
| 177 | + date(2026, 1, 1), date(2026, 3, 31), |
| 178 | + symbols=["EUR"], |
| 179 | +) |
| 180 | +``` |
| 181 | + |
| 182 | +**Response:** |
| 183 | + |
| 184 | +```python |
| 185 | +{ |
| 186 | + "base": "USD", |
| 187 | + "start_date": "2026-01-01", |
| 188 | + "end_date": "2026-03-31", |
| 189 | + "rates": { |
| 190 | + "2026-01-01": {"EUR": 0.9187, "GBP": 0.7834}, |
| 191 | + "2026-01-02": {"EUR": 0.9195, "GBP": 0.7841}, |
| 192 | + ... |
| 193 | + } |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +--- |
| 198 | + |
| 199 | +### Single Rate |
| 200 | + |
| 201 | +Get a single exchange rate between two currencies: |
| 202 | + |
| 203 | +```python |
| 204 | +rate = client.get_rate("USD", "EUR") |
| 205 | +print(f"1 USD = {rate['rate']} EUR") |
| 206 | + |
| 207 | +# With amount |
| 208 | +rate = client.get_rate("USD", "EUR", 500) |
| 209 | +print(f"$500 = EUR {rate['to']['amount']}") |
| 210 | +``` |
| 211 | + |
| 212 | +--- |
| 213 | + |
| 214 | +### Historical Rates by Period |
| 215 | + |
| 216 | +Get historical rates using preset periods -- no date math needed: |
| 217 | + |
| 218 | +```python |
| 219 | +history = client.get_historical_rates("USD", "EUR", "30d") |
| 220 | +print(f"Current: {history['current']['rate']}") |
| 221 | +for point in history["rates"]: |
| 222 | + print(f"{point['time']}: {point['rate']}") |
| 223 | +``` |
| 224 | + |
| 225 | +**Available periods:** `1d`, `7d`, `30d`, `1y` (default: `7d`) |
| 226 | + |
| 227 | +--- |
| 228 | + |
| 229 | +## Configuration |
| 230 | + |
| 231 | +```python |
| 232 | +client = ExchangeRateAPI( |
| 233 | + api_key="era_live_YOUR_API_KEY", # Required |
| 234 | + base_url="https://exchange-rateapi.com", # Optional |
| 235 | + timeout=10, # Optional (seconds) |
| 236 | +) |
| 237 | +``` |
| 238 | + |
| 239 | +| Parameter | Type | Default | Description | |
| 240 | +| ---------- | ----- | ------------------------------ | ------------------------------- | |
| 241 | +| `api_key` | `str` | -- | Your API key | |
| 242 | +| `base_url` | `str` | `https://exchange-rateapi.com` | API base URL | |
| 243 | +| `timeout` | `int` | `10` | Request timeout in seconds | |
| 244 | + |
| 245 | +--- |
| 246 | + |
| 247 | +## Per-Request API Key Override |
| 248 | + |
| 249 | +Every method supports a per-request API key override -- useful for multi-tenant apps: |
| 250 | + |
| 251 | +```python |
| 252 | +client = ExchangeRateAPI(api_key="default_key") |
| 253 | + |
| 254 | +# Override for a specific request |
| 255 | +data = client.latest(api_key="other_users_key") |
| 256 | +result = client.convert("USD", "EUR", 100, api_key="tenant_key") |
| 257 | +symbols = client.symbols(api_key="another_key") |
| 258 | +``` |
| 259 | + |
| 260 | +--- |
| 261 | + |
| 262 | +## Error Handling |
| 263 | + |
| 264 | +All errors are raised as `ExchangeRateAPIError` with an optional HTTP status code: |
| 265 | + |
| 266 | +```python |
| 267 | +from exchangerateapi import ExchangeRateAPI, ExchangeRateAPIError |
| 268 | + |
| 269 | +client = ExchangeRateAPI(api_key="era_live_YOUR_API_KEY") |
| 270 | + |
| 271 | +try: |
| 272 | + rate = client.get_rate("USD", "INVALID") |
| 273 | +except ExchangeRateAPIError as e: |
| 274 | + print(e) # "Currency not found" |
| 275 | + print(e.status) # 404 |
| 276 | +``` |
| 277 | + |
| 278 | +| Status | Meaning | |
| 279 | +| ------ | -------------------------------------- | |
| 280 | +| -- | Missing API key (raised before request) | |
| 281 | +| `401` | Invalid API key | |
| 282 | +| `404` | Currency code not found | |
| 283 | +| `429` | Rate limit exceeded | |
| 284 | +| `500` | Server error | |
| 285 | + |
| 286 | +--- |
| 287 | + |
| 288 | +## Methods Reference |
| 289 | + |
| 290 | +| Method | Description | |
| 291 | +| --------------------------------------------------- | ---------------------------------------------------------- | |
| 292 | +| `latest(base, symbols, api_key)` | Get latest rates for one or more currencies | |
| 293 | +| `for_date(date, base, symbols, api_key)` | Get rates for a specific historical date | |
| 294 | +| `convert(from, to, amount, date, api_key)` | Convert amount (supports historical date) | |
| 295 | +| `time_series(start, end, base, symbols, api_key)` | Get rates across a custom date range | |
| 296 | +| `symbols(api_key)` | List all 160+ supported currency codes and names | |
| 297 | +| `get_rate(from, to, amount, api_key)` | Get a single exchange rate | |
| 298 | +| `get_rates(source, target, api_key)` | Get rates with full metadata | |
| 299 | +| `get_historical_rates(source, target, period, api_key)` | Historical rates by preset period (1d/7d/30d/1y) | |
| 300 | + |
| 301 | +--- |
| 302 | + |
| 303 | +## Zero Dependencies |
| 304 | + |
| 305 | +This SDK uses only Python standard library (`urllib`, `json`). No external packages required. Nothing to audit, nothing to break. |
| 306 | + |
| 307 | +--- |
| 308 | + |
| 309 | +## Links |
| 310 | + |
| 311 | +- [API Documentation](https://exchange-rateapi.com/developers) |
| 312 | +- [Register (Free)](https://exchange-rateapi.com/register) |
| 313 | +- [Dashboard](https://exchange-rateapi.com/profile) |
| 314 | +- [Status](https://exchange-rateapi.com/status) |
| 315 | +- [GitHub](https://github.com/Exchange-RateAPI/exchange-rateapi-python) |
| 316 | + |
| 317 | +## License |
| 318 | + |
| 319 | +MIT |
0 commit comments