# UK Property Sales - HM Land Registry Price Paid (`j0401/uk-price-paid`) Actor

Every residential property sale in England & Wales since 1995 (about 30 million transactions, OGL v3): price, transfer date, postcode and address, property type, new-build and tenure flags, Price Paid category. Search by postcode, town, price, date or type; aggregate with average prices.

- **URL**: https://apify.com/j0401/uk-price-paid.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 uk property sale records

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?

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 Property Sales - HM Land Registry Price Paid

Every residential property sale in **England & Wales since 1995**, from
HM Land Registry's official **Price Paid Data**: **31,610,742 transactions**
through **28 August 2026** (the current-year file was last republished on
28 September 2026). The source is free, needs no key and is published under
the Open Government Licence v3.

Each record carries the sale price, transfer date, postcode, the full address
(PAON / SAON / street / locality / town / district / county), property type,
new-build and tenure flags, the Price Paid category and the record status.

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold.** Pay only for the
transactions you receive - the whole 31.6-million-sale corpus stays
searchable, you are never billed for the scan behind it.

### What you get per sale

| field group | fields |
|---|---|
| transaction | `transactionId`, `price`, `dateOfTransfer`, `recordStatus` |
| location | `postcode`, `postcodeArea`, `paon`, `saon`, `street`, `locality`, `town`, `district`, `county` |
| property | `propertyType`, `propertyTypeName`, `newBuild`, `newBuildName`, `tenure`, `tenureName` |
| price paid | `ppdCategory`, `ppdCategoryName` |
| provenance | `refreshedDate` |

Property types: **T** terraced **9,356,460** / **S** semi-detached
**8,625,668** / **D** detached **7,286,665** / **F** flat/maisonette
**5,686,095** / **O** other **655,854**.
Tenure: freehold **24,172,969** / leasehold **7,437,248** / unknown **525**.
New build: **3,296,125** / established **28,314,617**.
Price Paid category: standard **A 29,767,193** / additional **B 1,843,549**
(repossessions, buy-to-let/portfolio transfers, power-of-sale sales).

### Search it

- **Postcode** - `postcode="SW1A"` (541 sales) or a full postcode such as
  `"SW1A 2EP"`, or an area such as `"SW"`. Only postcodes present in the
  England & Wales data resolve.
- **Town** - `town="LEEDS"` (354,922 sales), exact and case-insensitive.
  Also `county` (`"GREATER LONDON"`, `"KENT"`) and `district`
  (`"CAMDEN"`, `"LEEDS"`).
- **Street** - `street="HIGH STREET"` (case-insensitive substring).
- **Price** - `priceFrom=1000000` (466,390 sales of 1m+), `priceTo`.
- **Dates** - `dateFrom` / `dateTo` (YYYY-MM-DD), inclusive. The 2026 file
  alone holds 386,238 sales.
- **Property** - `propertyType` (D/S/T/F/O), `tenure` (F/L/U),
  `newBuild` (Y/N), `ppdCategory` (A/B).
- **Transaction id** - `transactionId` for one exact Price Paid GUID. This is
  an unindexed lookup: it scans the whole corpus and can take several minutes.

### Example inputs

**A postcode** - the valuation starting point.

```json
{ "postcode": "SW1A", "maxResults": 25 }
```

**One town, the last five years**

```json
{ "town": "LEEDS", "dateFrom": "2021-01-01", "dateTo": "2026-12-31", "maxResults": 100 }
```

**Prime London sales** - 1m or more (the county filter keeps the scan small).

```json
{ "county": "GREATER LONDON", "priceFrom": 1000000, "maxResults": 50 }
```

**Leasehold flats in Leeds**

```json
{ "town": "LEEDS", "propertyType": "F", "tenure": "L", "maxResults": 50 }
```

**Average sale price by year** - `mode=aggregate`.

```json
{ "mode": "aggregate", "groupBy": "year" }
```

**Average price by property type**

```json
{ "mode": "aggregate", "groupBy": "propertyType" }
```

### Or roll it up

`mode=aggregate` returns one row per group with the count and the **average
price** - **year**, **propertyType**, **tenure**, **newBuild**,
**ppdCategory**, **county** or **district**. The default (empty) run answers
the whole-dataset year rollup from a small precomputed record.

### Example output

```json
{
 "transactionId": "0C143C97-1739-48C7-B999-AC8E849F66F6",
 "price": "200000",
 "dateOfTransfer": "1995-08-18",
 "postcode": "SW1A 2EP",
 "postcodeArea": "SW",
 "propertyType": "F",
 "propertyTypeName": "Flat / maisonette",
 "newBuild": "N",
 "newBuildName": "No",
 "tenure": "L",
 "tenureName": "Leasehold",
 "paon": "4",
 "saon": "FLAT 127",
 "street": "WHITEHALL COURT",
 "locality": "LONDON",
 "town": "LONDON",
 "district": "CITY OF WESTMINSTER",
 "county": "GREATER LONDON",
 "ppdCategory": "A",
 "ppdCategoryName": "Standard price paid",
 "recordStatus": "A",
 "refreshedDate": "2026-10-18"
}
```

### Notes on the data, from the source

- **One row = one transaction.** The transaction GUID is unique within the
  published yearly files.
- **Price Paid category B is not a normal open-market sale.** 1.84M records
  (5.8%) are additional price-paid entries - repossessions, buy-to-let or
  portfolio transfers, power-of-sale sales. They are included and flagged
  (`ppdCategory="B"`) so you can exclude them with `ppdCategory="A"`.
- **Monthly refresh.** HM Land Registry republishes the current-year file
  around the 20th working day of each month. As of this build the newest
  transfer is **28 August 2026**, in the file last updated 28 September 2026.
  Every record carries `refreshedDate` (the date this corpus was built).
- **Fast lookups.** Postcode, town, county and district filters use a
  precomputed shard index, so they read only the relevant postcode-area
  slices. A street-, price- or date-only query has no index and scans the
  whole corpus - it can take several minutes, so combine it with a town,
  county or postcode.
- **England & Wales only.** Scotland (Registers of Scotland) and Northern
  Ireland (Land & Property Services) publish separate registers and are not
  part of Price Paid Data.
- **Address data.** Addresses derive from Ordnance Survey AddressBase Premium
  and Royal Mail PAF. HM Land Registry's licence permits their use "to display
  for the purpose of providing residential property price information
  services" - which is what this actor does. This is not an address database
  and addresses are not resold as such.
- **Licence.** The Price Paid data is published under the Open Government
  Licence v3 - commercial reuse is permitted, with attribution to HM Land
  Registry. The address fields additionally embed Ordnance Survey AddressBase
  Premium and Royal Mail PAF data, which HM Land Registry is licensed to use
  "to display for the purpose of providing residential property price
  information services". That is the use this actor supports; the addresses
  are not provided as an address database and must not be resold or used for
  address verification. Attribution: HM Land Registry, Ordnance Survey and
  Royal Mail.

Data source: `price-paid-data.publicdata.landregistry.gov.uk` (HM Land
Registry).

# Actor input Schema

## `mode` (type: `string`):

search = transactions matching your filters. aggregate = one row per group with count and average price. Leave blank to auto-route: filters -> search, no filters -> aggregate.

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

Full or partial postcode, e.g. "SW1A 1AA", "SW1A", "SW1", "SW" (area) or "S" (all S areas). Only postcodes present in England & Wales resolve.

## `town` (type: `string`):

Exact town/city as published by HM Land Registry, case-insensitive (e.g. "LONDON", "LEEDS", "BRISTOL").

## `county` (type: `string`):

Exact county as published, e.g. "GREATER LONDON", "KENT", "WEST YORKSHIRE".

## `district` (type: `string`):

Exact district/unitary authority as published, e.g. "CAMDEN", "LEEDS", "CITY OF BRISTOL".

## `street` (type: `string`):

Case-insensitive substring of the street name, e.g. "HIGH STREET".

## `transactionId` (type: `string`):

Exact Price Paid transaction GUID. Unindexed: scans all shards and can take several minutes.

## `propertyType` (type: `string`):

D = detached, S = semi-detached, T = terraced, F = flat/maisonette, O = other. Blank = all.

## `tenure` (type: `string`):

F = freehold, L = leasehold, U = unknown. Blank = all.

## `newBuild` (type: `string`):

Y = newly built property, N = established property. Blank = all.

## `ppdCategory` (type: `string`):

A = standard full-market-value sale; B = additional price paid entries (repossessions, buy-to-let / portfolio transfers, power-of-sale sales, etc.). Blank = all.

## `priceFrom` (type: `number`):

Minimum sale price in pounds, e.g. 500000.

## `priceTo` (type: `number`):

Maximum sale price in pounds, e.g. 2000000.

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

Earliest transfer date (YYYY-MM-DD), inclusive.

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

Latest transfer date (YYYY-MM-DD), inclusive.

## `aggregate` (type: `boolean`):

When on, returns one summary record per group with count and average price, instead of individual transactions.

## `groupBy` (type: `string`):

year -> transfers by year; propertyType; tenure; newBuild; ppdCategory -> standard vs additional; county; district. Blank defaults to year.

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

Cap the number of search records pushed (0 = the default ceiling of 50, maximum 5000). Aggregate returns every group.

## Actor input object example

```json
{
  "aggregate": false,
  "maxResults": 50
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

HM Land Registry Price Paid transactions or aggregate rows - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (type: `string`):

No description

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("j0401/uk-price-paid").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("j0401/uk-price-paid").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 '{}' |
apify call j0401/uk-price-paid --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/uk-price-paid"
        }
    }
}
```

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/WkzYHUIKaTCJwcPS2/builds/Y26KOty4vedYxvXyc/openapi.json
