hmrc-rates
HMRC exchange rates for Python, backed by the hmrc-rates Rust crate.
The full published history ships inside the wheel, so Rates() is free and needs no network, parsing or I/O.
All money values are decimal.Decimal and conversions are exact — the library never rounds.
Install
python3 -m pip install hmrc-rates
Python ≥ 3.10. Wheels ship for Linux (glibc and musl, x86_64 and aarch64), macOS and Windows. The sdist builds anywhere with a Rust toolchain.
Quick start
import datetime
from decimal import Decimal
from hmrc_rates import YearMonth, Rates, YearEnd
rates = Rates()
# Monthly customs/VAT rate; months can be YearMonth, datetime.date, or "YYYY-MM"
rate = rates.monthly_rate("USD", YearMonth(2025, 8))
gbp = rate.to_gbp(Decimal("2500")) # exact — you choose the rounding
print(f"$2500 in Aug 2025 = £{gbp.quantize(Decimal('0.01'))}")
# Self Assessment style: the yearly average to 31 March 2025
eur = rates.average(YearEnd.march(2025)).rate("EUR")
print(f"EUR average, year to 31 Mar 2025: {eur.units_per_gbp}")
# Whole tables iterate as (Currency, Rate) pairs
table = rates.monthly(datetime.date(2025, 8, 15))
print(f"{len(table)} currencies in {table.period}")
"GBP" always resolves to the identity rate, and code lookups are case-insensitive.
Data coverage
One Rates value holds all four series HMRC has published:
| Series | Coverage | Lookup |
|---|---|---|
| Monthly customs/VAT | 2014-02 — present, no gaps | monthly_rate(code, month) |
| Spot | Dec 2010 — present, years ending 31 Mar / 31 Dec | spot(year_end) |
| Yearly average | Dec 2010 — present, years ending 31 Mar / 31 Dec | average(year_end) |
| Weekly amendments | 2014-01 — 2016-04, complete (discontinued by HMRC) | weekly(date) |
Currency codes are as published by HMRC, which is not always ISO 4217.
E.g. Ecuador appears as ECS.
Strict lookups and exceptions
A period HMRC never published is an exception, never a silently substituted older rate.
Every exception derives from HmrcRatesError (not the builtin LookupError):
UnknownCurrencyError— the code never appears in that seriesPeriodNotAvailableError— no table for that period (the message includes the available range)NotInPeriodError— the period exists but the currency is absent from itFetchError— fetching fresh rates failed
Fallback is opt-in and visible:
rate = rates.monthly_rate_or_earlier("USD", month, 2)
rate.period # reveals which month was actually used
Exactness
Amounts must be decimal.Decimal or int: floats raise TypeError because they are inexact.
Results come back as decimal.Decimal, unrounded.
Apply whatever rounding your tax context requires.
Fresh rates
Updater fetches whatever HMRC has published since this release and caches the files verbatim in the system cache directory.
refreshed() performs blocking HTTP with the GIL released.
cached() never touches the network.
from hmrc_rates import FetchError, Updater
updater = Updater()
try:
rates = updater.refreshed()
except FetchError as e:
print(f"warning: possibly stale rates: {e}")
rates = updater.cached() # offline fallback is an explicit choice
New HMRC publications also trigger a new patch release of this package automatically. So pinning the latest version is an alternative to runtime fetching.
Development
cd python
uv venv && uv pip install maturin pytest
VIRTUAL_ENV=$PWD/.venv .venv/bin/maturin develop
.venv/bin/pytest
The package is a PyO3 binding built with Maturin. The Rust sources live in the repository root.
Licence
MIT.
Disclaimer
This project is not affiliated with, endorsed by, or maintained by HMRC. Only the underlying rate data comes from HMRC.
Metadata
Release files for hmrc-rates 0.3.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hmrc_rates-0.3.4.tar.gz | 694.5 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| hmrc_rates-0.3.4-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| hmrc_rates-0.3.4-cp310-abi3-musllinux_1_2_x86_64.whl | CPython 3.10 | abi3 | Linux musl 1.2+ x86-64 | Details |
| hmrc_rates-0.3.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| hmrc_rates-0.3.4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| hmrc_rates-0.3.4-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64, macOS 11.0+ ARM64, macOS 10.12+ universal2 (ARM64, x86-64) | Details |
Total release size: 9.7 MB
Release files / hmrc_rates-0.3.4.tar.gz
| Download URL | hmrc_rates-0.3.4.tar.gz |
|---|---|
| Size | 694.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3e74af496f368495ea7d8a66e0cba70f001dc8d2f0c66d40827a72c3d141cd07
|
|
BLAKE2b-256 checksum How to use checksums |
2feddaf43307fbe2d00f9e6f05f648e5b09b583e07df38b2fbbb181bcf345fa9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / hmrc_rates-0.3.4-cp310-abi3-win_amd64.whl
| Download URL | hmrc_rates-0.3.4-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
70b942b5b12f04908f4634093e706adf514185ba476ed896ff8a54c870bcbbc0
|
|
BLAKE2b-256 checksum How to use checksums |
6003b9ba97bfe841ad6e8fc038affce6be915c47edaa01eab2ecb4b452446d5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / hmrc_rates-0.3.4-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | hmrc_rates-0.3.4-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
a198842f20fe57af32d43235c0e3b142efeca8cc8e7edb57c9854a86a29a6410
|
|
BLAKE2b-256 checksum How to use checksums |
cd7d6a1bfd7c8dd1c8f0692c5ef88040854d17089c47f8ea3f20ed6fa4b56ced
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / hmrc_rates-0.3.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | hmrc_rates-0.3.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
9e7d82f0017c7e93450e04ca6d1ed3f1764c5c69f8c90933f09ea2e81224e15b
|
|
BLAKE2b-256 checksum How to use checksums |
2c5476a0acd37b3a7da4b5509f58e3379e008f6f319350c2143910487acc58fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / hmrc_rates-0.3.4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | hmrc_rates-0.3.4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
fc1bc8365d6088659fc7a7cc28906b103e8560d47fda11f631bc7403a688be60
|
|
BLAKE2b-256 checksum How to use checksums |
35a9b8984775bd9a771a076a3f98b0231136eb4c975c05ef01771e3ee9525b3b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / hmrc_rates-0.3.4-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | hmrc_rates-0.3.4-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 2.8 MB |
| Tags | CPython 3.10 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
836b77b06e634f22b19f7d396e47435eaccc54191158218fa8b4dcb756e0d870
|
|
BLAKE2b-256 checksum How to use checksums |
4397e03a286bfa8b70d9b4974466a0a856bdbeadd4c562eb03870291105074b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency log