# UK Sold House Prices | Official Land Registry Data (`alinz/uk-sold-house-prices`) Actor

Real sold prices for UK property from HM Land Registry Price Paid Data - not asking prices. Search 31.5M official transactions by town, district, county or postcode, with date, price, property type, tenure and new-build flags. Includes quarterly market statistics.

- **URL**: https://apify.com/alinz/uk-sold-house-prices.md
- **Developed by:** [אלון זריהן](https://apify.com/alinz) (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 $1.50 / 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?

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 Sold House Prices — Official HM Land Registry Data

What properties **actually sold for**, from HM Land Registry's Price Paid Data — the official record of every registered property sale in England and Wales.

This is not listing data. Portals show what sellers *ask*. This shows what buyers *paid*, as recorded on the transfer deed.

### Coverage

| | |
|---|---|
| Transactions | **31.5 million**, 1995 to present |
| Geography | Every town, district and county in England & Wales |
| Search by | Town, district, county, or postcode prefix |
| Filters | Date range, price range, property type, transaction category |
| Speed | ~4 seconds per month of data queried |

### Who uses this

- **Estate agents and valuers** — comparable evidence for a valuation, with a citable official source.
- **Property investors** — what a street or postcode actually transacts at, before making an offer.
- **Mortgage and credit analysts** — collateral checks and portfolio review against recorded sale prices.
- **Developers and land buyers** — new-build versus resale pricing in a target area.
- **Researchers and journalists** — defensible numbers from the official register.

### Two output modes

**`transactions`** — one row per sale.

```json
{
  "transactionId": "2F7F2B42-A40E-E08F-E063-4804A8C05A49",
  "price": 790000,
  "date": "2025-01-31",
  "address": "41 CHARLTON ROAD",
  "street": "CHARLTON ROAD",
  "locality": "KEYNSHAM",
  "town": "BRISTOL",
  "district": "BATH AND NORTH EAST SOMERSET",
  "county": "BATH AND NORTH EAST SOMERSET",
  "postcode": "BS31 2JG",
  "postcodeArea": "BS31",
  "propertyType": "Semi-detached",
  "tenure": "Freehold",
  "newBuild": false,
  "category": "Standard",
  "isStandardSale": true
}
```

**`stats`** — quarterly medians and quartiles per postcode area and property type. Thousands of sales collapse into a few dozen rows.

```json
{
  "area": "BS1",
  "period": "2025-Q1",
  "propertyType": "Flat/Maisonette",
  "salesCount": 74,
  "minPrice": 92000,
  "p25Price": 230000,
  "medianPrice": 315000,
  "p75Price": 415000,
  "maxPrice": 1150000,
  "meanPrice": 341216,
  "newBuildCount": 12,
  "freeholdCount": 3
}
```

### Examples

**Everything sold in a city last quarter:**

```json
{ "town": "BRISTOL", "dateFrom": "2025-01-01", "dateTo": "2025-04-01" }
```

**One neighbourhood, a price band, flats only:**

```json
{
  "postcodePrefix": "BS8",
  "dateFrom": "2025-01-01",
  "dateTo": "2025-07-01",
  "minPrice": 400000,
  "maxPrice": 900000,
  "propertyTypes": ["flat"]
}
```

**Market trend for a whole postcode area:**

```json
{
  "postcodePrefix": "M",
  "dateFrom": "2023-01-01",
  "dateTo": "2026-01-01",
  "outputFormat": "stats"
}
```

At least one location is required — town, district, county or postcode prefix. An unbounded query would sweep all 31.5M records, so the Actor refuses it rather than running for an hour.

### The category filter matters more than it looks

Land Registry splits sales into two categories, and mixing them quietly corrupts any price analysis:

- **Standard** — an ordinary sale at full market value between private parties.
- **Additional** — repossessions, buy-to-let portfolio transfers, sales to non-private buyers, and property types recorded as "Other". Between **12% and 19%** of records, depending on area and period.

An "average house price" computed over both is not an average house price. This Actor defaults to **standard only** and labels every row with its category, so the choice is explicit rather than accidental.

### Field reference

| Field | Meaning |
|---|---|
| `transactionId` | Land Registry's unique reference for the sale |
| `price` | Sale price on the transfer deed, GBP |
| `date`, `year`, `month` | Date of transfer |
| `address` | SAON + PAON + street, joined |
| `saon` / `paon` | Secondary / primary addressable object (flat number / house number) |
| `street`, `locality`, `town`, `district`, `county` | Address components as recorded |
| `postcode` / `postcodeArea` | Full postcode and its outward code (e.g. `BS31`) |
| `propertyType` | Detached, Semi-detached, Terraced, Flat/Maisonette, Other |
| `tenure` | Freehold or Leasehold (leases of 7 years or less are not registered) |
| `newBuild` | True if newly built at the time of sale |
| `category` / `isStandardSale` | Standard or Additional — see above |
| `sourceUrl`, `scrapedAt` | Provenance |

Statistics mode adds `salesCount`, `minPrice`, `p25Price`, `medianPrice`, `p75Price`, `maxPrice`, `meanPrice`, `newBuildCount`, `freeholdCount`.

### Notes on the data

- **Recent months are incomplete.** Registration lags completion by two weeks to two months. A query ending today will under-report the last few weeks — this is a property of the register, not of this Actor.
- **Deleted and corrected records are already resolved.** The bulk CSV feed carries raw add/change/delete markers that must be applied by hand; this Actor reads the endpoint that serves current state, so superseded sales never appear.
- **Very low prices are real but are not market sales.** A handful of records sit below £1,000 — transfers between related parties, not open-market transactions. Most carry the Additional category, so the default filter removes them.
- **Postcodes are as recorded at the time of sale** and are not updated if the postcode is later reallocated.
- **England and Wales only.** Scotland and Northern Ireland maintain separate registers.

### Source and conduct

Data comes from HM Land Registry's public Price Paid Data via its open SPARQL endpoint at `landregistry.data.gov.uk`. No authentication, no access controls, no scraping of protected pages. Requests are rate-limited and retried politely.

Contains HM Land Registry data © Crown copyright and database right. Licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/). You must preserve this attribution when redistributing the data.

### Integrations

Output lands in a standard Apify dataset: export as **JSON, CSV, Excel or XML**, or connect it to **Make, Zapier, n8n, Google Sheets, Slack**, or your own code via the Apify API. Schedule it to track a market over time.

# Actor input Schema

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

Town or city as recorded by Land Registry, e.g. BRISTOL, MANCHESTER, LONDON. Case-insensitive. At least one location field is required.

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

Administrative district, e.g. CAMDEN, BATH AND NORTH EAST SOMERSET. Use instead of, or together with, town.

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

County, e.g. GREATER LONDON, WEST MIDLANDS. Broadest geographic filter — expect large result sets.

## `postcodePrefix` (type: `string`):

Matches the start of the postcode. 'BS8' returns one outward code, 'BS' returns the whole Bristol area. The most precise way to target a neighbourhood.

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

Earliest transaction date, inclusive. Data starts in 1995. Defaults to 2024-01-01.

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

Latest transaction date, exclusive. Defaults to today. Note the registration lag: the last 1-2 months are always incomplete.

## `minPrice` (type: `integer`):

Optional. Filtered on the server, so it also makes the query faster.

## `maxPrice` (type: `integer`):

Optional. Filtered on the server, so it also makes the query faster.

## `propertyTypes` (type: `array`):

Optional. Leave empty for all types.

## `category` (type: `string`):

'Standard' is an ordinary sale at full market value. 'Additional' covers repossessions, buy-to-let portfolio transfers and other sales never openly marketed — roughly 12-19% of records. Including them will skew any price average, so standard-only is the default.

## `outputFormat` (type: `string`):

'transactions' returns one row per sale. 'stats' aggregates them into quarterly medians and quartiles per postcode area and property type — far fewer rows, ideal for market analysis.

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

Optional cap on rows returned. Useful for a cheap trial run before a large pull.

## `concurrency` (type: `integer`):

Parallel queries against the Land Registry endpoint. 4 is a good default; higher is not necessarily faster, as the endpoint is a shared public service.

## Actor input object example

```json
{
  "town": "BRISTOL",
  "postcodePrefix": "BS8",
  "dateFrom": "2025-01-01",
  "dateTo": "2025-04-01",
  "minPrice": 250000,
  "maxPrice": 750000,
  "propertyTypes": [],
  "category": "standard",
  "outputFormat": "transactions",
  "maxResults": 100,
  "concurrency": 4
}
```

# Actor output Schema

## `results` (type: `string`):

One row per sale in 'transactions' mode, or one row per area x quarter x property type in 'stats' mode.

## `transactions` (type: `string`):

Sale-level view: date, price, full address, postcode, property type and tenure.

## `marketStats` (type: `string`):

Quarterly median, quartiles and sale counts per postcode area and property type.

## `runStats` (type: `string`):

Windows queried, rows fetched and kept, and the input used.

# 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 = {
    "town": "BRISTOL",
    "dateFrom": "2025-01-01",
    "dateTo": "2025-04-01",
    "propertyTypes": [],
    "category": "standard",
    "outputFormat": "transactions"
};

// Run the Actor and wait for it to finish
const run = await client.actor("alinz/uk-sold-house-prices").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 = {
    "town": "BRISTOL",
    "dateFrom": "2025-01-01",
    "dateTo": "2025-04-01",
    "propertyTypes": [],
    "category": "standard",
    "outputFormat": "transactions",
}

# Run the Actor and wait for it to finish
run = client.actor("alinz/uk-sold-house-prices").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 '{
  "town": "BRISTOL",
  "dateFrom": "2025-01-01",
  "dateTo": "2025-04-01",
  "propertyTypes": [],
  "category": "standard",
  "outputFormat": "transactions"
}' |
apify call alinz/uk-sold-house-prices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,alinz/uk-sold-house-prices"
        }
    }
}

```

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/ZeDk3PwekEkym9ayd/builds/P3qbKF7JtdNG8uaqI/openapi.json
