# UK Planning Applications — by Postcode or Keyword (`promptandproof/uk-planning-applications`) Actor

Real, live UK planning application data by postcode+radius, free-text keyword, council/authority name, or date range — sourced from PlanIt (planit.org.uk), a free, public aggregator of UK local-authority planning application registers.

- **URL**: https://apify.com/promptandproof/uk-planning-applications.md
- **Developed by:** [dan boulton](https://apify.com/promptandproof) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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 Applications — by Postcode or Keyword

Real, live UK planning application data — search by postcode + radius,
free-text keyword, council/authority name, or a received-date range.
Sourced from [PlanIt](https://www.planit.org.uk/), a real, free, public
aggregator of local-authority planning application registers across the
UK. No scraping of council portals directly — every field is a real
PlanIt API response field, passed through un-invented.

### Input

| Field | Type | Notes |
|---|---|---|
| `postcode` | string | e.g. `"M16 9HF"`. Used with `radiusKm`. |
| `radiusKm` | number | Default 5. |
| `keyword` | string | Free-text search against the application description. |
| `authority` | string | Restrict to one council, e.g. `"Manchester"`. |
| `startDate` / `endDate` | string | `YYYY-MM-DD`, application-received date range. |
| `maxResults` | integer | Default 100, hard cap 5000 (PlanIt's own absolute per-request limit). |

At least one of `postcode`, `keyword`, or `authority` is required — this
actor refuses an unscoped "everything" query rather than guess one (a real
unscoped keyword-only search against PlanIt's full national dataset timed
out during testing; scoping by authority or postcode keeps a real query
fast and is a genuine, disclosed usage note, not just an input-validation
nicety).

### Output (one dataset item per application)

```json
{
  "reference": "Manchester/115763/FU/2017",
  "authority": "Manchester",
  "address": "All Bar One 73 - 79 King Street Manchester M2 4NG",
  "postcode": "M2 4NG",
  "description": "Change of use of pavement for use as an external seating area",
  "status": "Permitted",
  "decision": "Approved",
  "application_type": "Amendment",
  "received_date": "2017-05-19",
  "decided_date": "2017-07-14",
  "last_changed": "2026-09-05T11:18:35.383358",
  "planit_url": "https://www.planit.org.uk/planapplic/Manchester/115763/FU/2017/",
  "source_url": "https://arcusbe.manchester.gov.uk/pr/s/detail/a1DSl000007GC6AMAW",
  "location": {"lat": 53.480914, "lng": -2.242698}
}
```

### Pricing

Pay-per-event: one charge per real application actually returned — never
charged for a search that returns nothing. See
`.actor/pay_per_event_schema.json` for the proposed event/price; **verify
and finalise the real price in the Apify Console's own Monetization tab
before publishing** (disclosed honestly, same as the Companies House
actor's README: the exact checked-in schema format could not be confirmed
from a literal authoritative example during a live web search while
building this — the code-side `Actor.charge()` call is real and correct
regardless of how the price itself ends up configured).

### Rate limits

PlanIt is real and genuinely rate-limited (a live 429 was hit while
building/testing this actor). One real retry after a 5s pause is built
in; a persistent 429 surfaces as a real, disclosed error rather than being
silently retried forever.

# Actor input Schema

## `postcode` (type: `string`):

A UK postcode to search around. Used with radiusKm. Prefilled with a real postcode (M16 9HF, Old Trafford) that returns live applications, so a first run works as-is. At least one of postcode, keyword or authority is required.

## `radiusKm` (type: `number`):

Radius around postcode, in kilometres.

## `keyword` (type: `string`):

Free-text search against the application description (PlanIt's own 'search' parameter), e.g. "extension", "solar", "change of use".

## `authority` (type: `string`):

Restrict to one local authority (PlanIt's own 'auth' parameter, e.g. "Manchester City Council").

## `startDate` (type: `string`):

YYYY-MM-DD. Applications received on/after this date.

## `endDate` (type: `string`):

YYYY-MM-DD. Applications received on/before this date.

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

Caps real results returned (and real charges). PlanIt's own absolute per-request cap is 5000.

## Actor input object example

```json
{
  "postcode": "M16 9HF",
  "radiusKm": 2,
  "maxResults": 20
}
```

# Actor output Schema

## `applications` (type: `string`):

Every planning application returned by this run, as JSON. Each item's fields are described by the dataset schema.

# 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 = {
    "postcode": "M16 9HF",
    "radiusKm": 2,
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("promptandproof/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 = {
    "postcode": "M16 9HF",
    "radiusKm": 2,
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("promptandproof/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 '{
  "postcode": "M16 9HF",
  "radiusKm": 2,
  "maxResults": 20
}' |
apify call promptandproof/uk-planning-applications --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,promptandproof/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/ltcDL1Lful1ymXX3R/builds/yA9du01TznAQqFVnr/openapi.json
