Spain's cadastre has a genuinely free, no-registration public API (the OVC). For a
one-off lookup it's fine. This post documents what you'll hit when you put it in
production — verified against the live service.
It's not one API, it's three ASMX services
-
By cadastral reference:
Consulta_DNPRC(OVCCallejero.asmx) -
By coordinates:
Consulta_RCCOOR(OVCCoordenadas.asmx) — with its own SRS/axis-order handling -
By address:
Consulta_DNPLOC— province/municipality by UPPERCASE NAME, not code
All XML. GET works, which is the last easy part.
The teeth
1. Required parameters even when empty. Omit Provincia (instead of sending it
empty) and you get HTTP 500 text/plain: Missing parameter: Provincia. — not XML.
And the reference parameter is RC, not RefCat.
2. Four response shapes on one endpoint. Urban single (<bico> + <lcons>
construction breakdown), rustic single (no <lcons>; location in <lorus>, crops in
<lspr>, no build year), multi-property (a 14-char reference with several units
returns <lrcdnp> — a list, different structure, you must re-query with the 20-char
ref), and business error (<lerr>). Your parser needs all four branches; with one
test reference you'll only ever see one.
3. Don't trust the HTTP status. "Reference doesn't exist" and "malformed
reference" arrive as HTTP 200 with the error inside the XML. Infra failures are
500 text/plain. Map "200 = success" and you'll ship errors as data; retry every
failure and you'll retry malformed references forever. Classify by channel: infra
(retryable) vs business (not) vs multi (it's data, not an error).
4. es-ES locale all the way down. Decimal commas (100,000000), uppercase
accented literals (LABRADÍO), default XML namespaces.
5. The reference has its own grammar. 14 chars = parcel, 20 = specific property
(last 2 are verifiable check digits — validate before calling, it catches the most
common transcription error).
6. Operationally: no SLA, undocumented rate limits. Government service: variable
latency, unannounced maintenance. Budget timeouts + backoff + your own cache. Coverage
excludes the Basque Country and Navarre (separate foral cadastres).
If you still want to DIY
Totally reasonable for low volume: pycatastro
(Python) and CatastRo (R) wrap the transport.
The fine parsing and error classification stay yours.
The shortcut
I built Predio because I'd already paid this toll: the three
inputs behind one stable JSON contract, typed errors, serve-stale cache, and an MCP
server so AI agents can call it directly. 250 free calls/month, prepaid per-call after
that. And if you're comparing options, here's an honest comparison that includes when
NOT to use it: https://prediohq.com/guias/api-catastro-comparativa/
Top comments (0)