# UK Planning Applications Scraper — Agent Contacts (`spotless_studios/uk-planning-applications-scraper`) Actor

New planning applications from 31 UK councils (Leeds, Westminster, Glasgow, Edinburgh, Southwark…) plus any Idox portal. Applicant, agent name, phone & email, status, decision, deadlines. Daily monitoring.

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

## Pricing

from $6.00 / 1,000 application scrapeds

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 Scraper — Agent Contacts

Get **new planning applications from 31 UK councils** in one run: Leeds, Westminster, Glasgow, Edinburgh, Southwark, Lambeth, Sheffield, Cornwall, Cambridge, and more. Any other council on Idox Public Access works too; paste its URL. Each application comes with **site address, postcode, proposal, status, and dates**. Turn on details to add **application type, ward, case officer, applicant, and the agent's name, company, phone, and email**.

Built for **builders, architects, kitchen and window installers, solar and heat-pump companies, surveyors, property investors, and planning consultants** who want to reach projects the week they're filed.

> **Trial cost:** 25 applications ≈ **$0.15** · **+$0.10** with agent/applicant details (`includeDetails`).

### What you get

| Field | Example |
|-------|---------|
| `councilName`, `reference`, `url` | Leeds City Council · 26/9/00148/MOD · direct link |
| `address`, `postcode` | 12 Example Road, Wetherby · LS23 6RG |
| `proposal` | Demolition of existing side extension; construction of single-storey extension… |
| `status`, `validatedDate`, `receivedDate` | Current · 2026-09-24 |
| `decision`, `decisionDate` | Approved · 2026-10-30 |
| **Details:** `applicationType`, `ward`, `parish`, `caseOfficer` | Householder · Wetherby · … |
| **Details:** `applicantName`, `applicantAddress` | Mrs M Barnes |
| **Details:** `agentName`, `agentCompanyName`, `agentAddress` | Apex Architecture |
| **Details:** `agentEmail`, `agentPhone` | mohammed@apex-architecture.co.uk · 07838 236 302 |
| **Details:** `consultationDeadline`, `determinationDeadline`, `committeeDate` | 2026-10-18 |
| `summaryFields`, `detailFields`, `dateFields` | Every raw field the council publishes |

Dates are ISO (`YYYY-MM-DD`), and postcodes are normalised.

### Why this scraper

- 🏛️ **31 councils built in, plus any Idox portal** — one input, one dataset, one schema across councils.
- 📇 **Agent contacts** — agents (architects, planning consultants, builders) publish phone and email on many councils. Filter with `requireAgentContact`.
- 🎯 **Filters** — postcode area, district, or sector (`LS6`, `SW1`, `EH10 6`), proposal text (searched on the council side), status, application type include/exclude (drop "Tree Works"), decision, ward, and keywords with `/regex/`.
- 🔔 **Daily monitoring** — `onlyNewItems` remembers what you've already received. Schedule daily with `daysBack: 3` and get only fresh filings.
- 🧠 **Handles council limits** — long date ranges are split into windows, and windows that hit a council's result cap are halved automatically.
- 🤝 **Polite by design** — a per-council request gap that backs off automatically when a council says "slow down".

### Quick start

**Loft conversions and extensions in Leeds with agent contacts, last 14 days**

```json
{
  "councils": ["leeds"],
  "daysBack": 14,
  "proposalContains": "extension",
  "requireAgentContact": true,
  "outputFields": ["reference", "address", "postcode", "proposal", "agentName", "agentEmail", "agentPhone", "url"]
}
```

**Daily London householder feed (no tree works), for a CRM**

```json
{
  "councils": ["westminster", "southwark", "lambeth", "barnet", "ealing"],
  "daysBack": 3,
  "applicationTypes": ["Householder"],
  "excludeKeywords": ["tree", "TPO"],
  "onlyNewItems": true,
  "stateKey": "london-householder"
}
```

**Recently approved applications in Edinburgh (EH10), for contractors**

```json
{ "councils": ["edinburgh"], "dateType": "decision", "daysBack": 30, "decisions": ["Grant", "Approve"], "postcodes": ["EH10"] }
```

**A council that isn't in the list**

```json
{ "customPortalUrls": ["https://planning.example.gov.uk/online-applications"], "daysBack": 7 }
```

### Input reference

| Parameter | Default | What it does |
|-----------|---------|--------------|
| `councils` | leeds, glasgow | Built-in councils |
| `customPortalUrls` | — | Any Idox Public Access base URL |
| `dateType` | validated | validated, received, decision |
| `daysBack` / `dateFrom` / `dateTo` | 7 / — / today | Date range (`dateFrom` accepts `30 days`) |
| `proposalContains` | — | Council-side proposal text search |
| `postcodes` | — | Area, district, sector, or full postcode |
| `statuses` | — | Status contains |
| `applicationTypes` / `excludeApplicationTypes` | — | Needs details |
| `decisions`, `wards` | — | Needs details |
| `includeDetails` | false | Type, ward, officer, applicant, agent contacts, deadlines (add-on) |
| `requireAgentContact` | false | Only applications with agent phone or email |
| `includeKeywords` / `excludeKeywords` / `keywordMatch` | — | Words or `/regex/`, any/all |
| `onlyNewItems` + `stateKey` | false | Monitoring memory per saved search |
| `maxResults` / `maxResultsPerCouncil` | 200 / — | Caps |
| `outputFields` | all | Keep only these fields, in order |
| `maxConcurrency`, `detailConcurrency`, `minRequestIntervalMs`, `dateChunkDays` | 4 / 2 / 600 / 14 | Performance and politeness |
| `maxRequestRetries`, `requestTimeoutSecs` | 4 / 60 | Reliability |
| `proxyConfiguration` | off | Optional (use GB if a council blocks non-UK traffic) |

### Pricing

| Event | Price |
|-------|-------|
| Application saved (`application-scraped`) | **$0.006** |
| Details & contacts add-on (`application-details`) | **$0.004** per saved application |

A daily feed of 40 new applications with agent contacts costs about **$0.40 per day**. Applications removed by filters are free.

### Export formats & integrations

#### Export formats

Export your dataset with zero code in whichever format fits your workflow:

- **Excel (.xlsx) & CSV:** Clean tabular sheets formatted for Microsoft Excel, Google Sheets, LibreOffice, and CRM imports.
- **JSON & JSONL:** Structured records for developers, backend pipelines, and AI agent prompt context.
- **XML & HTML:** Formatted for web dashboards, feed syndication, and reporting.

#### No-code automations & integrations

- **Google Sheets & Airtable:** Automatically push new scraped rows into live tracking spreadsheets.
- **Make, Zapier & n8n:** Trigger instant Slack alerts, email digests, or create deals in HubSpot, Salesforce, and Pipedrive.
- **Webhooks & REST API:** Programmatically trigger runs and retrieve results via Apify's REST API, Python SDK, or JavaScript/TypeScript SDK.

### FAQ

**How do I export this data to Excel or CSV?** After the run finishes, click the **Export** button in the Dataset tab to download the complete file in Excel (.xlsx), CSV, JSON, or XML. You can also automate exports directly to Google Sheets via the Integrations tab.
**Is this data public?** Yes. Councils publish planning applications for public consultation. Use contact details responsibly, and follow UK GDPR and PECR when doing outreach.

**Why are some agent emails missing?** Councils and agents choose what to publish. Some councils never show contact details.

**A council I need isn't listed?** Paste its Idox URL into `customPortalUrls`. If it runs a different system (Northgate, Ocella, Agile), ask on the actor page.

## **Bristol?** Bristol's firewall rejects automated date searches, so it isn't in the list.

### More from Spotless Studios

**[All actors on Apify](https://apify.com/spotless_studios)** · Support: spotless.studios.info@gmail.com

| Actor | Best for |
|-------|----------|
| [SLED Government Bids](https://apify.com/spotless_studios/sled-procurement-scraper) | Daily US gov RFP / bid alerts |
| [Webflow Experts](https://apify.com/spotless_studios/webflow-experts-scraper) | Webflow agency & freelancer leads |
| [Stripe Partners](https://apify.com/spotless_studios/stripe-partners-scraper) | Stripe implementation partner lists |
| [UK Planning Applications](https://apify.com/spotless_studios/uk-planning-applications-scraper) | UK planning leads + agent contacts |
| [Product Hunt](https://apify.com/spotless_studios/product-hunt-scraper) | Every PH launch + makers / websites |
| [Duunitori Jobs](https://apify.com/spotless_studios/duunitori-jobs-scraper) | Finland job listings |
| [Clutch Agencies](https://apify.com/spotless_studios/clutch-agencies-scraper) | Clutch agency prospecting |
| [Skool Communities](https://apify.com/spotless_studios/skool-communities-scraper) | Skool community & creator leads |

# Actor input Schema

## `councils` (type: `array`):

Pick one or more councils. Empty (with no custom portals) = Leeds and Glasgow.

## `customPortalUrls` (type: `array`):

Any other council's Idox Public Access URL, e.g. https://planning.example.gov.uk/online-applications. Recognisable by 'search.do' / 'applicationDetails.do' in the address bar.

## `dateType` (type: `string`):

Validated = new applications accepted by the council (best for leads). Decision = recently decided. Received is used where the council supports it.

## `daysBack` (type: `integer`):

Search the last N days (including today). Ignored when Date from is set.

## `dateFrom` (type: `string`):

YYYY-MM-DD or relative, e.g. 30 days.

## `dateTo` (type: `string`):

YYYY-MM-DD. Default: today.

## `proposalContains` (type: `string`):

Council-side search on the proposal text, e.g. 'loft conversion' or 'solar'. Fastest way to narrow big councils.

## `postcodes` (type: `array`):

Area (LS), district (LS6, SW1), sector (LS6 2), or full postcode.

## `statuses` (type: `array`):

e.g. Current, Awaiting decision, Decided, Registered, Withdrawn.

## `applicationTypes` (type: `array`):

e.g. Householder, Full Planning, Listed Building, Prior Approval, Change of Use.

## `excludeApplicationTypes` (type: `array`):

e.g. Tree Works, Advertisement, Discharge of Condition, Non Material Amendment.

## `decisions` (type: `array`):

e.g. Approved, Granted, Refused.

## `wards` (type: `array`):

Ward, parish, or community council names.

## `applicationUrls` (type: `array`):

Fetch specific Idox planning application detail URLs (containing keyVal=...) directly without running a date-range search.

## `includeDetails` (type: `boolean`):

Visit each application for application type, case officer, ward, applicant, agent name, company, address, phone, and email, plus consultation and decision deadlines. Billed as an add-on per application.

## `requireAgentContact` (type: `boolean`):

Keep only applications whose agent published a phone number or email.

## `includeKeywords` (type: `array`):

Keep applications whose proposal, address, type, applicant, or agent contain these words. /regex/ supported.

## `excludeKeywords` (type: `array`):

Drop applications containing any of these words or /regex/, e.g. tree, TPO, advertisement.

## `keywordMatch` (type: `string`):

Require any or all include keywords.

## `onlyNewItems` (type: `boolean`):

Remember applications from previous runs and save only new ones. Schedule daily with Days back = 3.

## `stateKey` (type: `string`):

Separate memory per saved search.

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

Stop after saving this many applications in total.

## `maxResultsPerCouncil` (type: `integer`):

Keeps one big council from using the whole budget.

## `outputPreset` (type: `string`):

Quickly choose how much data to save per record: full record, lean summary, or contact & social links only.

## `outputFields` (type: `array`):

Save only these fields, in this order (e.g. councilName, reference, address, postcode, proposal, agentName, agentEmail, agentPhone). Supports nested dot-paths (e.g. makers.username). Empty keeps all fields from the selected preset.

## `excludeFields` (type: `array`):

Remove specific fields (or nested dot-paths) from each saved record to keep datasets compact.

## `includeEmptyFields` (type: `boolean`):

When turned off, strips null, empty strings, empty arrays, and empty objects from every saved record.

## `requiredFields` (type: `array`):

Only save (and only pay for) records where every listed field or dot-path has a non-empty value (e.g. website, inquiryEmail).

## `maxConcurrency` (type: `integer`):

Councils searched at the same time.

## `detailConcurrency` (type: `integer`):

Council servers are slow; keep this low to be polite and avoid errors.

## `minRequestIntervalMs` (type: `integer`):

Politeness delay per council server. Doubles automatically if a council answers 'too many requests'.

## `dateChunkDays` (type: `integer`):

Long ranges are searched in windows of this size. Windows that hit a council's result cap are split automatically.

## `maxRequestRetries` (type: `integer`):

Retries with exponential backoff on timeouts, 429, and 5xx responses.

## `requestTimeoutSecs` (type: `integer`):

Council portals can be slow.

## `proxyConfiguration` (type: `object`):

Not needed for most councils. A few block non-UK traffic; use Apify Proxy with country GB for those.

## `proxyEscalation` (type: `boolean`):

If the site blocks the run, automatically step up from a direct connection to Apify datacenter proxy, then residential proxy, only for the blocked site. Turn off to use exactly the proxy above.

## Actor input object example

```json
{
  "councils": [
    "leeds",
    "glasgow"
  ],
  "dateType": "validated",
  "daysBack": 7,
  "includeDetails": false,
  "requireAgentContact": false,
  "keywordMatch": "any",
  "onlyNewItems": false,
  "stateKey": "default",
  "maxResults": 25,
  "outputPreset": "full",
  "includeEmptyFields": true,
  "maxConcurrency": 4,
  "detailConcurrency": 2,
  "minRequestIntervalMs": 600,
  "dateChunkDays": 14,
  "maxRequestRetries": 4,
  "requestTimeoutSecs": 60,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "proxyEscalation": true
}
```

# Actor output Schema

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

Scraped planning applications

# 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 = {
    "councils": [
        "leeds",
        "glasgow"
    ],
    "maxResults": 25,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("spotless_studios/uk-planning-applications-scraper").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 = {
    "councils": [
        "leeds",
        "glasgow",
    ],
    "maxResults": 25,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("spotless_studios/uk-planning-applications-scraper").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 '{
  "councils": [
    "leeds",
    "glasgow"
  ],
  "maxResults": 25,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call spotless_studios/uk-planning-applications-scraper --silent --output-dataset

```

## MCP server setup

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

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/5UoPEvFGQEDYSP0Vo/builds/CAOWLT6uNMfAIL9Yi/openapi.json
