UK Land Registry Price Paid — Valuation & Deal Finder
Pricing
from $2.00 / 1,000 record fetcheds
UK Land Registry Price Paid — Valuation & Deal Finder
Turn HM Land Registry Price Paid data into decisions: fair value, comparable sales, deal-check verdicts, market scores, repeat-sale growth, street rankings and below-market deal finding across England & Wales. Deterministic, no AI, free government data.
Pricing
from $2.00 / 1,000 record fetcheds
Rating
0.0
(0)
Developer
Ryan Clinton
Maintained by CommunityActor stats
0
Bookmarked
13
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share

UK Property Intelligence and Valuation Engine. 30 years of official HM Land Registry sales, turned into decisions.
This actor answers, in one API call:
- ✓ Is this property overpriced?
- ✓ What is fair value?
- ✓ Which streets outperform?
- ✓ Which towns are strongest for investment?
- ✓ Where are the discounted deals?
30 years of official HM Land Registry data. No AI. No spreadsheets. Just answers, every one of them deterministic and reproducible.
Most property tools help you analyse a market. This actor tells you what to do next.
Is this property overpriced?
The killer feature. Pass an asking price and get a fair value from comparable sold prices, plus a verdict:
{ "askingPrice": 320000, "fairValue": 285000, "dealRating": "overpriced", "confidence": 82 }
It does not just show recent sales. It answers the question every buyer asks.
Output in 10 seconds
Input{ "town": "MANCHESTER" }vOutputMarket score: 84 / 100 (excellent)Heat index: 76 / 100 (hot)Market: risingBest street: PARK LANERecommendation: STRONG OPPORTUNITY
Every analysis ends with a recommendation
No interpretation required. Every run returns one decision scalar your team, or your automation, can act on:
STRONG OPPORTUNITY · INVESTIGATE · MONITOR · CAUTION · INSUFFICIENT DATA
Find deals, not just sales
Flip the actor from "search an area" to "find me deals" with analysisMode: "find-deals":
{ "topOpportunities": [ { "address": "14 MILL ROAD", "price": 182000, "opportunityScore": 78 } ] }
Instead of searching for sales, search for opportunities.
Real examples
Buyer: "Is this £320,000 flat overpriced?"
{ "fairValue": 285000, "dealRating": "overpriced" }
Investor: "Which town should I invest in?"
{ "winner": "MANCHESTER", "highestGrowth": "LEEDS" }
Sourcer: "Show me discounted opportunities."
{ "topOpportunities": [ { "price": 182000, "opportunityScore": 78 } ] }
Every recommendation, explained
Every run ends with a recommendation.action. The five values and what they mean:
| Recommendation | Meaning |
|---|---|
strong-opportunity | Rising market, strong score, discounted sales or high activity present |
investigate | Decent market with mixed signals, worth a closer look |
monitor | Unremarkable signals, watch for future movement |
caution | Cooling market or thin transaction volume |
insufficient-data | Sample too small to draw a conclusion |
Questions this actor answers
- Is this property overpriced? Deal-check mode returns a fair value and an underpriced / fair / overpriced verdict.
- What is fair value? The median of comparable sold prices, with the basis and a confidence score.
- Which streets are outperforming? Street rankings, categories and growth over the covered period.
- Which town or postcode is the strongest investment? Compare mode ranks them and names a winner.
- Is this market heating up or cooling down? Market posture, heat index and 3 / 12 / 36-month trends.
- Where are the discounted deals? Find-deals mode ranks below-market sales.
- How reliable is the conclusion? A confidence score with the reasons behind it.
The rest of this page is the proof.
Why this exists
Most Land Registry tools give you transactions. Then you still have to export them, clean them, calculate medians, find comparables, identify outliers and assess market direction by hand.
This actor does that work for you. Instead of rows, it returns decisions.
Before vs after
A plain Land Registry scraper returns a row:
{ "price": 275000, "street": "WHITWORTH STREET", "dateOfTransfer": "2024-06-15" }
This actor returns the decision layer on top of it:
{ "fairValue": 285000, "dealRating": "fair", "marketScore": 84, "heatIndex": 76, "streetRank": 4, "opportunityScore": 91 }

Property portals show what sold. This shows what it means.
| Question | Property portals | This actor |
|---|---|---|
| What sold? | yes | yes |
| What is fair value? | no | yes |
| Which sales are comparable? | no | yes |
| Which streets outperform? | no | yes |
| Which area wins? | no | yes |
| Is it overpriced? | no | yes |
You do not need competitors named to know which tools leave the right-hand column blank.
Used by
Property investors, estate agents, surveyors, property sourcing companies, PropTech platforms and journalists.
- Property investors: find undervalued sales, rank investment locations, analyse repeat-sale growth, compare a portfolio of postcodes.
- Estate agents and surveyors: generate valuation evidence, identify comparable sales, understand street performance.
- PropTech platforms: consume structured market intelligence, automate scoring, branch on the stable enums and alerts.
- Journalists: detect unusual transactions, identify market shifts, compare regions.
Property investor workflow
- Search a postcode or town.
- Get comparable sales (valuation mode).
- Calculate fair value and check an asking price (deal-check mode).
- Identify discounted sales (find-deals mode).
- Assess market momentum, liquidity and cycle stage.
- Rank candidate areas head-to-head (compare mode).
Each step is one input change on the same actor. The output is the next decision, not another spreadsheet.
Why the scoring is trustworthy
No AI, no black box. Every score is a documented formula over the sold prices, so you can audit any number:
Market score = growth + liquidity + price stability + property-type mixDeal rating = asking price vs the median of comparable sold pricesOpportunity score = price vs street median + type median + area medianFair value = median of the closest comparable sold prices (basis stated)Confidence = sample size + months of coverage + data freshness
Same input, same output, every time. Every score ships its components (or reasons) so the math is visible, never hidden.
Designed for automation
Built to drop straight into a pipeline:
- ✓ Stable enums (priceTier, dealRating, recommendation.action, marketDNA, …) that never get renamed within a major version
- ✓ Deterministic scoring (no LLM variability, reproducible runs)
- ✓
recordTypediscriminators so you can filter mixed records (WHERE recordType = 'deal-check') - ✓ A market-summary KV mirror under the
SUMMARYkey - ✓ Workflow-friendly flat JSON, ready for Dify, n8n, Make and Zapier
Why use this actor?
- Official government data source -- queries the HM Land Registry Linked Data API directly, giving you the same authoritative Price Paid Data used by property professionals, solicitors, and estate agents across the UK.
- No API key or account needed -- the underlying data is published under the Open Government Licence v3.0 and is completely free. This actor wraps the API so you never need to learn its query format or handle its linked-data response structure.
- Clean, structured output -- the raw API returns nested objects with language-tagged arrays. This actor flattens and normalizes every record into simple key-value fields, adds a deterministic decision layer (price tier, percentile, vs-median), and returns a market-summary record ready for analysis.
- Automatic pagination -- a single run fetches up to 500 results across multiple API pages without you writing any loop logic.
- Scheduled monitoring -- set up recurring Apify schedules to track property prices in target areas weekly or monthly and feed results into Google Sheets, webhooks, or your CRM automatically.
Key features
- Flexible location search -- filter by postcode, town/city, or street name, with at least one of postcode or town required
- Price range filtering -- set minimum and maximum sale prices in GBP to focus on a specific market segment
- Property type filter -- narrow results to detached, semi-detached, terraced, or flat/maisonette properties
- Date range support -- search within a specific time period using YYYY-MM-DD start and end dates
- 30+ years of data -- access records dating back to January 1995 through to the most recent monthly update
- Structured output with a decision layer -- every transaction includes price, date, full address breakdown, estate type, property type, new build status and transaction category, plus a price tier, percentile and vs-median figure computed across the result set
- Market-summary record -- one run returns the median, affordability bands, price percentiles, by-type breakdown, freehold/leasehold split, new-build ratio, windowed trends (3m/12m/36m), a market score, a heat index, volatility and a market-posture verdict, so you do not have to crunch the rows yourself
- Comparable sales engine -- in valuation mode, every sale is scored for attribute similarity to your subject property (street, type, recency) and the best comparables are ranked, for fast, defensible valuations
- Repeat-sales detection -- any address sold more than once in the result set returns its gain and annualised growth, the classic Land Registry investor analysis
- Pricing-outlier flags -- sales that deviate 35%+ from the local median are flagged with a plain-English reason, surfacing potential bargains and anomalies
- Deal check -- pass an asking price and get a fair-value estimate from comparable sales plus an underpriced / fair / overpriced verdict, the direct answer to "is this overpriced?"
- Opportunity scoring + market DNA + alerts -- every sale is scored for relative value, each market is profiled (growth / cooling / stable, risk, liquidity, maturity), and deterministic detections (rapid-growth, discount-sales, low-liquidity) drop straight into automation
- Multi-area comparison -- pass several towns and get them ranked head-to-head by market score, with a winner, so you can decide where to buy in one run
- Street rankings and a market narrative -- every street is ranked and categorised, and each run returns a plain-English market narrative ready to drop into a report
- Automatic pagination -- fetches up to 500 results across multiple API pages in a single run
- Graceful timeout handling -- if a request takes longer than 60 seconds, the actor returns all results collected so far rather than failing
- Case-insensitive input -- town and street names are automatically uppercased before querying, so you can enter them in any case
- Low resource usage -- runs on 256 MB of memory with typical execution times under 30 seconds
How to use
Using the Apify Console
- Go to the UK Land Registry Price Paid Search actor page on Apify.
- Click Start to open the input configuration form.
- Enter at least a Postcode (e.g.,
SW1A 2AA) or a Town / City (e.g.,LONDON). - Optionally add a street name, price range, property type, or date range to narrow results.
- Set the Max Results (default 50, maximum 500).
- Click Start to run the actor.
- When the run completes, view results in the Dataset tab or export as JSON, CSV, or Excel.
Using the Apify API (JavaScript)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });const run = await client.actor('ryanclinton/uk-land-registry').call({town: 'MANCHESTER',propertyType: 'flat-maisonette',minPrice: 100000,maxPrice: 300000,dateFrom: '2024-01-01',dateTo: '2024-12-31',maxResults: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(`Found ${items.length} transactions`);items.forEach((item) => console.log(`${item.postcode} - ${item.price} GBP - ${item.dateOfTransfer}`));
Using the Apify API (Python)
from apify_client import ApifyClientclient = ApifyClient("YOUR_API_TOKEN")run = client.actor("ryanclinton/uk-land-registry").call(run_input={"town": "MANCHESTER","propertyType": "flat-maisonette","minPrice": 100000,"maxPrice": 300000,"dateFrom": "2024-01-01","dateTo": "2024-12-31","maxResults": 100,})items = list(client.dataset(run["defaultDatasetId"]).iterate_items())print(f"Found {len(items)} transactions")for item in items:print(f"{item['postcode']} - {item['price']} GBP - {item['dateOfTransfer']}")
Input parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
postcode | String | Conditional | -- | Full UK postcode (e.g., SW1A 2AA, M34 3BG). Must be an exact match. At least one of postcode or town is required. |
town | String | Conditional | -- | Town or city name (e.g., LONDON, MANCHESTER). Case-insensitive -- automatically uppercased. At least one of postcode or town is required. |
street | String | No | -- | Street name (e.g., HIGH STREET, PARK LANE). Case-insensitive -- automatically uppercased. |
minPrice | Integer | No | -- | Minimum sale price in GBP. Must be 0 or greater. |
maxPrice | Integer | No | -- | Maximum sale price in GBP. Must be 0 or greater. |
propertyType | String | No | Any | Property type filter. Options: detached, semi-detached, terraced, flat-maisonette. |
dateFrom | String | No | -- | Start date in YYYY-MM-DD format (e.g., 2023-01-01). Data available from 1995-01-01. |
dateTo | String | No | -- | End date in YYYY-MM-DD format (e.g., 2024-12-31). |
maxResults | Integer | No | 50 | Maximum number of results to return. Minimum: 1, Maximum: 500. |
includeMarketSummary | Boolean | No | true | Append a single market-summary record (median/min/max, affordability, percentiles, by-type breakdown, tenure split, new-build ratio, windowed trends, market score, heat index, volatility, transaction activity and a market-posture verdict). Never charged. |
analysisMode | String | No | market | market (transactions + summary + repeat-sales), valuation (ranked comparable sales), investment (emphasises repeat-sale gains, trends, scores), street (street breakdown), deal-check (asking price vs fair value, needs askingPrice), find-deals (ranked below-market sales; opportunity-scan is the legacy alias), transactions (raw rows only). Derived records are never charged. |
askingPrice | Integer | No | -- | Deal-check mode: the asking/listed price to assess. The actor estimates fair value from comparable sales and rates it underpriced / fair / overpriced. |
comparePostcodes | Array | No | -- | Provide 2+ postcodes to rank them head-to-head (portfolio view): strongest/weakest market, highest liquidity, highest growth. Takes precedence over compareTowns. Max 8. |
subjectStreet | String | No | -- | Valuation mode: street of the property you're valuing. Comparables on this street score highest. Defaults to the street filter. |
subjectPropertyType | String | No | -- | Valuation mode: property type you're valuing. Comparables of the same type score higher. Defaults to the propertyType filter. |
compareTowns | Array | No | -- | Provide 2+ towns/cities to rank them head-to-head. The actor searches each, scores its market, and emits an area-comparison record with a winner. Overrides the single-area search. Max 8. |
Example input JSON
{"postcode": "SW1A 2AA","minPrice": 200000,"maxPrice": 1000000,"propertyType": "flat-maisonette","dateFrom": "2020-01-01","dateTo": "2024-12-31","maxResults": 100}
Tips:
- Use full postcodes only -- partial postcodes like
SW1AorM1will not return results. - Combine postcode with street name to find sales on a specific street.
- For high-volume towns like London, always use date filters to keep result sets manageable.
Output

The dataset uses a recordType discriminator so you can filter mixed records downstream (WHERE recordType = 'repeat-sale'):
transaction- one per property sale, with the decision layer belowrepeat-sale- one per address sold 2+ times in the result set, with gain + annualised growthcomparable- ranked comparable sales (valuation mode only)deal-check- asking price vs comparable-derived fair value (deal-check mode only)opportunity-scan- ranked below-market sales (find-deals mode only)summary- one market-summary record per run (carries the recommendation)area-comparison- head-to-head ranking of towns/postcodes (compare mode only)error- a run-level failure record (carriesfailureType)
Each transaction record carries the raw address and sale fields plus deterministic decision fields computed across the result set:
{"recordType": "transaction","schemaVersion": "2.0","transactionId": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890","price": 275000,"priceTier": "above-average","pricePercentile": 72,"vsMedianPct": 18.4,"dateOfTransfer": "2024-06-15","postcode": "M1 4BT","propertyType": "Flat/Maisonette","oldNew": "Established","duration": "Leasehold","paon": "42","saon": "APARTMENT 7","street": "WHITWORTH STREET","locality": "","town": "MANCHESTER","district": "MANCHESTER","county": "GREATER MANCHESTER","categoryType": "Standard price paid","summary": "£275,000 Flat/Maisonette at 42, APARTMENT 7, WHITWORTH STREET, MANCHESTER sold 2024-06-15 (+18.4% vs local median)"}
priceTier, pricePercentile and vsMedianPct position each sale within the result set (not against a national average), so you can sort for the top sales or filter for below-median deals without post-processing.
Output fields
| Field | Type | Description |
|---|---|---|
transactionId | String | Unique transaction identifier assigned by HM Land Registry |
price | Number | Sale price in GBP (pounds sterling) |
dateOfTransfer | String | Date the sale completed, in YYYY-MM-DD format |
postcode | String | Full postcode of the property |
propertyType | String | Detached, Semi-Detached, Terraced, or Flat/Maisonette |
oldNew | String | New build if the property was newly built at the time of sale, otherwise Established |
duration | String | Estate type -- Freehold or Leasehold |
paon | String | Primary Addressable Object Name -- typically the house number or building name |
saon | String | Secondary Addressable Object Name -- typically a flat or apartment number |
street | String | Street name |
locality | String | Locality within the town, if applicable (often empty) |
town | String | Town or city name |
district | String | Local authority district |
county | String | County |
categoryType | String | Standard price paid for normal sales, or Additional price paid for company purchases, repossessions, and non-private transfers |
priceTier | String | Position within the result set: premium, above-average, average, below-average, or budget |
pricePercentile | Number | 0–100 position of the sale price within the result set's price distribution |
vsMedianPct | Number | Signed percentage the sale price sits above/below the result-set median |
streetMedianPrice | Number | Median sale price on this street within the result set |
streetPercentile | Number | 0–100 rank of this street's median among all streets in the result set |
streetRank | Number | Absolute rank of this street by median (1 = highest) among all streets in the set |
streetCategory | String | Street price band: premium / mid-range / budget |
streetTrend | String | Price direction on this street (needs 4+ dated sales): rising / cooling / stable |
vsTypeMedianPct | Number | Signed % the price sits above/below the median of the same property type (apples-to-apples) |
outlier | Boolean | true when the sale price deviates 35%+ from the result-set median |
outlierReason | String | Plain-English reason when outlier is true (e.g. 42% below the local median) |
opportunityScore | Number | 0–100 relative-value signal - how far below comparable medians (street / type / local) the price sits |
opportunityType | String | discounted-sale / below-market / fair / premium / unknown |
opportunityReasons | Array | Plain-English drivers (e.g. 35% below the street median) |
summary | String | Plain-English one-line summary of the sale, ready to quote |
Market summary record
When includeMarketSummary is on, the last record in the dataset (recordType: "summary") aggregates the whole result set so you get the market picture from one run, without exporting and crunching the rows yourself:
{"recordType": "summary","transactionCount": 87,"priceStats": { "min": 95000, "max": 1250000, "mean": 412300, "median": 365000, "p25": 240000, "p75": 520000 },"affordability": { "entryLevelPrice": 165000, "medianPrice": 365000, "premiumPrice": 720000 },"byPropertyType": { "Terraced": { "count": 41, "medianPrice": 310000, "marketSharePct": 47.1, "trend12mPct": 8.2 } },"bestPerformingType": "Detached","fastestGrowingPropertyType": "Terraced","tenureSplit": { "freehold": 52, "leasehold": 35, "unknown": 0 },"newBuildRatio": 0.07,"totalStreets": 122,"dateRange": { "earliest": "2023-01-12", "latest": "2024-11-28" },"marketPosture": "rising","windowedTrends": { "trend3MonthPct": 4.3, "trend12MonthPct": 9.1, "trend36MonthPct": 28.5, "momentum": "accelerating", "cyclePosition": "expansion" },"transactionActivity": { "salesPerMonth": 3.6, "peakMonth": "2024-06", "trend": "increasing", "liquidityScore": 71, "marketDepth": "high" },"marketScore": { "score": 84, "rating": "excellent", "reasons": ["strong price growth", "high transaction liquidity", "diverse property mix"] },"heatIndex": { "index": 76, "classification": "hot" },"priceVolatility": { "coefficientOfVariationPct": 31.2, "stability": "medium" },"marketConcentration": { "top10PctValueSharePct": 22, "concentrationLevel": "low" },"performers": { "bestPerformingStreet": "PARK LANE", "mostActiveStreet": "HIGH STREET", "topGrowthStreets": [ { "street": "MILL ROAD", "growthPct": 31.4 } ], "highestValueSale": { "address": "1, PARK LANE, MANCHESTER", "price": 1250000 } },"marketDNA": { "type": "growth-market", "risk": "medium", "liquidity": "high", "maturity": "expansion" },"repeatSaleInsights": { "count": 7, "medianGainPct": 41.0, "medianAnnualGrowthPct": 6.1, "topGainPct": 162.0 },"alerts": [ { "type": "rapid-growth", "severity": "high", "message": "Prices rising fast (+9.1% over 12 months)." } ],"recommendation": { "action": "strong-opportunity", "priority": "high", "confidence": 88, "reasons": ["rising market with a strong score", "high current activity"] },"marketNarrative": "Hot market (score 84/100, excellent) with rising prices, moderate volatility and increasing transaction activity. Momentum is accelerating.","confidence": { "level": "high", "score": 88, "sampleSize": 87, "coverageMonths": 23, "dataFreshnessDays": 18, "reasons": ["87 comparable sales", "23 months of coverage", "recent transactions available"], "note": "Large sample, market figures are reliable." },"summary": "87 sales - median £365,000; prices rising. Market score 84/100 (excellent), heat 76/100 (hot)."}
| Field | Description |
|---|---|
priceStats | Min, max, mean, median and the 25th/75th percentiles across all sales |
affordability | Entry-level (10th pct), median and premium (90th pct) price points |
byPropertyType | Per type: count, median price, market share % and a 12-month trend |
bestPerformingType / fastestGrowingPropertyType | Highest-median type / highest 12-month growth type |
totalStreets | Distinct streets in the result set |
marketPosture | Deterministic verdict from the price trend: rising, cooling, stable, or insufficient-data |
windowedTrends | 3-, 12- and 36-month price changes plus momentum, cyclePosition and cycleConfidence |
transactionActivity | Sales per month, peak month, activity trend, plus liquidityScore (0–100) and marketDepth |
marketScore | 0–100 desirability composite + rating + reasons (the verdict's "why") |
heatIndex | 0–100 current-activity composite + classification |
priceVolatility | Coefficient of variation (%) and a stability band |
marketConcentration | Share of total value held by the top 10% of sales + a concentration level |
performers | Best/worst/most-active street, top streets by growth, and the highest-value sale (leaderboard) |
marketDNA | Categorical market profile: type, risk, liquidity, maturity |
repeatSaleInsights | Count, median gain %, median annual growth % and top gain % across repeat sales |
alerts | Deterministic detections (rapid-growth, cooling-market, discount-sales-present, …) with severity, for automation |
recommendation | The "what to do" decision scalar: action (strong-opportunity / investigate / monitor / caution / insufficient-data), priority, confidence, reasons |
marketNarrative | Plain-English market summary, ready to paste into a report (no AI) |
confidence | Reliability composite (0–100) + sample size, coverage months, data-freshness days, and the reasons behind the score |
marketScore (desirability) and heatIndex (current activity) are deliberately separate axes - a stable, expensive area scores high on desirability but low on heat; a fast-moving, cheaper area is the reverse. Both ship a components breakdown so the scores are auditable.
The summary record is never charged - it aggregates data you have already retrieved. It is also mirrored to the key-value store under the SUMMARY key.
Repeat-sale records
Where the same address appears more than once in the result set, the actor emits a recordType: "repeat-sale" record showing how its value changed between sales - the single most-requested Land Registry analysis for investors:
{"recordType": "repeat-sale","address": "42, WHITWORTH STREET, MANCHESTER","postcode": "M1 4BT","propertyType": "Flat/Maisonette","saleCount": 2,"previousSale": { "date": "2017-03-01", "price": 185000 },"latestSale": { "date": "2025-04-01", "price": 285000 },"gain": 100000,"gainPct": 54.1,"annualisedGrowthPct": 5.5}
Comparable-sale records (valuation mode)
Set analysisMode: "valuation" and supply a subjectStreet / subjectPropertyType (or rely on the street / propertyType filters). The actor scores every sale by attribute similarity to the subject - same street, same type, recency, same postcode sector - and emits a ranked recordType: "comparable" list. Similarity is scored on attributes, never on price, because price is exactly what you are estimating:
{"recordType": "comparable","rank": 1,"similarityScore": 90,"similarityReasons": ["same street", "same property type", "sold within 12 months"],"price": 292000,"dateOfTransfer": "2024-09-10","postcode": "M1 4BT","street": "WHITWORTH STREET","town": "MANCHESTER"}
Deal-check record (deal-check mode)
Set analysisMode: "deal-check" and an askingPrice, with a postcode/town (and optionally a subjectStreet / subjectPropertyType). The actor estimates a fair value from comparable sold prices and rates the asking price - the direct answer to "is this overpriced?":
{"recordType": "deal-check","askingPrice": 320000,"fairValue": 285000,"differencePct": 12.3,"dealRating": "overpriced","confidence": 82,"basis": "median of 8 comparable sales (same street/type)","comparableCount": 8,"reasons": ["Fair value £285,000 (median of 8 comparable sales (same street/type)).", "Asking £320,000 is +12.3% vs fair value."],"scenarios": {"atAskingPrice": { "price": 320000, "vsFairValuePct": 12.3, "note": "Paying £320,000 is 12.3% above fair value." },"atFairValue": { "price": 285000, "savingVsAskingUsd": 35000, "note": "Negotiating to fair value would save £35,000." }}}
Fair value is derived from comparable sold prices (the same basis a surveyor uses), falling back to the same-type median, then the area median, with the basis and a confidence score stated. It is an estimate from public data, not a formal valuation.
Area-comparison record (compare mode)
Pass compareTowns: ["MANCHESTER", "LEEDS", "LIVERPOOL"] and the actor searches each area, scores its market, and emits a single recordType: "area-comparison" record ranking them - the answer to "which area should I buy in?":
{"recordType": "area-comparison","areaCount": 3,"winner": "MANCHESTER","strongestMarket": "MANCHESTER","weakestMarket": "LIVERPOOL","highestLiquidity": "MANCHESTER","highestGrowth": "LEEDS","areas": [{ "area": "MANCHESTER", "rank": 1, "marketScore": 84, "marketRating": "excellent", "heatIndex": 76, "medianPrice": 365000, "marketPosture": "rising" },{ "area": "LEEDS", "rank": 2, "marketScore": 78, "marketRating": "good", "heatIndex": 64, "medianPrice": 295000, "marketPosture": "rising" },{ "area": "LIVERPOOL", "rank": 3, "marketScore": 72, "marketRating": "good", "heatIndex": 58, "medianPrice": 210000, "marketPosture": "stable" }]}
Pass comparePostcodes instead of compareTowns for a true portfolio view across specific postcodes. Each area's marketPercentile ranks it within the compared set, not against a national baseline (which would require data this actor does not have).
Deal-finder record (find-deals mode)
Set analysisMode: "find-deals" to flip the actor from "search an area" to "find me deals" (opportunity-scan is the legacy alias). It ranks the below-market sales in the result set by opportunityScore and emits a recordType: "opportunity-scan" record:
{"recordType": "opportunity-scan","scanned": 200,"opportunityCount": 12,"topOpportunities": [{ "address": "14, MILL ROAD, MANCHESTER", "postcode": "M19 2AB", "price": 182000, "opportunityScore": 78, "opportunityType": "discounted-sale", "reasons": ["38% below the street median", "21% below the property-type median"] }]}
Use cases
- Property valuation research -- look up historical sale prices for a specific postcode or street to estimate current market value
- Real estate market analysis -- track price trends across towns, districts, or property types over months or years
- Investment due diligence -- compare sale prices in target postcodes before making buy-to-let or development investment decisions
- Estate agent competitor research -- monitor recent sales volumes and prices in your operating area
- Mortgage and lending assessment -- verify recent comparable sales to support property valuations
- Academic and policy research -- analyze housing affordability, regional price disparities, and market cycles using 30+ years of data
- Journalism and investigations -- identify unusual property transactions, such as high-value sales or bulk purchases in specific areas
- Relocation planning -- compare property prices across different towns and property types when deciding where to move
- Portfolio monitoring -- schedule regular runs to track price movements in areas where you own property
- Proptech data pipelines -- feed structured transaction data into property technology platforms, dashboards, or machine learning models
API & integration
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_API_TOKEN")run = client.actor("ryanclinton/uk-land-registry").call(run_input={"postcode": "EC2R 8AH","maxResults": 50,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(f"{item['price']} GBP -- {item['street']}, {item['town']}")
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });const run = await client.actor('ryanclinton/uk-land-registry').call({postcode: 'EC2R 8AH',maxResults: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();items.forEach((item) => console.log(`${item.price} GBP -- ${item.street}, ${item.town}`));
cURL
curl "https://api.apify.com/v2/acts/ryanclinton~uk-land-registry/runs" \-X POST \-H "Content-Type: application/json" \-H "Authorization: Bearer YOUR_API_TOKEN" \-d '{"postcode": "EC2R 8AH","maxResults": 50}'
Integrations
Results can be connected to downstream systems using Apify's built-in integrations:
- Google Sheets -- export transaction data directly to a spreadsheet for analysis
- Webhooks -- trigger HTTP callbacks when a run completes to feed data into your own API
- Zapier / Make -- build automated workflows that process property data without code
- Slack / Email -- receive notifications with summary data after each scheduled run
- Amazon S3 / Google Cloud Storage -- archive datasets for long-term storage and batch processing
Use in Dify
Drop this actor into Dify workflows via the Apify plugin's Run Actor node. Every sale returns classified as structured JSON - priceTier (premium / above-average / average / below-average / budget) plus a pricePercentile your downstream node branches on, and the market-summary record carries a marketPosture verdict (rising / cooling / stable). A generic scraper pointed at the same data returns raw transaction rows; this returns the tier and the market call.
- Actor ID:
ryanclinton/uk-land-registry - Sample input (track a target postcode for above-median sales in a rising market):
{"postcode": "M1 4BT","dateFrom": "2023-01-01","maxResults": 200,"includeMarketSummary": true}
-
Branching example - a Dify if/else node routes on the discriminator and the enums:
recordType == "summary"ANDmarketPosture == "rising"→ send a "market heating up" alertrecordType == "transaction"ANDpriceTier == "premium"→ flag a high-end comparable for valuation reviewrecordType == "transaction"ANDpriceTier == "budget"→ route to a below-market-deal watchlistrecordType == "error"→ branch onfailureType(timeout / parse-error / api-error) to a retry or notify path
-
Opt-in mode: set
includeMarketSummary: falsewhen a workflow only needs the raw classified transactions and not the per-run market verdict.
The priceTier, pricePercentile and marketPosture values are computed deterministically and emitted as stable enums, so a Dify equality match routes on them directly without any LLM rewriting.
How it works

- Input validation -- the actor checks that at least one of
postcodeortownis provided. If neither is set, it returns an error message with usage examples. - Query construction -- search parameters are mapped to the HM Land Registry Linked Data API query format. Town, postcode, and street values are uppercased. Price and date filters are applied as range parameters.
- Paginated fetching -- the actor requests results in pages of 200 from the API, starting at page 0. Each request has a 60-second timeout via AbortController.
- Data transformation -- raw API responses contain nested linked-data objects with language-tagged value arrays. The actor extracts clean string values, maps each transaction to flat output fields, and adds price tier, percentile and vs-median figures computed across the result set.
- Result collection -- transformed records accumulate until the maximum result count is reached or no more pages are available.
- Output -- all collected records are pushed to the Apify dataset for export in JSON, CSV, Excel, or via API.
HM Land Registry datavComparable salesvFair valuevMarket intelligencevRecommendation
The actor wraps the implementation (paginated fetch, linked-data normalisation, deterministic scoring) so you never see it. What you get is the bottom of that flow: a decision.
Performance & cost
| Metric | Value |
|---|---|
| Memory requirement | 256 MB |
| Typical run time (50 results) | 5--15 seconds |
| Typical run time (500 results) | 15--45 seconds |
| API pages per request | Up to 200 results per page |
| Maximum results per run | 500 |
| Estimated cost (50 results) | ~$0.001--$0.005 |
| Estimated cost (500 results) | ~$0.005--$0.015 |
| External API cost | Free (Open Government Licence) |
| API key required | No |
Apify's free tier includes $5 of monthly platform usage, which is sufficient for hundreds of runs. Since the HM Land Registry API is free, you only pay for Apify compute time.
Limitations
- England and Wales only -- the HM Land Registry covers England and Wales. Scotland (Registers of Scotland) and Northern Ireland (Land Registers of Northern Ireland) have separate registries not covered by this actor.
- Full postcodes required -- partial postcodes (e.g.,
SW1AorM1) will not return results. You must provide the complete postcode including the inward code (e.g.,SW1A 2AA). - Residential sales only -- the Price Paid dataset covers residential property transactions. Commercial property sales, transfers at zero value (gifts), right-to-buy sales at a discount, and court-ordered transfers are excluded.
- Data publication lag -- HM Land Registry publishes new data monthly, typically with a lag of several weeks from the actual date of sale. Very recent transactions may not yet be available.
- Maximum 500 results per run -- the actor caps output at 500 results. For larger datasets, run multiple queries with narrower filters (e.g., split by date range or postcode).
- API timeout handling -- if a single API page request exceeds 60 seconds, the actor stops fetching and returns whatever results were already collected. This is rare but can happen with very broad queries.
- No geospatial coordinates -- the output includes addresses and postcodes but not latitude/longitude. Use the Nominatim Geocoder actor to convert postcodes to coordinates.
Responsible use
- Open Government Licence compliance -- the Price Paid Data is published under the Open Government Licence v3.0. You are free to use it for commercial and non-commercial purposes, but you must acknowledge the source: "Contains HM Land Registry data Crown copyright and database right 2025."
- Personal data considerations -- while the dataset does not contain names of buyers or sellers, property addresses combined with sale prices could be used to infer information about individuals. Handle this data with appropriate care and in compliance with applicable privacy laws.
- Fair use of the API -- the Land Registry Linked Data API is a free public service. Avoid running excessively large numbers of concurrent requests. The actor's built-in pagination and result limits help keep usage reasonable.
- Accuracy disclaimer -- while this data comes from an official government source, it should not be used as the sole basis for financial decisions. Always consult qualified professionals for property valuations, mortgage applications, or investment decisions.
- Rate limiting -- if you schedule frequent runs, space them appropriately to avoid placing unnecessary load on the government API. Hourly or daily schedules are reasonable; per-minute schedules are not.
FAQ
What geographic areas does this actor cover? The HM Land Registry Price Paid Data covers residential property transactions in England and Wales only. Scotland and Northern Ireland have separate land registries with their own datasets.
How far back does the data go? The dataset includes transactions from January 1995 to the present. New data is added monthly.
Is the data free to use? Yes. The Price Paid Data is published under the Open Government Licence v3.0. There is no API key required and no charge for accessing the data.
Why am I getting no results for my postcode?
Make sure you are using a complete postcode with both the outward and inward codes (e.g., SW1A 2AA, not just SW1A). Partial postcodes are not supported by the API.
What is the difference between "Standard" and "Additional" category types? "Standard price paid" covers normal residential sales at full market value. "Additional price paid" includes non-standard transactions such as company purchases, repossessions, and transfers to non-private individuals.
What is the difference between "Freehold" and "Leasehold"? Freehold means the buyer owns the property and the land it sits on outright. Leasehold means the buyer owns the property for a fixed term but not the land, which is owned by a freeholder. Flats are typically leasehold; houses are typically freehold.
What do PAON and SAON mean? PAON stands for Primary Addressable Object Name -- usually the house number or building name. SAON stands for Secondary Addressable Object Name -- usually a flat number, apartment name, or unit within a larger building.
Can I search for commercial property sales? No. The Price Paid Data only includes residential property transactions. Commercial property sales are not recorded in this dataset.
How often is the data updated? HM Land Registry publishes updated data monthly. There is typically a lag of several weeks between the date of sale and when the transaction appears in the dataset.
Can I get more than 500 results? The actor caps output at 500 results per run. To retrieve more data, run multiple queries with narrower filters -- for example, split a large town search into separate date ranges or postcode areas.
What property types are available to filter by?
Four types: detached, semi-detached, terraced, and flat-maisonette. Leave the field empty to search all property types.
Does this actor support wildcard or partial matching? No. The Land Registry API requires exact matches for postcodes and performs exact string matching on town and street names. There is no fuzzy or wildcard search.
Related actors
| Actor | Description |
|---|---|
| UK Companies House | Search UK registered companies and directors -- useful for cross-referencing corporate property purchases |
| UK Food Hygiene Ratings | Search food hygiene ratings for UK businesses -- pair with Land Registry data for area due diligence |
| Nominatim Geocoder | Convert postcodes and addresses to geographic coordinates -- map property sales geographically |
| UK Charity Commission | Search registered UK charities -- identify charity-owned properties in specific areas |
| UK Flood Warnings | Monitor Environment Agency flood warnings -- assess flood risk for properties in target postcodes |
| OpenStreetMap POI Search | Find points of interest by location -- evaluate local amenities around properties |