# UK Land Data API - Parcels, Planning, Titles, Owners (`nabeelbaghoor/uk-land-planning-data-api`) Actor

UK land and planning data: search land parcels in any local authority by size and tenure, read the HM Land Registry titles and registered owners behind them, the planning applications on them, the properties inside them, and the flood, green belt, heritage and allocation layers that cover them.

- **URL**: https://apify.com/nabeelbaghoor/uk-land-planning-data-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Real estate, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $18.00 / 1,000 land parcel returneds

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## UK Land Data API - Parcels, Planning, Titles and Owners

Find a UK development site, then find out who owns it, what has been applied for on it, and what stops you building on it.

### What it collects

- **Land parcels** by local authority, filtered on size in square metres and on freehold or leasehold tenure, with the ratio of each parcel that is already developed.
- **Ownership** from HM Land Registry: title number, tenure, registered addresses, registered proprietors with company numbers and countries, and the ultimate owner behind a holding company.
- **Planning applications** at a point or inside a polygon: the authority's reference, the proposal, the number of residential units, the authority's own status and the derived status side by side, the decision and its date, the applicant and the agent, and the link to the authority's page.
- **Properties** by UPRN: full address, property type and state, Ordnance Survey classification, planning use class, building height and roof height in metres, estimated floor count, and current and potential EPC ratings with certified floor area.
- **Site designations**: flood zones, green belt, conservation areas, listed buildings, airport and rail safeguarding, rights of way, agricultural land classification, regeneration areas, brownfield register entries, land availability assessments, Homes England sites, power infrastructure, strategic industrial locations and renewable energy sites.
- **Coverage fractions** on every constraint and policy, so a flood zone clipping one corner of a site never reads the same as one covering all of it.

### FAQ

#### What data does this UK land API return?

Land parcels with size and developed-area ratio, HM Land Registry title numbers and registered owners, planning applications with status and decision, properties with UPRN, height and EPC data, and the planning constraint, allocation and opportunity layers covering a site. Coverage is England, Wales and Scotland by local authority, addressed through Office for National Statistics GSS codes.

#### How do I find out who owns a piece of land in the UK?

Search parcels in the local authority, read the parcel's details to get its HM Land Registry title numbers, then run title details on those numbers. Each title returns its registered proprietors, their company numbers and countries of registration, the date ownership last changed, and the ultimate owner where the registered proprietor is a holding company.

#### Can I search planning applications by location?

Yes. Planning search takes a latitude and longitude pair or a GeoJSON polygon and returns every planning application the provider holds for that area, grouped by planning authority. Each application carries its reference, proposal description, unit count, status, decision and dates. Give the pair as latitude first; the actor converts it to the longitude-first order the API expects, so a swapped pair cannot quietly return a real place somewhere else.

#### What is a GSS code and where do I get one?

A GSS code is the Office for National Statistics identifier for a UK local authority, written as one letter and eight digits, such as E06000023 for Bristol. Run the list regions mode to get every code this API accepts along with the authority name.

#### Do searches return full records?

Searches on this API return identifiers rather than records: up to 100,000 parcel IDs, or planning references grouped by authority. This actor reads the full record behind each identifier by default, and applies your row cap before the lookups so a search returning thousands of identifiers does not spend thousands of calls filling a small run. Turn hydration off to collect identifiers only.

#### Why is the full boundary missing from my rows?

Geometry is off by default, because a multipolygon in a spreadsheet cell is size without use. Every row already carries a centre point. Turn on full geometry to get the GeoJSON ring, which also switches the site feature modes from the provider's geometry-free endpoint to its full one.

#### Do I need my own API key?

Yes. This actor is bring-your-own-key: it calls the provider with your own account credentials and never ships a key of its own. Paste the key on its own rather than a whole header line. The account status mode checks the key works, and tells apart a key the provider does not recognise from a key it does recognise on a subscription that has expired or been blocked.

#### What does it cost?

Pay per result. Parcels and titles are the richest rows and cost the most; parcel identifiers and planning references cost a fraction of a hydrated record; the region catalogue and the account status check are priced near zero so you can run them before committing to a large job. Platform usage is included. Rows for identifiers the provider has no record for are never charged.

### Example output

```json
{
  "recordType": "parcel",
  "requested": "E06000023",
  "found": true,
  "parcelId": "1a2b3c4d5e6f",
  "parcelSizeSqm": 18336.97,
  "developedAreaRatio": 0.2865,
  "titleNumbers": ["K375897", "TT17693"],
  "titleCount": 2,
  "uprns": ["50121170", "50100934"],
  "intersectingUprns": ["10091868676"],
  "planningApplicationIds": ["E07000112+Y18/1381/FH"],
  "planningApplicationCount": 1,
  "developmentConstraints": "flood_zone_2 (34%); rail_safeguarded_land (100%)",
  "developmentOpportunities": "brownfield_register (54%)",
  "localPlanPolicies": "local_planning_authority (100%); settlement_boundaries (54%)",
  "latitude": 51.454514,
  "longitude": -2.58791
}
```

### Keyword map

UK land data API, land registry ownership API, land parcel search API, planning application API, UK planning data API, site sourcing API, land assembly data, freehold leasehold title lookup, UPRN property lookup API, EPC data API, green belt flood zone constraints API, SHLAA land availability data, brownfield register API, development opportunity data, GSS code local authority search.

### Notes

Bring your own key. Read only: every route this actor calls reads data, so a scheduled run cannot change anything in your provider account. Rate limiting, retries and per-endpoint batch ceilings are handled for you, and a missing or refused key ends the run cleanly with an explanation rather than failing it.

# Actor input Schema

## `mode` (type: `string`):

Parcel search finds land parcels in one local authority by size and tenure. Advanced parcel search runs the provider's own filter language. Parcel details reads everything known about a parcel ID. Planning search finds applications around a point or inside a polygon, and planning details reads one application. Title details reads a registered title and its owners. Property details reads one UPRN. Site features reads constraints, allocations, land availability assessments and the other designation layers.

## `regions` (type: `array`):

One local authority GSS code per line, for parcel search. A GSS code looks like E06000023 and is the Office for National Statistics identifier for the authority. Run the list regions mode if you need the codes.

## `identifiers` (type: `array`):

One identifier per line, for the detail modes: a parcel ID, a planning application ID such as E07000112+Y18/1381/FH, an HM Land Registry title number such as SGL235730, a UPRN such as 100023523019, or a site feature ID depending on the mode.

## `locations` (type: `array`):

One location per line for planning search, either a "latitude,longitude" pair or a GeoJSON polygon. Latitude comes first in the pair, and the actor converts it to the longitude-first order this API expects, so a swapped pair cannot quietly return a real place somewhere else.

## `minParcelSizeSqm` (type: `integer`):

Only return parcels at least this large, in square metres. One hectare is 10000 square metres. Leave empty for no lower bound.

## `maxParcelSizeSqm` (type: `integer`):

Only return parcels no larger than this, in square metres. Leave empty for no upper bound.

## `tenure` (type: `array`):

Which tenures to include in parcel search. The provider defaults to freehold only when this is left empty, so pick leasehold explicitly if you want leasehold interests.

## `advancedSearchFilter` (type: `string`):

The provider's own search\_filter object, as JSON, for advanced parcel search. For example {"ALL":\[{"parcel\_size":{"min":10000}},{"ownership\_type":{"values":\["company"]}}]}. The provider marks this endpoint beta and changes its filters, so it is passed through as written rather than rebuilt from form fields.

## `featureCollection` (type: `string`):

Which designation layer the site features mode reads. Development constraints covers flood zones, green belt, conservation areas, listed buildings, safeguarding and rights of way. Land availability assessments are the local authority's own SHLAA sites.

## `hydrateSearchResults` (type: `boolean`):

Searches on this API return identifiers rather than records. Leave this on to read the full record behind each identifier, which is what most runs want. Turn it off to collect identifiers only, which is far cheaper when you plan to filter the list before looking anything up.

## `includeGeometry` (type: `boolean`):

Adds the full GeoJSON boundary to each row. Off by default because a multipolygon makes a spreadsheet cell enormous without making it useful, and every row already carries a centre point. For site features this also switches to the provider's full endpoint rather than its geometry-free one.

## `maxResults` (type: `integer`):

Stop after this many rows. Counts every row: parcels, planning applications, titles, properties, site features and regions alike. When search results are hydrated, the cap is applied before the lookups so a search returning thousands of identifiers does not spend thousands of calls to fill a small run.

## `requestsPerMinute` (type: `integer`):

How fast to call the provider. The default of 120 is two a second, which is polite for a metered API. Raise it if your contract allows more.

## `apiKey` (type: `string`):

Your own account key, issued by the provider. Sent in an X-API-Key header. Paste the key on its own rather than a whole header line or a bearer token. Stored encrypted and never written into the dataset. Can also be supplied as the DATA\_API\_KEY environment secret.

## `baseUrl` (type: `string`):

Overrides the host the API is called on. Leave empty unless the provider has given you a different one.

## Actor input object example

```json
{
  "mode": "parcelSearch",
  "featureCollection": "developmentConstraints",
  "hydrateSearchResults": true,
  "includeGeometry": false,
  "maxResults": 100,
  "requestsPerMinute": 120
}
```

# Actor output Schema

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

One row per record, alongside the region, identifier or location that produced it.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/uk-land-planning-data-api").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/uk-land-planning-data-api").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call nabeelbaghoor/uk-land-planning-data-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/uk-land-planning-data-api"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/eK9V1ohr98qLmcjb8/builds/TIe3umv4bpHtEgndg/openapi.json
