# Spain Land Finder — Vacant Plots from Catastro (`rodimuxai/spain-land-opportunity-finder`) Actor

Find vacant building plots anywhere in Spain without knowing a single address. Sweeps an area in the official Catastro, separates empty plots from buildings, and tells you why. The list no portal has, because it is not advertised — it is deduced.

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

## Pricing

from $300.00 / 1,000 plot candidates

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 Finder — Vacant Plots from the Official Cadastre

**Find vacant building plots anywhere in Spain without knowing a single address.**

This is the list no portal has, because it isn't advertised anywhere — it's *deduced*. Draw a rectangle on the map, and this Actor enumerates every parcel inside it in Spain's official Cadastre, then separates the empty plots from the buildings and tells you why for each one.

It's exactly what a land sourcing professional does by hand, parcel by parcel, in the Cadastre viewer — except it does a whole neighbourhood while you read this.

```json
{
  "cadastralReference": "6138538XM7163G",
  "areaM2": 414,
  "lat": 41.6584, "lon": -0.8792,
  "verdict": "vacant_plot",
  "reason": "Single property, cadastral use: \"Obras de urbanización y jardineria, suelos sin edificar\".",
  "registeredUnits": 1,
  "catastroViewer": "https://www1.sedecatastro.gob.es/CYCBienInmueble/OVCListaBienes.aspx?RC1=6138538&RC2=XM7163G"
}
```

### Every candidate comes with its context — that's the part that saves you the afternoon

A vacant parcel on its own tells you nothing. What a professional actually needs to know is what surrounds it, and that's what you get:

> **414 m² · `infill`** — *Gap in a consolidated area: 96% of surrounding parcels are built, median year 1936, mostly offices.*
> **Estimated buildable: 1,931 m²** (local ratio 4.66×, from 6 samples) · 23 built neighbours

| Opportunity | What it means |
|---|---|
| `infill` | A gap in a consolidated area — 70%+ of surrounding parcels built, 5 or more of them |
| `developing` | Area still filling in: 30%+ built, other vacant parcels nearby |
| `isolated` | Little built around it. Might be a field with a cadastral reference |

**The buildable estimate is derived, and honestly labelled as such.** It is *not* the municipal planning figure — that isn't published in any uniform way across Spain. It's the median of *what the neighbours actually built* per m² of their own plot, applied to this one: "on this block, people build at 4.66× plot area". With fewer than 3 comparable neighbours it returns nothing instead of guessing.

All of it is computed from the parcels already fetched to sweep the area — no extra calls, no extra cost to you.

### What you actually do with the output

Be clear on what this is: it finds the plots. Reaching the owner is a paid, per-parcel step that no tool anywhere can do for you, because **owner data is protected by Spanish law and no public API returns it** — not this one, not any other.

What this Actor does is tell you *which* parcels are worth paying for. The workflow:

1. **Sweep the area.** You get the vacant plots, their size, soil class and context.
2. **Rule out the junk in seconds.** Every record carries two links: the **Cadastre viewer** (the parcel drawn on the plan) and the **aerial view** on Google Maps at 150 m. One look tells you whether it's a building plot or a housing estate's shared garden.
3. **Pick the ones worth money.** Big, urban, in a consolidated area, with a healthy local build ratio.
4. **Request a *nota simple*** at [registradores.org](https://www.registradores.org/) with the cadastral reference — around 10 €, online, and it gives you the registered owner.
5. **Make the call.**

Without this, step 4 costs you 10 € per parcel blind, or an afternoon in the Cadastre viewer going block by block. With it, you spend those 10 € only on plots you already know are worth it.

Every record states its status explicitly rather than leaving you to guess: plots deduced from the Cadastre come back as *"Not advertised — this is the point: nobody else is bidding for it"*, while auction lots come back `forSale: true` with a starting price and a deadline.

### Who this is for

**Land scouts, developers and brokers** who make a living finding plots to offer — or to buy and resell. If you need to know *which* parcels in a district are empty before you make a single call, this is the shortcut.

Also: municipalities auditing vacant land, solar and telecom operators looking for sites, and investors mapping a city block by block.

### How it judges

Every parcel gets a verdict, and the verdict is explained:

| Verdict | What it means |
|---|---|
| `vacant_plot` | **Candidate.** No properties registered, or a single one whose cadastral use is unbuilt land |
| `single_building` | One property, already built — the use and year are included |
| `multi_unit_building` | Two or more registered properties: it's a building. Discarded |
| `vacant_plot_too_small` | Vacant, but under your minimum size |

**This distinction is the whole product, and it is not obvious.** Our first attempt treated "the record lists no constructions" as empty — and it was wrong. The parcels that looked empty had **203, 95 and 21 registered properties**: they were apartment blocks, whose cadastral query returns a *list* of units rather than a single record. The rule that works is counting registered units.

Every record links to the **official Cadastre viewer**, so you can confirm any plot yourself in five seconds. You never have to take this Actor's word for it.

### Three ways in

1. **Sweep an area** — four coordinates from any map. ~1 km² per run works well.
2. **Specific cadastral references** — judge parcels you already have.
3. **Addresses, or the dataset of any real-estate scraper** — run an Idealista / Fotocasa / Milanuncios scraper, paste that run's dataset ID, and every advertised plot is resolved to its parcel and checked. Is that "solar" really vacant land? Now you know before you drive out.

### Pricing

| Event | When you're charged |
|---|---|
| Plot candidate | Only for a **vacant plot** delivered above your minimum size |

Buildings, undersized plots and unresolved parcels are **never charged** — sweep a thousand parcels and pay only for the handful worth calling about.

### What to expect

Vacant plots in a dense urban core are rare, and that's precisely why they're valuable. A real sweep of ~1 km² of central Zaragoza (30 parcels) returned **1 candidate of 414 m²**, 1 vacant-but-too-small, 19 apartment buildings and 9 single buildings. Sweep the outskirts, an industrial belt or a growing town and the ratio climbs sharply.

### Limits, up front

**Vacant is not the same as for sale.** The Cadastre tells you a parcel is unbuilt. It does not tell you it's on the market — and for a land scout that's the point: unadvertised plots are the ones nobody else is competing for. You take the cadastral reference to the Land Registry to find the owner.

**Some "vacant" plots are communal green space.** The cadastral use *"Obras de urbanización y jardinería, suelos sin edificar"* covers both a serviced building plot and the shared gardens of a housing estate — and the Cadastre alone can't tell them apart. That's exactly why every record carries a link to the official viewer: open it, look at the aerial photo, and rule it out in five seconds. This Actor narrows 300 parcels down to the handful worth looking at; it doesn't replace your eyes on the last step.

- **No ownership data — and nobody else has it either.** Owner names are protected under Spanish law; the Cadastre's public service does not serve them and no commercial API does. Each record tells you the official route instead: a *nota simple* from the Land Registry with the cadastral reference, ~10 € online. If you were hoping for owner names and phone numbers in a spreadsheet, no legal product can give you that.
- **"Urbanizable" is not a category you get.** Spanish planning law has three classes; the Cadastre only records two. **Urban land** (`UR`) means already serviced and buildable under the plan — that's what you get by default. Everything else comes back as **rural**, and that single bucket mixes plain farmland with *suelo urbanizable*: rural land the municipal plan intends to develop, which is where a land scout makes the biggest margins. The Cadastre cannot tell those two apart, because its purpose is fiscal, not urbanistic. Nor can any national service — see below.

  `onlyUrbanLand` is **on by default**: you get buildable plots. Turn it off for farmland, land banking or auction fincas, knowing that "rural" there means "farmland or future development, and this Actor can't say which".

  What you do **not** get is the plan's parameters — permitted height, occupancy, exact uses. Those live in each town hall's planning documents, are not published uniformly anywhere in Spain, and there is no national service for them: the Ministry's SIU is closed to automated access and no national INSPIRE planned-land-use service exists. In their place you get the derived local build ratio above — what the neighbours actually built.
- **No price.** Vacant plots deduced from the Cadastre aren't for sale by definition — nobody advertised them. Price only comes with input mode 3, from the listing.
- The Cadastre is a free public service. This Actor caches per reference, keeps concurrency low, and warns you when your area is too big to sweep in one go. Please keep it that way.

### Source

**Sede Electrónica del Catastro** (Spanish Ministry of Finance): INSPIRE parcel service for enumeration, *servicio de consulta libre* for each parcel record. Public, unauthenticated, unprotected data. Reuse of Spanish public-sector information is governed by Ley 37/2007.

# Actor input Schema

## `area` (type: `string`):

Three ways, whichever is easiest: (1) paste a Google Maps link of the spot, (2) a point as "lat, lon", or (3) an exact rectangle as "south, west, north, east". With a link or a point, the search covers a square around it — see radius below.

## `radiusM` (type: `integer`):

Only used with a map link or a point: half the side of the square searched around it. 500 m covers a neighbourhood; 1000 m a small town centre.

## `auctionsLastNDays` (type: `integer`):

Scan the official BOE gazette for public property auctions announced in the last N days. These are the only plots that come with a PRICE and a DEADLINE. 0 = skip auctions. 30 covers a month of announcements across all of Spain.

## `onlyUrbanLand` (type: `boolean`):

On by default, because it's what almost everyone wants: keep only plots the Cadastre classifies as URBAN land — already serviced, buildable under the municipal plan. Turn it OFF to also get rural land (farmland, land banking, auction fincas). Careful: the Cadastre does NOT distinguish 'urbanizable' (rural land the plan intends to develop) from plain farmland — both come back as rural.

## `minSurfaceM2` (type: `integer`):

Vacant plots smaller than this are not worth a call, so they are not delivered or charged.

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

Judge specific parcels instead of sweeping an area.

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

Addresses of plots advertised on a portal. Each one is resolved to its parcel and judged: is it really vacant land?

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

Run any Idealista / Fotocasa / Milanuncios scraper and paste that run's dataset ID: the addresses are read straight from it and checked against the Cadastre.

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

Field holding the address in that dataset. Empty = autodetected.

## `includeDiscarded` (type: `boolean`):

Include the buildings and undersized plots that were ruled out, with the reason. Useful to audit the sweep. Discarded parcels are never charged.

## `maxParcels` (type: `integer`):

Cap on parcels enumerated per area. The Cadastre is a free public service — keep it reasonable.

## Actor input object example

```json
{
  "area": "https://www.google.com/maps/@41.6560,-0.8800,16z",
  "radiusM": 500,
  "auctionsLastNDays": 7,
  "onlyUrbanLand": true,
  "minSurfaceM2": 200,
  "cadastralReferences": [],
  "addresses": [],
  "sourceDatasetId": "aBcDeFgHiJkLmNoPq",
  "sourceDatasetField": "",
  "includeDiscarded": false,
  "maxParcels": 40
}
```

# Actor output Schema

## `plots` (type: `string`):

One record per parcel, with cadastralReference, areaM2, lat/lon, verdict, reason and catastroViewer.

# 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 = {
    "area": "https://www.google.com/maps/@41.6560,-0.8800,16z",
    "auctionsLastNDays": 7,
    "maxParcels": 40
};

// Run the Actor and wait for it to finish
const run = await client.actor("rodimuxai/spain-land-opportunity-finder").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 = {
    "area": "https://www.google.com/maps/@41.6560,-0.8800,16z",
    "auctionsLastNDays": 7,
    "maxParcels": 40,
}

# Run the Actor and wait for it to finish
run = client.actor("rodimuxai/spain-land-opportunity-finder").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 '{
  "area": "https://www.google.com/maps/@41.6560,-0.8800,16z",
  "auctionsLastNDays": 7,
  "maxParcels": 40
}' |
apify call rodimuxai/spain-land-opportunity-finder --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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