Open-source calculators for the two Portuguese vehicle taxes, plus a tiny key-free HTTP API and installable packages for Python, JavaScript/TypeScript and PHP:
- ISV — Imposto Sobre Veículos, the one-off import/registration tax (Tabela A/B/C/D, motorhomes, motorcycles).
- IUC — Imposto Único de Circulação, the annual road tax (Categoria A / B / C / D / E).
Maintained by Clara Cars and used in production behind the public API at https://claracars.pt/api/public and the Clara Cars MCP server.
A maintained estimate, cross-checked against the official AT simulator; not the official AT figure. These are a maintained estimate, cross-checked periodically against the official Autoridade Tributária (AT) simulator and public tax tables — not the official AT number and not a substitute for the AT simulator or a licensed despachante. Tax tables change; verify before you rely on a euro amount.
| Tax | Categories | Basis |
|---|---|---|
| ISV | Tabela A (passenger), B (light commercial / mixed), C (motorcycles), autocaravanas, pesados (não sujeito) | cc + CO₂ (WLTP/NEDC), age reduction (Tabela D), diesel surcharge, PHEV reduction, €100 minimum |
| IUC | A (<2007), B (≥2007), E (motorcycles), C / D (goods vehicles, incl. ≥12 t) | cc + CO₂ for cars; gross weight × axles × suspension × year for goods vehicles |
Electric vehicles return 0.0 / exempt: True for both.
pip install portugal-vehicle-tax # Python — native, offline, zero deps
npm install portugal-vehicle-tax # JS/TS — API client
composer require claracars/portugal-vehicle-tax # PHP — API clientThe clients live in this repo: clients/js and clients/php.
The Python package mirrors src/. The JS and PHP packages are thin, honest clients of
the public API (they don't re-implement the tax math — one source of truth).
src/isv.py and src/iuc.py are pure Python (stdlib only) — copy them in or import:
from src import isv, iuc
# 2016 diesel, 1950 cc, 130 g/km CO2, used EU import
isv_result = isv.compute_isv("passenger", cc=1950, co2=130, fuel="diesel",
age_years=10.2, year=2016, from_eu=True, used=True)
# {'isv': 1832.92, 'exempt': False, 'table': 'A', ...}
iuc_result = iuc.compute(cc=1950, co2=130, fuel="diesel", year=2016)
# {'iuc': 278.85, 'category': 'B', 'taxa_cilindrada': 127.35, 'taxa_co2': 97.63, ...}
# Goods vehicle (Categoria C/D — by gross weight, not cc/CO2)
iuc.compute_iuc("pesados_mercadorias", 0, 0, "diesel", 2019, peso_bruto=18000, axles=2)pip install -r requirements.txt
uvicorn app:app --port 8080# ISV + IUC in one call
curl "http://localhost:8080/isv?cc=1950&co2=130&fuel=diesel&year=2016"The hosted instance (same contract) is live and key-free:
curl "https://claracars.pt/api/public/isv?cc=1950&co2=130&fuel=diesel&year=2016"Full request/response schema: openapi.yaml. Interactive docs at /docs when you run the app.
| Param | Type | Default | Notes |
|---|---|---|---|
cc |
int | 0 | Engine displacement (cm³) |
co2 |
int | 0 | CO₂ g/km (WLTP/NEDC handled by registration year) |
fuel |
string | petrol |
petrol | diesel | electric | phev | hybrid | lpg |
year |
int | — | First-registration year (drives age reduction + NEDC/WLTP + IUC categoria) |
month |
int | 6 | First-registration month |
from_eu |
bool | true | EU import (affects age-reduction eligibility) |
range_km |
int | 0 | Electric range — a PHEV needs ≥50 km (+ low CO₂) for the 75% reduction |
used |
bool | true | false (novo) → no age reduction |
vehicle_type |
string | passenger |
passenger | van_10 | commercial_15/50/100 | motorcycle | autocaravana | pesados_mercadorias | pesados_passageiros |
particulas |
bool | true | Diesel particle surcharge (≥0.001 g/km) |
/iuc takes cc, co2, fuel, year, vehicle_type.
pytest -q # or: python tests/test_calc_golden.pytests/test_calc_golden.py freezes a golden case table (petrol, diesel with age reduction,
electric-exempt, the €100 minimum, PHEV reduction, Categoria C/D goods vehicle) so any drift in
the tables fails. tests/test_smoke.py covers the calculators + the reference API.
- No auth, no keys, no PII, no state — vehicle params in, numbers out.
- Deterministic → the reference API caches by param hash and sends
Cache-Control. - Abuse-bounded → generous per-IP rate limit (default 60/min →
429+Retry-After), wildcard CORS (safe: no cookies/PII). Env-tunable:CALC_RATE_MAX,CALC_RATE_WIN,CALC_CACHE_TTL. - Every response carries a
sourceattribution link back to claracars.pt.
- Hosted API + docs: https://claracars.pt/en/api
- MCP server: claracarspt/mcp — AI assistants call these calculators + live stock over the Model Context Protocol.
- WordPress plugin: Clara Cars ISV & IUC Calculator (embeds the widget).
Tax tables change every year. PRs that update a bracket/coefficient with a link to the official AT source are very welcome. pytest -q runs the (dependency-free) calculator tests.
MIT © Clara Cars
