# Spain Land & Property Cadastral Enrichment (`rodimuxai/spain-cadastral-enrichment`) Actor

Official cadastral data for Spanish addresses and plots: real surface in m², use, year, existing buildings and the cadastral reference. Listings say what the seller wants; the Cadastre says what is there. Chain it after any real-estate scraper.

- **URL**: https://apify.com/rodimuxai/spain-cadastral-enrichment.md
- **Developed by:** [RodimuxAI](https://apify.com/rodimuxai) (community)
- **Categories:** Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 property enricheds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Spain Land & Property Cadastral Enrichment

**Listings say what the seller wants. The Cadastre says what is there.**

Give this Actor a Spanish address — or a whole dataset from any real-estate scraper — and it returns the official record from Spain's Cadastre: **real surface in m², official use, year, existing constructions, and the cadastral reference**.

That reference is the point. It's the legal identity of the plot, the one you take to the Land Registry. Without it, a listing is just a claim.

```json
{
  "input": "Calle Alfonso I, 1, 50003 Zaragoza",
  "cadastralReference": "6437117XM7163E0002LK",
  "parcelReference": "6437117XM7163E",
  "surfaceM2": 7161,
  "use": "Ocio y Hosteleria",
  "yearBuilt": 2010,
  "propertyClass": "UR",
  "address": "CL ALFONSO I 1 50003 ZARAGOZA (ZARAGOZA)",
  "constructions": [
    { "use": "ALMACEN", "surfaceM2": 320, "floor": "-1" },
    { "use": "OCIO Y HOSTELERIA", "surfaceM2": 1200, "floor": "00" }
  ],
  "status": "found"
}
```

### Who this is for

- **Land scouts and developers** sourcing plots: check the surface a listing claims, before you drive out to see it.
- **Real-estate agencies and portals**: verify and normalize a whole portfolio at once.
- **Valuation, lending and insurance**: official surface, use and age, at scale.
- **Anyone running a Spanish property scraper**: this is the layer that turns listings into verified records.

### Three ways in — the third is the point

1. **Addresses** as written in a listing: `Calle Alfonso I, 1, 50003 Zaragoza`. Street type, name, number, postcode and town are parsed for you.
2. **Cadastral references** (14 or 20 characters) — exact, no parsing involved.
3. **`sourceDatasetId` of another Actor.** Run any Idealista / Fotocasa / Milanuncios scraper, paste that run's dataset ID, and addresses are read straight from it. No CSV export, no copying columns.

### Land mode: one record per parcel

A street number returns every property in the building — one per flat. With `parcelLevel` on (the default) you get **the parcel once**, which is what matters for land, and **you're charged once**. Turn it off when you want every individual unit.

### It asks the Cadastre how it spells things

Spanish addresses don't match the Cadastre's own spelling, and that's the single biggest source of failure. Before looking anything up, this Actor resolves the street against the official street index:

| A listing writes | The Cadastre stores |
|---|---|
| Calle Mariano Lagasca | `CL LAGASCA, MARIANO` — surname first |
| Calle Gran Vía (Zaragoza) | `PS GRAN VIA (RAMON Y CAJAL)` — it's a *paseo*, not a street |

That normalization alone took the hit rate from 55% to **68%**.

### Hit rate, measured — not promised

**68%** on 20 real listing-style addresses across Zaragoza, Madrid and Valencia (30 July 2026). Exact cadastral references resolve essentially always — the loss is all in address matching.

The remaining failures are almost entirely *"street exists, that number doesn't"*. **The Actor reports that instead of guessing.** It will never snap to a nearby number: a different number is a different building, and handing you the wrong plot would be worse than handing you nothing.

**You only pay for records actually delivered.** Addresses that don't resolve cost you nothing.

### Input

| Field | Default | What it does |
|---|---|---|
| `addresses` | — | Spanish addresses, as written in listings |
| `cadastralReferences` | — | Cadastral references (14 or 20 chars) |
| `sourceDatasetId` | — | Dataset ID of any real-estate scraper |
| `sourceDatasetField` | auto | Field holding the address (autodetected) |
| `province` / `municipality` | — | Force them when addresses omit the town |
| `parcelLevel` | `true` | One record per parcel instead of per unit |
| `maxItems` | 200 | Cap per run |

### Pricing

| Event | When you're charged |
|---|---|
| Property enriched | Only when the Cadastre returns an actual record |

### Limits, up front

- **No ownership data.** Owner names are protected under Spanish law and this service does not serve them. What you get is the **unprotected** cadastral data: surface, use, situation, constructions. If you need to know who owns it, this Actor is not what you want.
- **No buildability.** The Cadastre states the *current* use, not what the municipal plan allows you to build. That's the number a land scout most wants, it lives in scattered municipal planning documents, and it is not in here.
- **Rural parcels** follow a different query branch and are less reliable than urban ones in this version.
- The Cadastre's service is a free public API. This Actor caches by reference, keeps concurrency low and backs off — please don't hammer it.

### Source

Official data from the **Sede Electrónica del Catastro** (Spanish Ministry of Finance), *servicio de consulta libre* — the public, unauthenticated endpoint for unprotected cadastral data. Reuse of Spanish public-sector information is governed by Ley 37/2007.

# Actor input Schema

## `addresses` (type: `array`):

Spanish addresses to look up, as written in a listing (e.g. "Calle Alfonso I, 1, 50003 Zaragoza"). Street type, name, number, postcode and town are parsed automatically.

## `cadastralReferences` (type: `array`):

Cadastral references, 14 characters (parcel) or 20 (individual property). Faster and exact — no address parsing involved.

## `sourceDatasetId` (type: `string`):

Run ID of any real-estate scraper (Idealista, Fotocasa, Milanuncios…). Addresses are read straight from there — no CSV export, no copying columns.

## `sourceDatasetField` (type: `string`):

Field holding the address in that dataset. Leave empty to autodetect (address, direccion, location, fullAddress…).

## `province` (type: `string`):

Forces the province for every lookup. Helps when the addresses don't include the town.

## `municipality` (type: `string`):

Forces the municipality for every lookup.

## `parcelLevel` (type: `boolean`):

A street number returns every property in the building (one per flat). With this on you get the parcel once — which is what matters for land — and you are charged once. Turn it off to get every individual property.

## `maxItems` (type: `integer`):

Cap of records to deliver in this run.

## Actor input object example

```json
{
  "addresses": [
    "Calle Alfonso I, 1, 50003 Zaragoza",
    "Avenida de Navarra 24, Zaragoza"
  ],
  "cadastralReferences": [],
  "sourceDatasetId": "aBcDeFgHiJkLmNoPq",
  "sourceDatasetField": "",
  "province": "",
  "municipality": "",
  "parcelLevel": true,
  "maxItems": 5
}
```

# Actor output Schema

## `records` (type: `string`):

One record per parcel or property, with cadastralReference, surfaceM2, use, yearBuilt, constructions, province, municipality and status (found / not\_found / error).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "addresses": [
        "Calle Alfonso I, 1, 50003 Zaragoza",
        "Avenida de Navarra 24, Zaragoza"
    ],
    "maxItems": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("rodimuxai/spain-cadastral-enrichment").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "addresses": [
        "Calle Alfonso I, 1, 50003 Zaragoza",
        "Avenida de Navarra 24, Zaragoza",
    ],
    "maxItems": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("rodimuxai/spain-cadastral-enrichment").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "addresses": [
    "Calle Alfonso I, 1, 50003 Zaragoza",
    "Avenida de Navarra 24, Zaragoza"
  ],
  "maxItems": 5
}' |
apify call rodimuxai/spain-cadastral-enrichment --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=rodimuxai/spain-cadastral-enrichment",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/hzqfpMfptPDjBfZQJ/builds/hnt45jP3aBuTusoGN/openapi.json
