# UK Planning Constraints: Conservation Area, Listed, Article 4 (`ukdatakit/uk-planning-constraints`) Actor

Bulk-check postcodes or coordinates in England for conservation areas, listed buildings, Article 4, TPOs, flood zone 2/3, green belt, national parks, AONB, SSSI and more. Official planning.data.gov.uk (OGL) data, coverage flags, nearby listed buildings.

- **URL**: https://apify.com/ukdatakit/uk-planning-constraints.md
- **Developed by:** [Christopher Brown](https://apify.com/ukdatakit) (community)
- **Categories:** Real estate, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 location checkeds

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 Planning Constraints Checker – Conservation Area, Listed Building, Article 4, TPO, Flood Zone

Paste in a list of **postcodes or coordinates in England** and get back a clear yes/no for every main planning constraint at each one: **conservation area, listed building, Article 4 direction, Tree Preservation Order, flood zone 2/3, green belt, national park, National Landscape (AONB), SSSI, scheduled monument, World Heritage Site** and more. Each row also lists the **listed buildings nearby with their grade and distance**, a plain-English note on what each constraint means, and a link to the official map.

Everything comes from the government's official **planning.data.gov.uk** (MHCLG) API, published under the Open Government Licence. No API key, no login, no scraping.

### Who uses this

- **Property investors, sourcers and buy-to-let landlords** – screen a deal list before you view: is it in a conservation area, under an Article 4 HMO direction, or in flood zone 3?
- **Estate agents and conveyancers** – flag listed status and conservation areas early, before the searches come back.
- **Architects, builders and extension firms** – know whether permitted development is likely to apply before you quote.
- **Tree surgeons** – check for conservation areas and protected trees before you start work.
- **PropTech and data teams** – add constraint columns to a whole portfolio on a schedule.

### What you get per location

| Column | Example |
|---|---|
| `inConservationArea` / `conservationAreaNames` | `true` / `Bath` |
| `inListedBuilding` / `listedBuildingNames` | Is the point inside a mapped listed-building outline |
| `listedBuildingsNearby` | `Grand Pump Room (grade I, 8 m); King's Bath (grade I, 20 m); …` |
| `nearestListedBuildingMetres` | `8` |
| `inArticle4` / `article4Names` | `true` / `HMO` |
| `inTreePreservation`, `protectedTreesWithinRadius` | TPO areas at the point and protected trees nearby |
| `floodZone`, `inFloodZone2or3` | `Flood Zone 3`, `true` |
| `inGreenBelt`, `inNationalPark`, `inNationalLandscape`, `inSssi`, `inScheduledMonument`, `inWorldHeritageSite`, `inRegisteredParkAndGarden`, `inRegisteredBattlefield` | yes/no columns with names |
| Optional extras | ancient woodland, heritage coast, SAC, SPA, Ramsar, national and local nature reserves, brownfield land register, heritage at risk |
| `conservationAreaCoverage`, `article4Coverage`, `treePreservationCoverage` | Whether the council publishes that layer at all (see below) |
| `whatItMeans` | One plain-English line per constraint found |
| `summary` | One sentence for the whole location |
| `localAuthority`, `localPlanningAuthority` | `Chichester`, `South Downs National Park LPA` |
| `planningDataMapUrl`, `sourceEntities` | Link to the official map and the source records |

### The "honest blank" – why coverage columns matter

Conservation areas, Article 4 directions and TPOs are published by each council, and **not every council has published them yet**. Most tools just say "no" when the data is missing. This one checks whether the council (and the national park authority, where there is one) has published each layer at all:

- `found` – the constraint applies here.
- `council publishes this data – none at this point` – a real "no".
- `not published by council – unknown` – **"no" here means "we don't know"**; ask the council. A matching line is added to `coverageWarnings`.

If a listed building sits within 15 m but no outline is mapped, you also get a warning to check whether the property itself is listed.

### Input

| Field | Default | Notes |
|---|---|---|
| Locations | `BA1 1LZ`, `53.9580,-1.0790`, `GU29 0BP` | Postcodes, `latitude,longitude` strings, or objects like `{"latitude": 51.50, "longitude": -0.14, "label": "Site A"}` |
| Listed building radius (m) | `50` | 0–500. Lists nearby listed buildings and protected trees. |
| Include extra designations | `true` | Ancient woodland, nature sites, brownfield, heritage at risk. |
| Include ended designations | `false` | Include records with an end date. |
| Max locations | `1000` | Safety cap per run. |

```json
{"locations": ["BA1 1LZ", "53.9580,-1.0790", {"postcode": "GU29 0BP", "label": "Midhurst farm"}], "listedBuildingRadius": 50}
```

### Example output (one record, trimmed)

```json
{
  "input": "53.9580,-1.0790",
  "status": "checked",
  "localAuthority": "York",
  "inConservationArea": true,
  "conservationAreaNames": "Central Historic Core Conservation Area",
  "inArticle4": true,
  "article4Names": "HMO",
  "floodZone": "Flood Zone 3",
  "inFloodZone2or3": true,
  "listedBuildingsWithinRadius": 5,
  "nearestListedBuildingMetres": 18,
  "listedBuildingsNearby": "Merchant Adventurers Hall (grade I, 18 m); Gatehouse To Merchant Adventurers Hall (grade II*, 31 m); …",
  "treePreservationCoverage": "not published by council – unknown",
  "constraintsFound": ["Conservation area", "Article 4 direction", "Flood Zone 3"],
  "whatItMeans": ["Conservation area: Extra controls on demolition, some extensions, cladding and satellite dishes; give the council 6 weeks' notice before most tree work.", "…"],
  "summary": "Found: Conservation area, Article 4 direction, Flood Zone 3. Not published by the council, so 'no' means unknown: Tree Preservation Order area.",
  "planningDataMapUrl": "https://www.planning.data.gov.uk/map/#53.958,-1.079,17z"
}
```

Full sample rows are in `samples/sample_output.json`.

### Pricing

**$0.005 per location checked** (pay per event). Invalid inputs, unknown postcodes and locations outside England are returned with a reason and **not charged**. About 200 locations take under a minute.

### Good to know

- **England only.** planning.data.gov.uk does not cover Wales, Scotland or Northern Ireland; those rows come back as `outside-england`, free.
- **Postcodes are checked at their centre point.** A postcode can cover several streets, so for a single property use its coordinates.
- **Flood zones** are the Environment Agency's planning flood zones (rivers and sea) as published on planning.data.gov.uk – not surface water risk and not an insurance rating.
- **Not legal advice and not a substitute for official local authority searches (CON29/LLC1).** Data can lag council decisions. Always confirm with the council before buying or building.

### FAQ

**Does "no" mean there is no constraint?** Only when the coverage column says the council publishes that layer. Otherwise treat it as unknown.
**Can I run it on a schedule?** Yes – use Apify Schedules and the Excel/CSV/JSON export or the API.
**Why are some listed buildings not "on the point"?** Historic England publishes most listed buildings as points, not outlines, which is why we also list everything within your chosen radius.

### Data sources and licence

- Contains public sector information from planning.data.gov.uk (MHCLG) licensed under the Open Government Licence v3.0. © Crown copyright and database right 2026.
- Postcode locations via postcodes.io: contains OS data © Crown copyright and database right 2026; contains Royal Mail data © Royal Mail copyright and database right 2026; source: Office for National Statistics licensed under the Open Government Licence v3.0.

Built by [ukdatakit](https://ukdatakit.com) – more UK open-data tools: UK House Prices, UK Visa Sponsor Register, Companies House ID Verification Checker.

# Changelog

This Actor's version history is a separate document: https://apify.com/ukdatakit/uk-planning-constraints/changelog.md

# Actor input Schema

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

One per line. A full postcode (e.g. BA1 1LZ) or latitude,longitude (e.g. 53.9580,-1.0790). Coordinates are more precise: a postcode is checked at its centre point. England only.

## `listedBuildingRadius` (type: `integer`):

Also list listed buildings and individually protected trees within this distance. 0 turns it off. Max 500.

## `includeExtraDesignations` (type: `boolean`):

Also check ancient woodland, heritage coast, SAC, SPA, Ramsar, nature reserves, brownfield register and Heritage at Risk.

## `includeEndedDesignations` (type: `boolean`):

Include designations that have an end date (revoked or superseded). Off by default.

## `maxLocations` (type: `integer`):

Safety cap on locations per run.

## Actor input object example

```json
{
  "locations": [
    "BA1 1LZ",
    "53.9580,-1.0790",
    "GU29 0BP"
  ],
  "listedBuildingRadius": 50,
  "includeExtraDesignations": true,
  "includeEndedDesignations": false,
  "maxLocations": 1000
}
```

# Actor output Schema

## `results` (type: `string`):

One row per location with yes/no columns for each designation, names, coverage flags and plain-English notes.

# 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 = {
    "locations": [
        "BA1 1LZ",
        "53.9580,-1.0790",
        "GU29 0BP"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ukdatakit/uk-planning-constraints").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 = { "locations": [
        "BA1 1LZ",
        "53.9580,-1.0790",
        "GU29 0BP",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("ukdatakit/uk-planning-constraints").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 '{
  "locations": [
    "BA1 1LZ",
    "53.9580,-1.0790",
    "GU29 0BP"
  ]
}' |
apify call ukdatakit/uk-planning-constraints --silent --output-dataset

```

## MCP server setup

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

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/xD7eanehmrunullKa/builds/xs2tXzYaMe5KTjHgN/openapi.json
