# UK Planning Documents: Decision Notices and Officer Reports (`devon_gtme/uk-planning-documents`) Actor

Extract the full text of UK planning Decision Notices and Officer Reports straight from council portals, and find out why permission was refused.

- **URL**: https://apify.com/devon\_gtme/uk-planning-documents.md
- **Developed by:** [Devon Kellar](https://apify.com/devon_gtme) (community)
- **Categories:** Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 document extracteds

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 Planning Decision Notice and Officer Report Text

Get the **full text of the documents** attached to a UK planning application, not just the register entry.

Give this actor a planning application and it returns the complete written text of the Decision Notice and the Officer Report, pulled straight from the council's own portal and cleaned up ready to read or feed into your own analysis.

### How this is different

Other UK planning tools return the **register listing**: reference number, address, proposal, decision, dates, applicant, agent. That tells you *what* was decided.

This actor returns the **documents behind that listing**. That tells you *why* it was decided, in the council's own words: the reasons for refusal, the policies cited, the officer's assessment, the conditions imposed.

If you already have a list of applications and keep hitting the wall of "decision: Refused" with no explanation, this is the piece that fills it in.

### What you get

One record per application, with the document text as plain fields:

| Field | What it holds |
|---|---|
| `decisionNoticeText` | Full text of the Decision Notice |
| `officerReportText` | Full text of the Officer Report |
| `reference`, `council` | Which application this is |
| `portalUrl`, `documentsUrl` | Where it came from, so you can check it |
| `portalType` | Which portal software the council runs |
| `documents` | Per document detail: type, filename, date, URL, how the text was extracted, page count, character count, and a plain English `warning` if a file could not yield text |
| `status`, `note` | What happened, in specific terms. See the status list below |

You can also ask for Plans, Consultation responses and Supporting Documents instead of, or as well as, the two defaults.

Where a council has uploaded several versions of a document, the newest by document date is the one returned, so you do not get a superseded notice.

### What you put in

Either of these, or both together:

- **Application portal URLs.** The most reliable option. Paste the council portal URL for each application. These chain straight from the `portalUrl` field of a UK planning applications actor.
- **Council plus reference.** For example `{"council": "Cornwall", "reference": "PA26/00056"}`, resolved through the free PlanIt API.

Other settings: which document types you want, whether to OCR scanned files, a cap on applications per run, and proxy configuration.

### File types

- **PDF with embedded text.** Read directly.
- **Scanned PDF with no text layer.** OCR'd automatically when OCR is switched on. Older decisions are often scans, and this is how they get recovered.
- **Word documents.** Officer Reports are frequently .docx rather than PDF. Both are handled.
- **Drawings and plans.** These are image only by nature and produce no text. When that happens the record says so in the `warning` field rather than leaving you with an unexplained blank.

### Statuses

Every application comes back with a specific status. There is no silent failure, and an empty result always says which kind of empty it is.

| Status | What it means |
|---|---|
| `ok` | Text extracted |
| `no_matching_documents` | The application has documents, but none of the types you asked for. Very common on applications still awaiting a decision. The note lists what is actually there |
| `no_documents_found` | The portal genuinely lists no documents for this application |
| `guest_access_denied` | The portal was reached but refused to show its document list to an anonymous visitor. The contents are unknown. This is **not** a confirmation that there are no documents |
| `extracted_empty` | Documents were found and downloaded, but no text could be recovered. The per document `warning` says why |
| `gateway_login_required` | The council's portal sits behind a login and needs an account for that council |
| `unsupported_portal` | The council runs portal software this actor does not handle yet. The note names the system |
| `not_found` | A council and reference could not be matched to an application |
| `error` | A network or portal failure. The note carries the detail |

### What it costs

You are charged **per document that actually comes back with text**, never per application.

That distinction matters. Applications still waiting on a decision, portals that refuse anonymous access, drawings that contain no text, and network failures all cost you nothing. You pay for text you receive.

| Documents in a single run | Price each |
|---|---|
| 1 to 999 | $0.050 |
| 1,000 to 1,999 | $0.040 |
| 2,000 and above | $0.035 |

The discount is applied as you go, in the same way income tax bands work. A run returning 2,500 documents is charged 999 at $0.050, then 1,000 at $0.040, then 501 at $0.035, which comes to $107.49, or an effective rate of $0.043 per document.

Two things worth knowing. The bands count documents within one run, so a single large run is cheaper than the same volume split across many small ones. And a typical application yields two documents, the Decision Notice and the Officer Report, so 1,000 applications usually means around 2,000 documents.

### Council coverage

Five portal systems are supported, which together account for roughly 85% of UK planning authorities. That figure was measured against a live sample of 55 authorities, not estimated.

- **Idox Public Access**, the most common system by a wide margin, on all of its URL variants
- **Agile Applications**
- **DEF Planning Register**, including the shared planning-register.co.uk sites
- **Civica and Idox Publisher**
- **Salesforce Experience Cloud**, the Arcus planning register

Councils on other systems, such as Northgate M3 and Ocella, are recognised and reported as `unsupported_portal` with the system named, so you always know why an application produced nothing. Adapters for those can be added on request.

### Honest limits

- Coverage is counted **by authority**. Idox is more common in large cities, so coverage by application volume is higher than 85%, but no single council is guaranteed until it has been run.
- Around 15 councils have been tested end to end so far. A supported system means the software is handled, not that every council on it has been individually verified.
- A small number of councils block automated access at the network level regardless of proxy. Those return `error` with the detail.
- Some councils, such as Central Bedfordshire, sit behind a portal login. Those return `gateway_login_required` and need an account for that council.
- Committee reports, as opposed to delegated officer reports, have not been specifically tested yet.

### Practical notes

- Council portals often block datacenter IP addresses. Residential proxy is strongly recommended and is the default.
- Each application runs in its own isolated session, so one bad proxy exit or one flaky council cannot spoil the rest of the run.
- Long Officer Reports are genuinely long. Reports over 200,000 characters have been returned intact.

# Actor input Schema

## `startUrls` (type: `array`):

Council planning-portal application URLs (Idox Public Access, Agile Applications, Civica/Idox Publisher, DEF Planning Register, Salesforce/Arcus; e.g. https://planning.cornwall.gov.uk/online-applications/applicationDetails.do?keyVal=...). Any tab works; the actor finds the document list. This is the most reliable input and chains directly from the UK Planning Applications actor's portalUrl field.

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

Resolve applications by council authority + planning reference via the free PlanIt API (e.g. {"council": "Cornwall", "reference": "PA26/00056"}). Portal URLs above are more reliable where you have them.

## `documentTypes` (type: `array`):

Which documents to pull text from. Decision Notice and Officer Report are the defaults.

## `includeOcr` (type: `boolean`):

If a Decision Notice is a scanned image with no embedded text, OCR it (slower). Turn off for text-only, faster runs.

## `maxApplications` (type: `integer`):

Cap the number of applications processed in this run (0 = no cap).

## `proxy` (type: `object`):

Council portals often block datacenter IP addresses, while residential proxies pass. Residential is the default and is strongly recommended. Note that a few councils, such as Central Bedfordshire, sit behind a portal login that no proxy can solve on its own. Those are reported as gateway\_login\_required.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://planning.cornwall.gov.uk/online-applications/applicationDetails.do?activeTab=summary&keyVal=T8FVJVFGFHN00"
    }
  ],
  "references": [],
  "documentTypes": [
    "decision_notice",
    "officer_report"
  ],
  "includeOcr": true,
  "maxApplications": 0,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "startUrls": [
        {
            "url": "https://planning.cornwall.gov.uk/online-applications/applicationDetails.do?activeTab=summary&keyVal=T8FVJVFGFHN00"
        }
    ],
    "references": [],
    "documentTypes": [
        "decision_notice",
        "officer_report"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devon_gtme/uk-planning-documents").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 = {
    "startUrls": [{ "url": "https://planning.cornwall.gov.uk/online-applications/applicationDetails.do?activeTab=summary&keyVal=T8FVJVFGFHN00" }],
    "references": [],
    "documentTypes": [
        "decision_notice",
        "officer_report",
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("devon_gtme/uk-planning-documents").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 '{
  "startUrls": [
    {
      "url": "https://planning.cornwall.gov.uk/online-applications/applicationDetails.do?activeTab=summary&keyVal=T8FVJVFGFHN00"
    }
  ],
  "references": [],
  "documentTypes": [
    "decision_notice",
    "officer_report"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call devon_gtme/uk-planning-documents --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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