catastrogps
Official Python client for the Catastro GPS API: cadastral parcels in 29 European countries plus the Basque Country and Navarre (31 country and region codes) with one API key.
- Look up a parcel by its official cadastral reference or by coordinates, with the country detected for you.
- Turn a Spanish postal address in free text into a cadastral reference.
- Get the parcel outline (GeoJSON or a
[lat, lng]ring), and KML / GPX / DXF exports. - Solar (PVGIS) and agricultural context for parcels in Spain, Portugal, France, Italy and Germany.
- One dependency (
httpx), typed, Python 3.9+.
Free tier: 250 calls a month, forever. Failed lookups are not charged. Get a key at parcelgps.com/developers.
Install
pip install catastrogps
Quick start
from catastrogps import CatastroGPS
client = CatastroGPS("pk_live_your_key_here")
parcel = client.parcels.get("9872023VH5797S0001WX")
print(parcel["municipio"], parcel.get("superficieParcela"), parcel["latitud"], parcel["longitud"])
CatastroGPS() with no arguments reads CATASTROGPS_API_KEY from the environment. Use it as a context manager to close the connection pool:
with CatastroGPS() as client:
...
Examples
match = client.parcels.find_by_address("Calle Mallorca 213, Barcelona")
match["referenciaCatastral"]
in_warsaw = client.parcels.at_point(52.2297, 21.0122)
in_warsaw["referenciaCatastral"], in_warsaw.get("pais")
foral = client.parcels.get("<Navarre reference>", country="NA")
outline = client.parcels.geometry("9872023VH5797S", country="ES")
outline.get("geojson")
solar = client.parcels.solar("9872023VH5797S0001WX")
solar["kwh_year"]
kml_bytes = client.export.file("9872023VH5797S0001WX", "kml")
guess = client.resolve("05102200100005")
guess["candidates"]
client.last_quota
client.last_quota is the monthly quota of your plan as of the last response: {"plan", "limit", "remaining", "resets_at"}, read from the X-Quota-Tier, X-Quota-Limit, X-Quota-Remaining and X-Quota-Reset headers. The X-RateLimit-* headers are a different thing: a per-key burst limit per minute that depends on your plan (Free 10, Developer 60, Startup 120, Growth 300; a global per-IP guard also applies) that the client handles by retrying.
Responses are the API's data object as a dict, with the field names the API uses (refCatastral, municipio, superficieParcela…). See the API reference.
Importar una comunidad de propietarios (Spain)
Address → finca (14-character reference) → every unit, with use, area, participation coefficient, stair, floor and door.
from catastrogps import CatastroGPS, CoverageError
client = CatastroGPS()
found = client.search_address_candidates("Avenida José Rodríguez de la Borbolla Camoyán 10, Dos Hermanas")
finca = found["candidatos"][0]
finca["refCatastral"], finca["confianza"], finca["pais"]
comunidad = client.get_units(finca["refCatastral"])
comunidad["totalUnidadesFinca"]
for u in comunidad["unidades"]:
print(u["refCatastral"], u["uso"], u["superficie"], u.get("participacion"), u["escalera"], u["planta"], u["puerta"])
comunidad["dataSource"], comunidad["dataDate"], comunidad["attribution"]
refreshed = client.get_units(finca["refCatastral"], previous=comunidad)
refreshed["changed"]
search_address_candidatesalso takesstreet=,number=,municipality=,postcode=,limit=. Candidates come ranked byconfianza(0.75 or more: number and municipality match). It costs 1 quota unit.get_unitsfollowsnextCursorfor you (200 units per page) and costs one quota unit per 50 units, minimum one per page.iter_unit_pages(ref)yields page by page.- Pass the previous result as
previous=to re-import: pages that did not change come back as304 Not Modified, cost nothing, and are reused;changedtells you if anything moved. - Fincas in the Basque Country or Navarra (
paisPVorNA) raiseCoverageError: their foral cadastres are not served per finca. - A
ServiceUnavailableErrorcarriesretry_after; the client already waits for it (up to 60 s) before its retries.
Errors
Every error is a CatastroGPSError with status, code and details:
from catastrogps import AmbiguousReferenceError, CoverageError, NotFoundError, QuotaExceededError
try:
client.parcels.get("05102200100005")
except AmbiguousReferenceError as error:
first = error.candidates[0]["country"]
client.parcels.get("05102200100005", country=first)
except (NotFoundError, CoverageError) as error:
print(error.message)
except QuotaExceededError:
print("Monthly quota used up")
Also available: AuthenticationError, ValidationError, RateLimitError, ServiceUnavailableError, ServerError, TimeoutError, NetworkError.
Timeouts, network errors, 429 rate limits and 502/503/504 are retried up to max_retries times (default 2) with exponential backoff. An exhausted monthly quota is never retried. Only 2xx responses spend quota; failed attempts and 304 Not Modified are free.
Options
| Argument | Default | |
|---|---|---|
api_key |
CATASTROGPS_API_KEY |
Required |
base_url |
https://api.catastrogps.es |
|
timeout |
30.0 seconds |
Official cadastres can be slow |
max_retries |
2 |
|
http_client |
new httpx.Client |
Bring your own (proxies, tests with httpx.MockTransport) |
Coverage
| Code | Country / region | Reference | Coordinates | Notes |
|---|---|---|---|---|
ES |
Spain | ✅ | ✅ | Free-text address search |
PV · NA |
Basque Country · Navarre | ✅ | ✅ | Foral cadastres |
PT |
Portugal | Partial | ✅ | Digital cadastre is partial |
FR · IT |
France · Italy | ✅ | ✅ | |
DE |
Germany | Partial | Partial | All Länder except Bavaria |
AT CH LI BE NL LU |
Austria, Switzerland, Liechtenstein, Belgium, Netherlands, Luxembourg | ✅ | ✅ | |
PL CZ SK SI HR BG GR CY |
Poland, Czechia, Slovakia, Slovenia, Croatia, Bulgaria, Greece, Cyprus | ✅ | ✅ | |
DK NO FI IS EE LV LT IE |
Denmark, Norway, Finland, Iceland, Estonia, Latvia, Lithuania, Ireland | ✅ | ✅ | |
SE |
Sweden | ✅ | ✅ | Agricultural blocks, not property units |
UK |
United Kingdom | — | Scotland | England, Wales and Northern Ireland not yet |
Geometry is available wherever a reference works. Solar and agriculture: ES, PV, NA, PT, FR, IT, DE. Data comes live from each official source, so availability follows theirs.
Pricing
| Plan | Price | Calls / month |
|---|---|---|
| Free | €0, forever | 100 |
| Developer | €19 / month | 5,000 |
| Startup | €49 / month | 15,000 |
| Growth | €99 / month | 50,000 |
The same key works with the JavaScript SDK (npm install catastrogps) and the MCP server for AI agents (catastro-gps-mcp).
License
MIT
Metadata
Release files for catastrogps 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| catastrogps-1.2.0.tar.gz | 14.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| catastrogps-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.6 kB
Release files / catastrogps-1.2.0.tar.gz
| Download URL | catastrogps-1.2.0.tar.gz |
|---|---|
| Size | 14.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8dc1363b1ecb757fac0d71788e8b34fd21302e8acc869125fa9384d664a295e7
|
|
BLAKE2b-256 checksum How to use checksums |
a8d5e72300bdd497c58021c8aa52e99ff03ab3813c71f5d26a9e108f9252e53d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / catastrogps-1.2.0-py3-none-any.whl
| Download URL | catastrogps-1.2.0-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc852b66946c4c6c8501514ceff0111032b4ee75dead309a153ae0990ab14f7a
|
|
BLAKE2b-256 checksum How to use checksums |
c4e16df79a7fed431662a7f0fccec7f1dc8e0bda86cb2ec43e27c2c0ce414769
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|