# UK Planning Applications Scraper (`automation-lab/uk-planning-applications`) Actor

Search and export official planning.data.gov.uk planning applications with council identifiers, proposals, dates, decisions, geometry, and provenance.

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

## Pricing

from $4.80 / 1,000 item extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## UK Planning Applications Scraper

Search and export **UK planning applications** from the official
[planning.data.gov.uk](https://www.planning.data.gov.uk/) planning-application
dataset.

The Actor turns the government API into integration-ready dataset rows with the
council/source organisation identifier, application reference, proposal, site
address, dates, decision, available coordinates or geometry, documentation URL,
and stable source provenance.

It is designed for repeatable development monitoring and property research.
It does not infer fields that the official source has not published.

### What can you do with this Actor?

- Export a bounded sample of official planning applications for analysis.
- Filter by council/source organisation entity ID.
- Look up exact application references or Planning Data entity IDs.
- Search by a postcode or UPRN supported by the official API.
- Find applications submitted or source-updated since a date.
- Filter returned proposals by required keywords.
- Filter by published decision values such as `Approve` or `Refuse`.
- Search within a WKT point, polygon, or multipolygon.
- Schedule runs and compare stable entity IDs or source entry dates downstream.
- Send normalized records to spreadsheets, databases, webhooks, or data lakes.

### Who is it for?

#### Property and development analysts

Build a reproducible feed of proposals, dates, decisions, locations, and source
links for a chosen council or area.

#### Construction and planning teams

Search proposal language for supported project terms, then inspect each
published council record through `documentationUrl`.

#### Researchers and journalists

Export official identifiers and provenance alongside the application facts used
in an analysis.

#### Data engineers

Schedule a small `updatedSince` query, ingest the default dataset, and compare
`entityId` plus `entryDate` with the previous run.

### Why use the official Planning Data route?

The Actor queries the documented, anonymous Planning Data API directly.

That means:

- no council portal browser automation;
- no login or API key;
- no residential proxy;
- stable official entity identifiers;
- official pagination and spatial filters;
- source and documentation URLs retained in every row;
- an explicit scan bound for predictable scheduled work.

Coverage follows the source dataset. The Actor does not claim that every UK
council or every historical application is present.

### What data is extracted?

| Field | Meaning |
| --- | --- |
| `entityId` | Stable numeric Planning Data entity ID |
| `reference` | Published planning application reference |
| `proposal` | Development proposal or description |
| `address` | Published site address text |
| `organisationEntity` | Official council/source organisation entity ID |
| `submittedDate` | Source start/submission date |
| `decisionDate` | Published decision date |
| `entryDate` | Date this record version entered Planning Data |
| `decision` | Published decision value |
| `decisionType` | Published decision route/type |
| `developmentClassification` | Official classification identifier or URL |
| `point` | Point in WKT format |
| `latitude`, `longitude` | Coordinates parsed from `point` |
| `geometry` | Other available WKT geometry |
| `quality` | Source quality marker when supplied |
| `documentationUrl` | Council/source application page |
| `sourceUrl` | Stable Planning Data entity page |
| `sourceQueryUrl` | Exact official API page used |
| `dataset` | `planning-application` |
| `licence` | Declared Open Government Licence |
| `retrievedAt` | UTC retrieval timestamp |

Fields can be `null` when planning.data.gov.uk does not supply them.

### Getting started

1. Open the Actor input page.
2. Keep the prefilled `submittedSince` date or choose a more precise filter.
3. Set `maxItems` to the number of useful applications you want.
4. Keep `maxScanItems` above `maxItems` when using local keyword or decision
   filters.
5. Click **Start**.
6. Open the **Planning applications** dataset view.
7. Export the rows as JSON, CSV, Excel, XML, or RSS through Apify.

A small first run is recommended before increasing either limit.

### Input parameters

#### `organisationEntity`

An array of official numeric organisation entity IDs.

Example:

```json
[26]
```

#### `references`

Exact application references.

```json
["AWDM/0550/25"]
```

#### `entityIds`

Exact Planning Data entity IDs for deterministic retrieval.

```json
[10000098508]
```

#### `postcodeOrUprn`

A UK postcode or Unique Property Reference Number accepted by the official API.

#### `submittedSince` and `submittedUntil`

Inclusive dates in `YYYY-MM-DD` form. The lower bound is sent to the source API;
the upper bound is applied to returned rows.

#### `updatedSince`

An inclusive Planning Data entry-date lower bound. This is useful for scheduled
refreshes but is not built-in deduplication or alerting.

#### `decision`

Exact decision values matched case-insensitively.

```json
["Approve", "Refuse"]
```

#### `proposalKeywords`

Every supplied term must appear in the proposal text, case-insensitively.
These terms are applied after API retrieval.

```json
["extension", "rear"]
```

#### `geometryWkt` and `geometryRelation`

Supply a `POINT`, `POLYGON`, or `MULTIPOLYGON` in WKT format. The supported
relations are `intersects`, `within`, and `contains`.

#### `maxItems`

Maximum useful rows saved. Default: `20`. Maximum: `10000`.

#### `maxScanItems`

Maximum source rows inspected. Default: `20`. Maximum: `100000`.
It must be at least `maxItems`.

### Input examples

#### Recent submitted applications

```json
{
  "submittedSince": "2025-05-01",
  "maxItems": 20,
  "maxScanItems": 1000
}
```

#### One organisation entity

```json
{
  "organisationEntity": [26],
  "maxItems": 10,
  "maxScanItems": 1000
}
```

#### Source-update monitoring input

```json
{
  "updatedSince": "2025-09-01",
  "maxItems": 20,
  "maxScanItems": 1000
}
```

### Output example

A current source row is normalized like this:

```json
{
  "entityId": 10000098508,
  "reference": "AWDM/0550/25",
  "proposal": "Single storey outbuilding, with metal pergola with aluminium louvres in rear garden, for use as an office and games room",
  "address": "2 Dankton Lane Sompting West Sussex BN15 0EE",
  "organisationEntity": 26,
  "submittedDate": "2025-05-01",
  "decisionDate": "2025-06-16",
  "entryDate": "2025-09-07",
  "decision": "Approve",
  "decisionType": "Delegated",
  "point": "POINT (-0.343124 50.834924)",
  "latitude": 50.834924,
  "longitude": -0.343124,
  "documentationUrl": "http://planning.adur-worthing.gov.uk/online-applications/applicationDetails.do?activeTab=summary&keyVal=SVGKCLCBHHE00",
  "sourceUrl": "https://www.planning.data.gov.uk/entity/10000098508",
  "dataset": "planning-application",
  "licence": "Open Government Licence v3.0"
}
```

The dataset contains one row per accepted planning application.

### How much does it cost to export UK planning applications?

Pricing uses one `$0.005` start event plus one `item` event for each planning
application saved. The per-item tiers decrease with the Apify customer tier:

| Tier | Price per saved application |
| --- | ---: |
| FREE | $0.00920 |
| BRONZE | $0.00800 |
| SILVER | $0.00624 |
| GOLD | $0.00480 |
| PLATINUM | $0.00320 |
| DIAMOND | $0.00224 |

At BRONZE, 20 results cost `$0.165`: `$0.005` to start plus `$0.160` for results.
Only useful rows saved to the default dataset receive an item charge. Source
rows rejected by your filters are not item-charged.

Apify may separately enforce your run spending limit. Check the live pricing
panel before a large run.

### Monitoring workflow

1. Choose an `updatedSince` date.
2. Schedule the Actor daily or weekly.
3. Store `entityId`, `entryDate`, and the business fields you monitor.
4. Compare the new dataset with your previous snapshot.
5. Notify your own system when a new entity or changed entry date appears.

The Actor supplies stable comparison fields. It does not persist cross-run state
or send alerts by itself.

### Spatial workflow

Use `geometryWkt` when a buyer job is defined by an area rather than a council.
For example, a polygon can select official source geometries that intersect a
site-search boundary.

Spatial results depend on the geometry present in the official dataset. Records
without suitable source geometry cannot satisfy a spatial query.

### Integrations

You can connect the default dataset to:

- Google Sheets through Apify integrations;
- Make or Zapier workflows;
- webhooks triggered after a successful run;
- an S3-compatible lake or database ingestion job;
- Python, JavaScript, or command-line data pipelines;
- Apify schedules for recurring refreshes.

Use `entityId` as the main stable key and retain `sourceUrl` for provenance.

### Run through the Apify API

Replace `<APIFY_TOKEN>` with your token.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~uk-planning-applications/runs?token=<APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"updatedSince":"2025-09-01","maxItems":20,"maxScanItems":1000}'
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/uk-planning-applications').call({
  organisationEntity: [26],
  maxItems: 10,
  maxScanItems: 1000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("automation-lab/uk-planning-applications").call(run_input={
    "submittedSince": "2025-05-01",
    "maxItems": 20,
    "maxScanItems": 1000,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Use with MCP and AI agents

Add the Apify MCP endpoint to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/uk-planning-applications"
```

Use the same remote-server configuration in **Claude Desktop**, **Cursor**, or
**VS Code**:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/uk-planning-applications"
    }
  }
}
```

In Claude Desktop, Cursor, and VS Code, open the application's MCP settings and
add the `apify` server shown above.

Example prompts:

- “Find 20 planning applications submitted since 2025-05-01 and summarize the
  proposal and decision fields.”
- “Export ten applications for organisation entity 26 and retain source links.”
- “Run the UK planning application monitor input and compare entity IDs with my
  previous dataset.”

### Reliability and retries

The Actor sends direct HTTPS requests to the official government API.

Each request has a 30-second timeout. Network errors, HTTP 429, and server 5xx
responses are retried up to three times with bounded exponential backoff.
Deterministic client errors are reported without an unbounded retry loop.

There is no browser, proxy, cookie, or login fallback.

### Limits and source coverage

- Planning application coverage is whatever planning.data.gov.uk currently
  publishes.
- The dataset is described by the source as alpha.
- Some records have no address, decision, point, or geometry.
- `proposalKeywords`, `decision`, and `submittedUntil` are local filters and can
  require scanning more rows than are saved.
- `maxScanItems` can stop a selective search before `maxItems` is reached.
- Postcode/UPRN and spatial semantics follow the official API.
- The Actor does not download council documents or attachments.
- Applicant and agent contact fields are not promised because this official
  entity dataset does not consistently expose them.

### Legality and responsible use

Planning Data declares the planning-application dataset under the
[Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).
Review the source attribution and licence before redistribution.

Planning applications can contain information about properties and people.
Use the data lawfully, minimize personal-data processing, maintain provenance,
and comply with applicable UK data-protection and direct-marketing rules.

This Actor is an independent data tool and is not affiliated with the UK
government or any council.

### Troubleshooting

#### My run returned fewer rows than `maxItems`

The source may contain fewer matching rows, fields needed by your local filters
may be empty, or `maxScanItems` may have been reached. Check the run log and
increase the scan limit only when necessary.

#### My council name is not an input option

The official filter uses numeric `organisationEntity` identifiers. Find the
appropriate entity on planning.data.gov.uk and supply the number.

#### A result has null coordinates or decision

Those values were absent from the official source response. The Actor keeps
nulls rather than guessing.

#### The source API is temporarily unavailable

The Actor retries transient failures three times. Retry the run later if all
attempts are exhausted.

#### Can I search arbitrary proposal text server-side?

The official API does not expose a general proposal-text query in this route.
`proposalKeywords` is applied locally to bounded scanned rows.

### FAQ

#### Does this cover every council in the UK?

No completeness claim is made. It covers planning-application entities currently
published by planning.data.gov.uk.

#### Does it scrape council portals?

No. It uses the official Planning Data API and only links to published council
records when `documentationUrl` is available.

#### Can I monitor changes?

Yes, schedule `updatedSince` runs and compare `entityId` plus `entryDate` in your
own storage. The Actor does not maintain cross-run history.

#### Are empty or rejected source rows charged?

No item event is charged for rows that are not saved. The one-time start event
still applies.

#### Can I export CSV or Excel?

Yes. Apify datasets can be downloaded in JSON, CSV, Excel, XML, RSS, and other
supported formats.

#### Can I request more than 500 rows?

Yes. The source page size is 500, while the Actor paginates until `maxItems`,
`maxScanItems`, or source exhaustion is reached.

### Related Automation Lab actors

This Actor is the portfolio's official UK national planning-record source.
No closely related Automation Lab Actor is linked in the initial release rather
than presenting a third-party competitor as a portfolio product.

For a broader workflow, combine these rows with your own property inventory,
site boundaries, CRM, or business-intelligence system through Apify integrations.

### Source and attribution

- Dataset: `planning-application`
- Source: [planning.data.gov.uk](https://www.planning.data.gov.uk/dataset/planning-application)
- API documentation: [Planning Data API](https://www.planning.data.gov.uk/docs)
- Licence: Open Government Licence v3.0

Always retain the application reference, source entity ID, and source URL when
a downstream use needs auditable provenance.

# Actor input Schema

## `organisationEntity` (type: `array`):

Official numeric organisation-entity identifiers from planning.data.gov.uk. Multiple values are combined by the source API.

## `references` (type: `array`):

Exact official application references, for example AWDM/0550/25.

## `entityIds` (type: `array`):

Exact numeric planning.data.gov.uk entity IDs for deterministic lookups.

## `postcodeOrUprn` (type: `string`):

A UK postcode or Unique Property Reference Number accepted by the official API.

## `submittedSince` (type: `string`):

Return applications submitted on or after this date (YYYY-MM-DD).

## `submittedUntil` (type: `string`):

Keep applications submitted on or before this date (YYYY-MM-DD). This bound is applied after retrieval.

## `updatedSince` (type: `string`):

Return records whose Planning Data entry date is on or after this date (YYYY-MM-DD), useful for scheduled monitoring.

## `decision` (type: `array`):

Keep exact decision values (case-insensitive), such as Approve or Refuse.

## `proposalKeywords` (type: `array`):

Keep records whose proposal contains every supplied term, case-insensitive. Increase the scan limit for rare terms.

## `geometryWkt` (type: `string`):

POINT, POLYGON, or MULTIPOLYGON in WKT format used by the official spatial API.

## `geometryRelation` (type: `string`):

Spatial relationship used with Search geometry.

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

Maximum useful planning applications saved to the default dataset.

## `maxScanItems` (type: `integer`):

Safety bound for source rows inspected when local decision, date, or keyword filters are selective. Must be at least Maximum results.

## Actor input object example

```json
{
  "submittedSince": "2025-05-01",
  "geometryRelation": "intersects",
  "maxItems": 20,
  "maxScanItems": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing normalized planning application records.

# 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 = {
    "submittedSince": "2025-05-01",
    "maxItems": 20,
    "maxScanItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/uk-planning-applications").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 = {
    "submittedSince": "2025-05-01",
    "maxItems": 20,
    "maxScanItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/uk-planning-applications").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 '{
  "submittedSince": "2025-05-01",
  "maxItems": 20,
  "maxScanItems": 20
}' |
apify call automation-lab/uk-planning-applications --silent --output-dataset

```

## MCP server setup

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

```

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/8T5Y9s10wY8fkKFAp/builds/Zw7E4Kb6bvJs84iCs/openapi.json
