# HM Land Registry Price Paid Scraper (UK Sales) (`knotty_mistveil/hm-land-registry-price-paid`) Actor

Property sales in England and Wales from HM Land Registry Price Paid Data: price paid, transfer date, full address, postcode, property type, tenure, new build.

- **URL**: https://apify.com/knotty\_mistveil/hm-land-registry-price-paid.md
- **Developed by:** [Jason](https://apify.com/knotty_mistveil) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 sale returneds

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

## HM Land Registry Price Paid Scraper (UK Sales)

Pulls property sales in England and Wales from **HM Land Registry Price Paid Data (PPD)** - the official record of every property sold for value and lodged with HM Land Registry since 1 January 1995 - through the two channels HM Land Registry publishes itself: the [linked-data endpoint](https://landregistry.data.gov.uk/app/root/doc/ppd) at `landregistry.data.gov.uk` and the [yearly bulk files](https://www.gov.uk/government/statistical-data-sets/price-paid-data-yearly-file) at `price-paid-data.publicdata.landregistry.gov.uk`. No API key, no account, no browser automation. You get one flat JSON record per sale with the price paid, the date of transfer, the full address in its BS7666 parts and as a single line, the postcode, property type, tenure, new-build flag and the PPD category - filtered by transfer-date window, postcode (full or an outward code such as `CB2`), town, local-authority district, county, property type, tenure, new build, price range and PPD category. The Actor picks whichever channel answers your filters fastest and **returns identical records either way** - a live cross-check of both routes over the same window is part of `npm run test:smoke`.

On 8 September 2026 the published dataset held **31,525,946 transaction records**, the newest transfer being 31 July 2026, with **930,559 sales in the last complete year (2024)** and **323,461 published so far for 2026**.

### What you get

Every record contains:

| Field | Description |
| --- | --- |
| `id` | HM Land Registry transaction unique identifier, e.g. `5834E4E8-7471-29C7-E063-4804A8C015BC`. The bulk files wrap it in braces; this Actor always publishes it without them, so it matches the URL below |
| `source` | `hm-land-registry`, constant |
| `url` | `https://landregistry.data.gov.uk/data/ppi/transaction/{id}/current` - the public record for that transaction |
| `pricePaid` | Price paid in pounds, as an integer. It is the consideration in the transfer deed, exclusive of VAT where the deed separates it |
| `currency` | `GBP`, constant |
| `transferDate` | Date of transfer, `YYYY-MM-DD`. This is the date on the deed, **not** the date HM Land Registry published it |
| `postcode` | Postcode as published, e.g. `CB2 9EF`. `null` for the 0.3% of sales HM Land Registry publishes without one |
| `propertyType` | `Detached`, `Semi-detached`, `Terraced`, `Flat/Maisonette` or `Other` |
| `propertyTypeCode` | The source's own letter: `D`, `S`, `T`, `F`, `O` |
| `newBuild` | `true` when the sale was of a newly built property (the source's old/new field). See *Limits and freshness* - this flag is heavily under-represented in recent months |
| `tenure` | `freehold` or `leasehold` (the source's duration field). Leases of seven years or less are not in PPD at all |
| `paon` | Primary Addressable Object Name: the house number or name, e.g. `84` or `GREENWAY HOUSE` |
| `saon` | Secondary Addressable Object Name: the flat or unit within the building, e.g. `FLAT 8`. `null` when there is none (87% of sales) |
| `street` / `locality` / `town` / `district` / `county` | The rest of the address as HM Land Registry publishes it, in upper case. `town` is the postal town and `district` the local authority, so a sale in Willingham is `town: CAMBRIDGE`, `district: SOUTH CAMBRIDGESHIRE` |
| `address` | The same parts as one line, e.g. `FLAT 8, GREENWAY HOUSE, OTTER CLOSE, TRUMPINGTON, CAMBRIDGE, CB2 9EF`. A numbered PAON runs into the street (`84 HIGH STREET`), a named one takes a comma, and a locality equal to the town is not repeated |
| `category` | PPD category type. `A` = standard price paid: a single residential property sold at full market value. `B` = additional price paid: transfers under a power of sale (repossessions), buy-to-lets identifiable by a mortgage, transfers to non-private individuals, and sales of property typed `Other`. HM Land Registry does not say which of those a `B` record is |
| `recordStatus` | `A` added, `C` changed, `D` deleted. The yearly files carry only `A`; a `C` or `D` can appear on the linked-data route when a record has been corrected |
| `fetchedAt` | ISO timestamp of the run that produced the record |

Records come back **newest transfer first**, so a `maxItems` below the window's volume keeps the most recent sales. The dataset has three views: **Overview** (date, price, address, type, tenure, link), **Address parts** (the BS7666 fields on their own, ready to join to your own address data) and **Sale classification** (type, tenure, new build, PPD category, record status).

### Input

| Input | Type | Default | Description |
| --- | --- | --- | --- |
| `daysBack` | integer | `60` | Look-back window in days on `transferDate`, ending today. Ignored when `dateFrom`/`dateTo` are set. Max 12,000, which reaches 1 January 1995. |
| `dateFrom` | string | - | Start of the transfer-date window, `YYYY-MM-DD`, inclusive. Clamped to `1995-01-01`. |
| `dateTo` | string | today | End of the transfer-date window, `YYYY-MM-DD`, inclusive. |
| `postcodes` | string\[] | none | Full postcodes (`CB2 9EF`, with or without the space) or prefixes: an area (`CB`), an outward code (`CB2`, `SW1A`) or a sector (`CB2 9`). A prefix never cuts a number in half, so `CB2` keeps `CB2 9EF` but not `CB21 4JT`, and `M1` keeps `M1 1AE` but not `M11 1AA`. |
| `towns` | string\[] | `["CAMBRIDGE"]` prefilled | Postal town, exactly as HM Land Registry writes it, case-insensitive. |
| `districts` | string\[] | none | Local authority district: `BIRMINGHAM`, `CITY OF WESTMINSTER`, `SOUTH CAMBRIDGESHIRE`. |
| `counties` | string\[] | none | County: `GREATER LONDON`, `CAMBRIDGESHIRE`, `WEST MIDLANDS`. |
| `propertyTypes` | string\[] | all | `D` detached, `S` semi-detached, `T` terraced, `F` flat/maisonette, `O` other. |
| `tenure` | string | `any` | `freehold`, `leasehold` or `any`. |
| `newBuildOnly` | boolean | `false` | Keep only sales flagged as newly built. |
| `minPrice` / `maxPrice` | integer | none | Price bounds in pounds, inclusive. |
| `categories` | string\[] | both | `A` standard price paid, `B` additional price paid. |
| `route` | string | `auto` | `auto`, `api` (linked-data only) or `csv` (bulk files only). See *Limits and freshness*. |
| `maxItems` | integer | `1000` | Stop after this many sales. You are charged per sale, so this is also the cost cap. Newest transfer first, so a value below the window's volume drops the **oldest** sales in it - and says so (`windowExhausted: false`). |

Filters inside one group are ORed; the groups are ANDed. `{"postcodes": ["CB1", "CB2"], "propertyTypes": ["F"]}` means "a flat in CB1 **or** CB2".

Example - every sale in one town in the last quarter, the fast route:

```json
{ "towns": ["CAMBRIDGE"], "daysBack": 120, "maxItems": 2000 }
```

Example - leasehold flats over £250,000 in two London boroughs, for a comparables table:

```json
{
  "districts": ["CITY OF WESTMINSTER", "CAMDEN"],
  "propertyTypes": ["F"],
  "tenure": "leasehold",
  "minPrice": 250000,
  "daysBack": 365,
  "maxItems": 5000
}
```

Example - the sale history of one address, back to 1995:

```json
{ "postcodes": ["CB2 9EF"], "daysBack": 12000, "maxItems": 500 }
```

Example - everything that sold anywhere in England and Wales in the last complete month:

```json
{ "dateFrom": "2026-07-01", "dateTo": "2026-07-31", "maxItems": 30000 }
```

Bad input fails fast: an unknown property type, tenure, category or route, a malformed postcode, a `minPrice` above the `maxPrice`, or a window whose ends are the wrong way round stops the run with the validation message as its status, before any request is made.

### Output example

A real record from a live run on 8 September 2026 (`{"towns": ["CAMBRIDGE"], "daysBack": 90, "maxItems": 5}`), unedited:

```json
{
  "id": "5834E4E8-7471-29C7-E063-4804A8C015BC",
  "source": "hm-land-registry",
  "url": "https://landregistry.data.gov.uk/data/ppi/transaction/5834E4E8-7471-29C7-E063-4804A8C015BC/current",
  "pricePaid": 580000,
  "currency": "GBP",
  "transferDate": "2026-07-29",
  "postcode": "CB21 4JT",
  "propertyType": "Semi-detached",
  "propertyTypeCode": "S",
  "newBuild": false,
  "tenure": "freehold",
  "paon": "84",
  "saon": null,
  "street": "HIGH STREET",
  "locality": "LINTON",
  "town": "CAMBRIDGE",
  "district": "SOUTH CAMBRIDGESHIRE",
  "county": "CAMBRIDGESHIRE",
  "address": "84 HIGH STREET, LINTON, CAMBRIDGE, CB21 4JT",
  "category": "A",
  "recordStatus": "A",
  "fetchedAt": "2026-09-08T05:39:03.413Z"
}
```

A flat from the same run carries the sub-building name: `"id": "5834E4E8-754F-29C7-E063-4804A8C015BC"`, `"pricePaid": 305000`, `"transferDate": "2026-07-27"`, `"postcode": "CB2 9EF"`, `"propertyType": "Flat/Maisonette"`, `"tenure": "leasehold"`, `"paon": "GREENWAY HOUSE"`, `"saon": "FLAT 8"`, `"address": "FLAT 8, GREENWAY HOUSE, OTTER CLOSE, TRUMPINGTON, CAMBRIDGE, CB2 9EF"`.

Every run also writes a `SUMMARY` record to the key-value store with the resolved window, the filters used, which route and which source files were read, how many rows were scanned and matched, the newest and oldest transfer delivered, the `limitReached` and `windowExhausted` completeness flags, and the attribution statement below.

### Pricing

Pay per result: **US$0.002 per sale delivered** (US$2 per 1,000 sales). You are charged only for records pushed to the dataset; a run that returns nothing costs nothing, and a run that downloads a 56 MB bulk file to find three matching sales is charged for the three. Runs on the Apify free plan are limited by the platform's free-tier usage allowance.

### Data source and licence

- **Linked-data route.** `GET https://landregistry.data.gov.uk/data/ppi/transaction-record.json` with `propertyAddress.postcode` / `propertyAddress.town` / `propertyAddress.district`, `min-transactionDate`, `max-transactionDate`, `min-pricePaid`, `max-pricePaid`, `_pageSize`, `_page` and `_sort=-transactionDate`. Documentation: <https://landregistry.data.gov.uk/app/root/doc/ppd> (read 8 September 2026).
- **Bulk route.** `GET https://price-paid-data.publicdata.landregistry.gov.uk/pp-YYYY.csv`, the yearly files linked from <https://www.gov.uk/government/statistical-data-sets/price-paid-data-yearly-file>, with the long-standing S3 endpoint `http://prod.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-YYYY.csv` as an automatic fallback (byte-identical files, verified 8 September 2026; the S3 host is HTTP-only). The 5.5 GB `pp-complete.csv` is never downloaded.
- **Licence: Open Government Licence v3.0**, <https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/> (read 8 September 2026). HM Land Registry states that under the OGL it "permits you to use the Price Paid Data for commercial or non-commercial purposes".
- **Mandatory attribution.** HM Land Registry requires anyone who uses or publishes Price Paid Data to add this statement, reproduced here exactly as it stands on <https://www.gov.uk/government/statistical-data-sets/price-paid-data-downloads> (page last updated 28 August 2026, read 8 September 2026):

  > Contains HM Land Registry data © Crown copyright and database right 2021. This data is licensed under the Open Government Licence v3.0.

  The year in HM Land Registry's published wording is 2021, and it is reproduced unaltered rather than silently updated. The same string is written into every run's `SUMMARY` record so it travels with the data; it is deliberately **not** repeated on every dataset item, where it would add about 130 bytes to each of them.
- **Third-party rights in the address fields - read this before using the data for marketing.** The OGL does not cover third-party rights, and the address fields (`postcode`, `paon`, `saon`, `street`, `locality`, `town`, `district`, `county`, and therefore `address`) are processed against Ordnance Survey's AddressBase Premium, which incorporates Royal Mail's PAF® database. HM Land Registry states that Royal Mail and Ordnance Survey permit your use of that Address Data "for personal and/or non-commercial use" and "to display for the purpose of providing residential property price information services", and that any other use requires contacting Royal Mail (`address.management@royalmail.com`). The price, date, property type, tenure, new-build flag and category carry no such restriction. Read the current terms yourself before building an address-driven product on it.
- **Personal data.** Price Paid Data contains **no names, emails or phone numbers** - no buyer, seller, owner or agent is identified, and this Actor adds none. HM Land Registry's own position is that "Price Paid Data is not personal information about individuals but property related information", published from the public register of title. A price and date attached to a specific address can still identify a household indirectly, so if you combine it with occupancy data you are the controller of the result: UK GDPR and the Data Protection Act 2018 apply to you, not to HM Land Registry, and HM Land Registry says explicitly that OGL users "have an obligation ... to ensure that their use of the data does not breach the Data Protection Act 2018 or the Privacy and Electronic Communication (EC Directive) Regulations 2003". Direct marketing off the back of this data is your legal risk, and the Address Data restriction above bites first.

### Limits and freshness

- **Update schedule and lag.** HM Land Registry updates Price Paid Data "on the 20th working day of each month". The release current on 8 September 2026 was the July 2026 release, published 28 August 2026, and the newest transfer in it was **31 July 2026** - so a `daysBack` under about 40 returns nothing at all. HM Land Registry puts the gap between sale and registration at "between 2 weeks and 2 months" and warns that "data for the two most recent months is therefore incomplete". Both routes serve the same release: a live run of the same 120-day Cambridge window through each returned **the same 20 CB2 sales with every field identical** (`npm run test:smoke`, 8 September 2026).
- **Recent months under-report new builds.** This is the biggest completeness trap in PPD and it is the source's, not the Actor's. New builds reach the register much later than resales: measured 8 September 2026, `newBuild` is `true` for **9.53% of the 930,559 sales in the settled 2024 file** but only **0.23% of the 323,461 published so far for 2026** - 0.41% for January 2026 falling to 0.02% for July 2026. The back-dated additions in HM Land Registry's own change-only file for August 2026 were **27.7% new builds for 2025 transfer dates**. Use `newBuildOnly` on a window at least a year old, or expect to miss most of them.
- **Volumes, measured 8 September 2026.** England and Wales: **930,559 sales in 2024**; 2026 to date **323,461** (January 52,243, February 55,616, March 55,911, April 44,450, May 46,381, June 46,025, July 22,835 and still filling). The default 60-day window held **12,720** sales. In 2024, 27.1% were semi-detached, 26.9% terraced, 22.7% detached, 17.6% flats and 5.8% `Other`; 23.1% were leasehold and 18.0% were category B. Town of Cambridge: **1,174 sales in 2026 to date**, 353 in a 120-day window, of which 20 were in the CB2 district. A single postcode is small enough to hold its whole history in one page - the full 1995-2026 window for `CB2 9EF` returns 18 sales, the oldest from September 2016.
- **Which route a run takes, and why it matters.** `auto` uses the **linked-data API** when your filters give it a list of full postcodes, or a town, or a district - the three things it answers quickly - and the **yearly bulk files** otherwise (an outward code such as `CB2`, a county on its own, or no area filter). Measured 8 September 2026 against the live endpoint: an exact postcode 1.2 s a page, a town 5-12 s, a district 5-24 s, a county **26 s**, a postcode range scan (which is what an outward code would need) **57-83 s**, and a date window with no area filter at all returned **HTTP 500 after 90 s**. The bulk files sidestep all of that by filtering locally. `route` forces the choice; `route: "api"` with filters the endpoint cannot answer is refused up front rather than run slowly.
- **What the bulk route costs.** One file per calendar year in the window: `pp-2026.csv` is 56 MB / 323,461 rows, `pp-2025.csv` 166 MB / 954,145 rows, `pp-2024.csv` 162 MB. Measured 8 September 2026 on this machine: the whole of England and Wales for the default 60-day window, 1,000 records delivered, **31.8 s**; the same window with every one of its 12,720 records delivered, **108.6 s** (about 117 records a second, most of it the per-record write); a two-year window (`pp-2025` + `pp-2026`, 1,277,606 rows scanned) delivering 786 Cambridge sales, **60.8 s**. A window spanning more than six calendar years is refused with a message telling you to narrow it or add a town, district or full postcode. The yearly files are used rather than HM Land Registry's smaller monthly change-only file (`pp-monthly-update-new-version.csv`, 17.7 MB / 101,600 rows on 8 September 2026) because, in HM Land Registry's words, "the single large file and yearly files have amendments and/or deletions applied to the data, ensuring the data is complete, up to date and accurate", whereas the monthly file is a feed of A/C/D changes a consumer has to apply for itself.
- **API paging.** The linked-data endpoint caps a page at **200 items** whatever `_pageSize` asks for, so this Actor requests 200 and pages until the endpoint returns a short page. Offset paging is consistent: six pages of a full-year Cambridge query returned **1,174 items with no duplicate and no gap**, exactly matching the 1,174 rows for that town in `pp-2026.csv`. Each area value is its own page walk, and at most 25 values are allowed in one run.
- **Rate limits and errors.** HM Land Registry documents no rate limit for the linked-data endpoint. Six consecutive page requests all returned HTTP 200, but requests issued while an earlier expensive query was still running came back **HTTP 429** - it behaves like a concurrency guard rather than a request-per-second limit, so this Actor never issues two requests at once. 429, 500 and 5xx responses are retried with exponential back-off, honouring `Retry-After`; a page that keeps timing out ends the run with a message telling you to narrow the window or the area rather than a bare HTTP status. A bulk file that fails on the HTTPS host is retried on HM Land Registry's S3 endpoint, and rows already read are recognised as duplicates rather than delivered twice.
- **`windowExhausted` is the completeness signal.** It is `true` only when every source the run needed was read to the end **and** every matching record was delivered. When `maxItems` (or your spend limit) cuts the result short, the run warns `the OLDEST transfers in the window are the ones missing` and `SUMMARY` carries `limitReached: true`, `windowExhausted: false`, and `matched` - the number of records that actually matched your filters - so you can see exactly how much you did not buy.
- **What PPD leaves out**, in HM Land Registry's own words: sales not lodged for registration, sales not for value, right-to-buy sales at a discount, transfers subject to an existing mortgage, transfers of a share (for example on divorce), gifts, compulsory purchases, court orders, transfers to trustees, and vesting deeds covering more than one property. Commercial transactions whose deed states a price *inclusive* of VAT are excluded entirely. So an absent sale is usually a real exclusion, not a missing record.
- **Corrections happen in place.** HM Land Registry amends and deletes records in later releases, and a transaction that changes PPD category is deleted under its old id and re-added under a **new** id. Re-run an overlapping window rather than assuming a transaction id is permanent, and treat `recordStatus` other than `A` as a record that has been revised.
- **Address quirks.** In the settled 2024 file, 0.30% of sales have no postcode, 1.6% have no street and 13.1% carry a SAON. Text is published in upper case and is passed through unchanged rather than re-cased, so `ST JOHN'S` is not mangled. Property characteristics are recorded as at registration, so a house later converted into flats keeps the old type on its old sale.

### Use cases

- **Comparable-sales and valuation tools.** Pull every sale in a postcode district or town over a date window with type, tenure and new-build already on the record, and build the comparables table an agent, surveyor or lender actually uses - the display purpose Royal Mail and Ordnance Survey explicitly permit for the address fields.
- **Local market research and dashboards.** A scheduled monthly run over a district or county tracks volumes and price distributions by property type and tenure, with `category` letting you separate ordinary sales from repossessions and portfolio transfers instead of quietly averaging them together.
- **Property data pipelines and enrichment.** Join `id` to HM Land Registry's own UPRN and INSPIRE ID lookup tables, or match on the BS7666 address parts, to attach a verified sale price and date to your own property records - a full historical download is `{"dateFrom": "1995-01-01", "dateTo": "1995-12-31", "maxItems": 100000}` repeated a year at a time.

### Support

Open an issue on the Actor's Issues tab on Apify Store. Replies within 14 days. Bug reports that name the run id and the input used are fixed fastest.

# Actor input Schema

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

Look-back window in days on the date of transfer, ending today. Ignored when Date from / Date to are set. Price Paid Data lags the market: on 8 September 2026 the newest transfer published was 31 July 2026, so a window shorter than about 40 days can be empty. The data starts on 1 January 1995, so 11600 reaches the beginning.

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

Start of the transfer-date window, YYYY-MM-DD (inclusive). Overrides Days back. Clamped to 1995-01-01.

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

End of the transfer-date window, YYYY-MM-DD (inclusive). Defaults to today.

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

Full postcodes (CB2 9EF) or prefixes: an area (CB), an outward code / postcode district (CB2, SW1A) or a sector (CB2 9). A prefix never cuts a number in half, so CB2 keeps CB2 9EF but not CB21 4JT. A list of full postcodes is answered by the fast linked-data route; a prefix needs a town or district alongside it, or it falls back to the bulk files. Empty = no postcode filter.

## `towns` (type: `array`):

Town or city exactly as HM Land Registry writes it, case-insensitive: CAMBRIDGE, LONDON, MANCHESTER, LEEDS. This is the postal town, not the council: a sale in Willingham is published with town CAMBRIDGE and district SOUTH CAMBRIDGESHIRE. Empty = all towns.

## `districts` (type: `array`):

District as HM Land Registry writes it, case-insensitive: BIRMINGHAM, CITY OF WESTMINSTER, SOUTH CAMBRIDGESHIRE, LEEDS. Empty = all districts.

## `counties` (type: `array`):

County as HM Land Registry writes it, case-insensitive: GREATER LONDON, CAMBRIDGESHIRE, WEST MIDLANDS. A county on its own always uses the bulk-file route, because the linked-data endpoint needs 26 s a page for one. Empty = all counties.

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

HM Land Registry's own property-type letters. Note that 'Other' covers property that is not one of the four residential types - typically commercial or agricultural land sold for value. Empty = all types.

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

Freehold or leasehold, from HM Land Registry's duration field. Leases of seven years or less are not in Price Paid Data at all.

## `newBuildOnly` (type: `boolean`):

Keep only sales HM Land Registry flags as a newly built property (the old/new field). Use it with a settled window, not a recent one: new builds reach the register far later than resales, so they are 9.5% of the 930,559 sales in the complete 2024 file but only 0.2% of the 323,461 sales published so far for 2026 (measured 8 September 2026).

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

Keep only sales at or above this price, in pounds. Empty = no lower bound.

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

Keep only sales at or below this price, in pounds. Empty = no upper bound.

## `categories` (type: `array`):

A = standard price paid data: a single residential property sold for value at full market value. B = additional price paid data: transfers under a power of sale (repossessions), buy-to-lets identifiable by a mortgage, transfers to non-private individuals, and sales where the property type is 'Other'. Category B was 18.0% of the 930,559 sales in the complete 2024 file (measured 8 September 2026). Empty = both.

## `route` (type: `string`):

Which HM Land Registry source to read. Auto picks the linked-data API when the filters include a list of full postcodes, or a town or district, and the yearly bulk CSV files otherwise. Force 'csv' to make a run reproducible from the published files; force 'api' to refuse a run that would download a bulk file.

## `maxItems` (type: `integer`):

Stop after this many sales. You are charged per sale delivered, so this is also the cost cap. Results are newest transfer first, so a value below the window's volume drops the OLDEST sales in it, and the SUMMARY record's windowExhausted flag goes false. Measured 8 September 2026: the default 60-day window held 12,720 sales across England and Wales, because the publication lag leaves the newest weeks of any window empty; a complete calendar month is 44,000 to 56,000 sales, and the town of Cambridge over 120 days is 353.

## Actor input object example

```json
{
  "daysBack": 60,
  "postcodes": [],
  "towns": [
    "CAMBRIDGE"
  ],
  "districts": [],
  "counties": [],
  "propertyTypes": [],
  "tenure": "any",
  "newBuildOnly": false,
  "categories": [],
  "route": "auto",
  "maxItems": 1000
}
```

# Actor output Schema

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

All price paid transactions returned by the run, one JSON object each, newest transfer first. Append ?format=csv or ?format=xlsx to download a spreadsheet.

## `summary` (type: `string`):

Counts, the transfer-date window used, which access route and source files were read, the completeness flags, and the Open Government Licence attribution this data must be published with.

# 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 = {
    "daysBack": 60,
    "postcodes": [],
    "towns": [
        "CAMBRIDGE"
    ],
    "districts": [],
    "counties": [],
    "propertyTypes": [],
    "tenure": "any",
    "newBuildOnly": false,
    "categories": [],
    "route": "auto",
    "maxItems": 1000
};

// Run the Actor and wait for it to finish
const run = await client.actor("knotty_mistveil/hm-land-registry-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 = {
    "daysBack": 60,
    "postcodes": [],
    "towns": ["CAMBRIDGE"],
    "districts": [],
    "counties": [],
    "propertyTypes": [],
    "tenure": "any",
    "newBuildOnly": False,
    "categories": [],
    "route": "auto",
    "maxItems": 1000,
}

# Run the Actor and wait for it to finish
run = client.actor("knotty_mistveil/hm-land-registry-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 '{
  "daysBack": 60,
  "postcodes": [],
  "towns": [
    "CAMBRIDGE"
  ],
  "districts": [],
  "counties": [],
  "propertyTypes": [],
  "tenure": "any",
  "newBuildOnly": false,
  "categories": [],
  "route": "auto",
  "maxItems": 1000
}' |
apify call knotty_mistveil/hm-land-registry-price-paid --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,knotty_mistveil/hm-land-registry-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/U9AM3wdc5cXyed15p/builds/X3S3Z7UwyigueZUw1/openapi.json
