Skip to main content

Zero-dependency command-line client for the Frankfurter foreign-exchange API

Project description

exrate

A zero-dependency command-line client for the Frankfurter v2 foreign-exchange API. Daily reference rates from 84 central banks, 201 currencies, back to 1948. No API key, no login, no rate caps for normal use.

It's a single Python file (exrate.py, stdlib only) — runs anywhere Python 3.8+ exists. Every subcommand maps 1:1 to the Frankfurter OpenAPI spec, and every subcommand accepts --json for machine-readable output, which also makes it pleasant to drive from scripts and AI agents.

Install

From PyPI (recommended):

pipx install exrate     # isolated, puts `exrate` on your PATH
# or
pip install exrate

From source (symlink install for hacking on it):

git clone https://github.com/ekinertac/exrate.git
cd exrate
./install.sh        # symlinks exrate.py -> ~/.local/bin/exrate
exrate --help

install.sh symlinks (not copies) the script, so edits take effect with no reinstall. It installs into ~/.local/bin; make sure that's on your PATH.

Usage

exrate rate EUR USD                              # latest single pair
exrate rate EUR USD --date 2020-03-15            # historical
exrate convert 100 USD JPY                       # convert an amount (client-side)
exrate rates --base USD --quotes EUR,GBP,JPY     # several pairs at once
exrate rates --from 2026-01-01 --quotes USD      # daily time series
exrate rates --from 2026-01-01 --group month     # downsample to monthly
exrate rates --from 2026-01-01 --quotes USD --csv  # native CSV
exrate currencies                                # list currency codes
exrate currencies --all                          # include legacy currencies
exrate currency AED                              # one currency's details + peg
exrate providers                                 # data sources (central banks)

Add --json to any command for raw API JSON (numbers stay JSON numbers, not strings), handy for jq pipelines:

exrate currencies --json | jq -r '.[].iso_code'
exrate providers  --json | jq -r '.[].key'

Run exrate <subcommand> --help for that command's modes, fields, and examples.

Commands

Command Endpoint Purpose
rate BASE QUOTE GET /rate/{base}/{quote} One pair, latest or historical
rates GET /rates Many rates: latest, a date, or a time series
convert AMOUNT FROM TO (client-side) Multiply amount by the pair rate
currencies GET /currencies List supported currency codes
currency CODE GET /currency/{code} One currency's details + peg metadata
providers GET /providers Data providers (central banks) and their keys

Conventions

  • Currency codes are ISO 4217, 3 letters, case-insensitive (eur == EUR).
  • Dates are YYYY-MM-DD. Weekends/holidays return the last published rate.
  • Default base is EUR. The base is the "1 unit" side; the rate says how many quote units equal 1 base unit.
  • Providers: rates are blended across providers by default. Pass --providers ECB to pin a single official source.
  • Conversion is client-side — the API has no conversion endpoint, so convert fetches the pair rate and multiplies (matching the official docs' approach).

Exit codes

Code Meaning
0 Success
1 API or network error (message on stderr, e.g. unknown currency)
2 Bad usage / invalid arguments

Releasing

Versions are single-sourced from __version__ in exrate.py. To cut a release:

  1. Bump __version__ in exrate.py.
  2. Commit and tag: git tag v1.2.3 && git push --tags.
  3. On GitHub: Releases → Draft a new release, pick the tag, Publish.

Publishing a GitHub Release triggers .github/workflows/publish.yml, which builds the sdist + wheel and uploads them to PyPI via Trusted Publishing (OIDC, no stored tokens). One-time PyPI setup before the first Actions run:

PyPI → Your projects / PublishingAdd a pending publisher · Owner: ekinertac · Repository: exrate · Workflow: publish.yml · Environment: pypi

To build/publish manually instead:

pipx run build                 # -> dist/*.tar.gz, dist/*.whl
pipx run twine check dist/*
pipx run twine upload dist/*   # prompts for a PyPI API token

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

exrate-1.0.0.tar.gz (9.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

exrate-1.0.0-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file exrate-1.0.0.tar.gz.

File metadata

  • Download URL: exrate-1.0.0.tar.gz
  • Upload date:
  • Size: 9.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for exrate-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3ed1dfe29caf4fbf6a89c82cc977eba4d4946014f435433fcc49e96996eec2f8
MD5 6f768c11e2107b1ed654947a39e437e7
BLAKE2b-256 3d12184f7602022234f55c241d2b0e1b005212e28b6aaed96eafae2b653ee701

See more details on using hashes here.

File details

Details for the file exrate-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: exrate-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for exrate-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 406c87d3af625b7303c086ef21d49281f6c81e475c3eea7ab887fe8b2a9f9f88
MD5 260cb60a8bd73ddac9613531e454c7f8
BLAKE2b-256 65e1a2b5f5a49ae5d6b0c6da1fbdeb5af5c59987ba8551426d071d7dd4f53c1b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page