# Uk Extension Loft Planning Leads (`devon_gtme/uk-extension-loft-planning-leads`) Actor

Fresh leads for builders: homeowners who just got planning permission for an extension, loft conversion or dormer. UK planning applications from 381 authorities, pre-filtered to extension and loft work. Site addresses, decision dates, agent details and council portal links. No API key.

- **URL**: https://apify.com/devon\_gtme/uk-extension-loft-planning-leads.md
- **Developed by:** [Devon Kellar](https://apify.com/devon_gtme) (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 $20.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/platform/actors/running/actors-in-store#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 Extension & Loft Conversion Planning Applications — Builder Leads

Homeowners who **just got planning permission for an extension or loft conversion** are the highest-intent leads a builder can buy: they've committed money to drawings and fees, the council has said yes, and now they need someone to build it. This actor finds them the week the decision lands.

It scrapes UK planning applications from **381 planning authorities** across England, Scotland, Wales and Northern Ireland, pre-filtered to extension and loft work — single and two storey extensions, loft conversions, dormers. Every record comes with the **site address**, decision date, application description, planning agent details where published, and a direct link to the council portal.

No API key needed. No login required. Pick your area and run.

### Who this is for

- **Builders & extension specialists** — reach homeowners the week permission is granted, before they've picked a contractor. The site address is the lead.
- **Loft conversion companies** — filter to loft/dormer terms only and own your postcode.
- **Scaffolders** — every approved two-storey extension and loft conversion needs scaffold. Get there before the main contractor's usual firm does.
- **Structural engineers** — approved applications still need structural calcs and building regs drawings.
- **Glaziers & bifold/roof-light suppliers** — extensions mean big glazed openings; dormers mean new windows.
- **Building material suppliers & builders merchants** — map upcoming demand on your patch, account-manage the agents who file the most applications.

### How it works

The actor searches planning applications using a set of **extension/loft search terms** (editable — defaults below), then applies your geographic and status filters:

1. **Search terms** — defaults to `extension`, `loft conversion`, `single storey extension`, `two storey extension`, `dormer`. Add your own (`rear extension`, `hip to gable`, `garage conversion`, `wrap around extension`) or trim the list to narrow the vertical.
2. **Area** — name specific councils, or set a postcode + radius to cover exactly your service area, or leave both empty for nationwide.
3. **Status** — `Permitted` (default: fresh green lights = hottest leads) or `Undecided` to watch the pipeline before decisions land.
4. **Days back** — how fresh the decisions must be.

Search terms are combined into a single query (multi-word terms match as exact phrases, terms are OR'd), so adding terms widens the net without slowing the run. Results are de-duplicated.

### Typical usage: a weekly lead run

Set a **weekly schedule** in Apify with `daysBack: 7` for your councils or postcode radius. Every Monday you get the past week's newly permitted extensions and lofts on your patch — export to CSV, or push straight to your CRM via the Apify API.

```json
{
    "searchTerms": ["extension", "loft conversion", "dormer"],
    "councils": ["Croydon", "Bromley", "Sutton"],
    "appState": ["Permitted"],
    "daysBack": 7,
    "maxResults": 500
}
```

#### Postcode radius (service-area) search

```json
{
    "postcode": "KT17 1AA",
    "radiusKm": 15,
    "appState": ["Permitted"],
    "daysBack": 30,
    "maxResults": 500
}
```

#### Watch the pipeline (pre-decision)

```json
{
    "searchTerms": ["loft conversion", "dormer"],
    "councils": ["Manchester"],
    "appState": ["Undecided"],
    "daysBack": 60,
    "maxResults": 500
}
```

### Input parameters

**searchTerms**: (Optional) (String\[]) Keywords matched against the application description (and application type/status fields). Terms are OR-combined into one search; multi-word terms match as phrases. Default: `["extension", "loft conversion", "single storey extension", "two storey extension", "dormer"]`.

**councils**: (Optional) (String\[]) Council names to search. Leave empty for a nationwide search across all 381 planning authorities. Find exact council names on [PlanIt](https://www.planit.org.uk).

**appState**: (Optional) (String\[]) Filter by decision status: `Permitted`, `Undecided`, `Conditions`, `Rejected`, `Withdrawn`, `Referred`, `Appeal`. Default is `["Permitted"]`.

**daysBack**: (Optional) (Number) How many days back to search from today. For decided applications this filters by decision date; for undecided, by submission date. Range: 1–365. Default is `30`.

**postcode**: (Optional) (String) UK postcode as the centre point for a radius search. Requires `radiusKm`. Note: the data source's radius search can be slow and occasionally times out — the `councils` filter is more reliable for service-area targeting.

**radiusKm**: (Optional) (Number) Search radius in kilometres from the postcode centre point. Range: 1–100. Default is `10`.

**maxResults**: (Optional) (Number) Maximum total results to return. Range: 1–5,000. Default is `500`.

### Output data

Each dataset item is one planning application with **50+ fields** (coverage varies by council):

```json
{
    "council": "Croydon",
    "address": "42 Meadow Way, Croydon",
    "postcode": "CR0 4XX",
    "description": "Erection of a single storey rear extension and loft conversion with rear dormer",
    "appType": "Full",
    "appSize": "Small",
    "appState": "Permitted",
    "decidedDate": "2026-07-01",
    "startDate": "2026-05-02",
    "agentCompany": "ABC Architectural Design Ltd",
    "agentTel": "020 7000 0000",
    "latitude": 51.3726,
    "longitude": -0.0998,
    "portalUrl": "https://publicaccess.croydon.gov.uk/online-applications/...",
    "planitUrl": "https://www.planit.org.uk/planapplic/Croydon/26/01234/HSE/",
    "reference": "26/01234/HSE",
    "planitId": "Croydon/26/01234/HSE"
}
```

Core fields: `council`, `address`, `postcode`, `description`, `appType`, `appState`, `decidedDate`, `startDate`, `agentCompany`, `agentTel`, `latitude`/`longitude`, `portalUrl`, `planitUrl`, `reference`. Plus every extra field the council publishes: case officer, ward, consultation dates, document counts, direct docs/comment/map links, and more.

Export to **JSON**, **CSV**, or **Excel** in one click from the Apify Console, or pull via the [Apify API](https://docs.apify.com/api/v2).

### Tips

- **Permitted + short daysBack is the money query.** A homeowner whose permission landed this week is actively looking for a builder right now.
- The `agentCompany` (architect / architectural designer) is a lead too — designers who file lots of extension applications can refer you work repeatedly.
- Start with one council and a low `maxResults` (e.g. 10) to verify the data fits your patch before scaling up.
- All search terms run in a single query, so the run time depends on the number of **councils**: the data source enforces a **62-second delay between queries**. 1 council or a nationwide run ≈ ~1 minute; 10 councils ≈ ~10 minutes. (Including `Undecided` alongside decided statuses adds one extra query per council, since the source filters them by different date fields.)
- Search matching is stemmed by the data source, so `extension` can occasionally match words like "extensive" in tree-work descriptions. Prefer phrase terms (`single storey extension`, `rear extension`, `loft conversion`, `dormer`) for a cleaner list, or keep `extension` for maximum recall and skim the description column.
- **The homeowner's name is not in this actor's output**, because the PlanIt aggregator returns "See source" rather than the value. It is usually published on the council's own portal - open `portalUrl` and read the Details tab, or see [Developer and applicant contact details](#developer-and-applicant-contact-details) for the managed version. What this actor gives you directly is the **site address** (100%) and, on ~37% of records, the **agent/architect company**.

### Developer and applicant contact details

Every record includes `portalUrl` - a direct link to the council's own page for that application. Most UK councils run Idox Public Access portals (roughly 70% of the country), and those pages publish the **applicant name, applicant address, agent name and case officer**.

This actor does not fetch them. It reads the PlanIt aggregator, which returns the literal string `"See source"` for those fields instead of the values - "see source" meaning the council's own portal. Rather than export placeholder text dressed up as data, the actor drops those fields entirely, so an empty field is honestly empty.

**If you need applicant and developer names at scale, we run that as a managed enrichment service.** It fetches each application's council portal page and returns the applicant/agent details, resolving on the majority of Idox-covered councils and returning null - never a guess - where a council does not publish them. Message me via my [Apify profile](https://apify.com/devon_gtme) with the councils, volume and fields you need.

You can of course do this yourself for small volumes: open `portalUrl` and read the Details tab.

### Compute unit consumption

The actor is light — it's rate-limit-bound, not compute-bound. Memory: 1024 MB recommended.

- **Nationwide (any number of terms):** ~1 minute
- **3 councils:** ~3 minutes
- **10 councils:** ~10 minutes

### Bugs, fixes, updates, and changelog

This scraper is under active development. If you have any feature requests, you can raise an issue from the actor's Apify Store page.

### Data source

All data comes from [PlanIt](https://www.planit.org.uk), which aggregates publicly available planning data from UK local authority portals. The data is published by councils under statutory obligation — this actor provides structured, filterable access to it.

***

**Need something more custom?** Every planning vertical (new builds, demolitions, commercial fit-outs), enriched homeowner/agent contact data, or a fully managed lead pipeline delivered to your CRM — message me via my Apify profile and I'll build it.

# Actor input Schema

## `searchTerms` (type: `array`):

Keywords matched against the application description (and type/status fields). Terms are OR-combined into one search; multi-word terms match as phrases. The defaults cover the common extension and loft phrasings — add your own (e.g. 'rear extension', 'hip to gable', 'garage conversion') or remove terms to narrow the net.

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

Council names to search. Leave empty for nationwide search. Type any UK council name, e.g. 'Croydon', 'Manchester'.

## `appState` (type: `array`):

Filter by decision status. 'Permitted' = the homeowner just got the green light (highest-intent leads). 'Undecided' = pipeline you can watch.

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

How many days back to search from today (based on decision date). For 'Undecided' apps, this filters by submission date. Set to 7 and schedule weekly to monitor new permissions on your patch.

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

UK postcode for radius search. Requires Radius to be set. Example: SW1A 1AA. Note: the data source's radius search can be slow and occasionally times out — council filtering is more reliable.

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

Search radius in kilometres from the postcode centre point.

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

Maximum total results to return; the actor stops fetching once this cap is reached. PlanIt allows one request a minute, so this is really a budget in minutes rather than in rows: 300 is a single page and returns in seconds, and every further 300 costs another 62-second wait. Prefilled at 300 so a first run is immediate. Raise it freely -- 5,000 is supported, it simply takes about a quarter of an hour.

## Actor input object example

```json
{
  "searchTerms": [
    "extension",
    "loft conversion",
    "single storey extension",
    "two storey extension",
    "dormer"
  ],
  "councils": [],
  "appState": [
    "Permitted"
  ],
  "daysBack": 30,
  "radiusKm": 10,
  "maxResults": 300
}
```

# 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 = {
    "searchTerms": [
        "extension",
        "loft conversion",
        "single storey extension",
        "two storey extension",
        "dormer"
    ],
    "councils": [],
    "appState": [
        "Permitted"
    ],
    "daysBack": 30,
    "radiusKm": 10,
    "maxResults": 300
};

// Run the Actor and wait for it to finish
const run = await client.actor("devon_gtme/uk-extension-loft-planning-leads").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 = {
    "searchTerms": [
        "extension",
        "loft conversion",
        "single storey extension",
        "two storey extension",
        "dormer",
    ],
    "councils": [],
    "appState": ["Permitted"],
    "daysBack": 30,
    "radiusKm": 10,
    "maxResults": 300,
}

# Run the Actor and wait for it to finish
run = client.actor("devon_gtme/uk-extension-loft-planning-leads").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "extension",
    "loft conversion",
    "single storey extension",
    "two storey extension",
    "dormer"
  ],
  "councils": [],
  "appState": [
    "Permitted"
  ],
  "daysBack": 30,
  "radiusKm": 10,
  "maxResults": 300
}' |
apify call devon_gtme/uk-extension-loft-planning-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=devon_gtme/uk-extension-loft-planning-leads",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/BE9KEnTR5052weqEL/builds/CmyBSlBOzfQ210uuO/openapi.json
