Sold Prices Forensics — Cross-Border Comp Data API
Pricing
from $6.00 / 1,000 sold-price comparable extracteds
Sold Prices Forensics — Cross-Border Comp Data API
Pull historical sold-price comparables across US (Zillow) and UK (Rightmove + Zoopla) in a single normalized dataset. Per-address forensic lookup, area sweep for comps, native currency declared per row. Built for appraisers, RICS surveyors, mortgage underwriters, cross-border investors.
Pricing
from $6.00 / 1,000 sold-price comparable extracteds
Rating
0.0
(0)
Developer
SIÁN OÜ
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Sold Prices Forensics — US + UK Comparable-Sales Data API 🚀
🎉 Sold prices across US + UK in one CSV — Zillow, Rightmove + Zoopla in a single normalized dataset
Built for appraisers, RICS surveyors, mortgage underwriters, AVM teams and cross-border investors who need forensic comparable-sales data with currency declared per row.
📋 Overview
The Sold Prices Forensics Scraper turns three historical sold-price sources into one valuation-grade dataset. Drop in a US address, a UK postcode, or a neighbourhood name and pull every recorded sale event in a normalized schema — one row per address-date-price — ready for AVM regression, Red Book appraisal, or cross-border thesis work.
Unlike consumer-grade "sold homes near me" scrapers, this actor is built for the appraisal and underwriting persona: repeat-sale rows preserved, native currency declared per row, subject-property summaries joinable by stable upstream ID, and a regulated-buyer pricing posture that passes procurement.
Why valuation professionals choose us:
- ✅ Cross-border in one run: Zillow (US) + Rightmove (UK) + Zoopla (UK) in a single dataset — no other actor on Apify Store ships more than one historical sold-price source.
- ⚡ Forensic per-address lookup: pinpoint mode for a single subject property's full sale history — the dataset RICS surveyors build by hand in a day.
- 🎯 Normalized schema across 3 platforms: every row carries the same 20 columns. No JOINs, no schema reconciliation, no per-source parsers.
- 💰 Regulated-buyer pricing: BRONZE $0.012/row matches the proven premium tier in this category — high enough to clear compliance, low enough that bulk runs still pay back. FREE tier: 25 rows per run, full feature access, no credit card.
- 💎 Repeat-sale rows preserved: properties with multiple historical sales (the Case-Shiller pattern) emit one row per sale, keyed by
sourceId + saleDate. - ✨ Currency-explicit output: every row tags
currency(USDorGBP) andcountry(usoruk). You own the FX step, on your terms.
✨ Features
- 🏠 byAddress mode (US + UK) — per-property forensic lookup. Auto-detects the country from the address and queries the right source.
- 🗺 byArea mode (UK) — comparable-sales sweep over a UK neighbourhood, town, or postcode (Hampstead, SW1A, Manchester, Oxford).
- 🔁 Repeat-sale rows — Zoopla's historic sale series emits one row per sale event. Same property, different date, separate row.
- 📌 Subject-address summary row —
byAddressmode adds a joinable summary row per resolved address carrying property attributes (UPRN, ZPID, beds, baths, tenure). - 💱 Native currency per row — USD or GBP declared explicitly. No silent FX, no guessing.
- 📅 Year-range filter —
yearFrom/yearTobound the sale-year window across all platforms in one filter. - 🌍 Cross-platform deduplication signal —
sourcePlatformcolumn lets you filter to one source or compare overlap. - 🔁 Auto-pagination — drains UK area sweeps until exhausted, respects
maxResultscap and FREE-tier safety net. - 📊 20-field normalized schema — same shape across Zillow, Rightmove and Zoopla rows.
- 🧮 Derived sqft for Zillow — computes
squareFeetfromsalePrice / pricePerSquareFootwhen both values are present.
🎬 Quick Start
So simple no training is needed. Pick a search mode, drop in addresses or areas, click Run.
curl -X POST https://api.apify.com/v2/acts/sian.agency~sold-prices-forensics-scraper/runs?token=[YOUR_TOKEN] \-H 'Content-Type: application/json' \-d '{"searchMode": "byAddress", "addresses": ["48 Elsworthy Road, London NW3 3BU"]}'
🚀 Getting Started (3 Simple Steps)
Step 1: Pick a Search Mode
Choose byAddress for a per-property forensic lookup (US or UK), or byArea for a UK comparable-sales sweep over a neighbourhood, town, or postcode.
Step 2: Drop in Addresses or Areas
Paste full property addresses (one per line) for byAddress, or area names / postcodes for byArea. The country is auto-detected — US ZIP and state codes route to Zillow, UK postcodes to Zoopla and Rightmove.
Step 3: Click Run
One click and the actor stitches all enabled sources together. Results stream to your Apify dataset live.
That's it! In under a minute, you'll have:
- One row per address-year-price across Zillow, Rightmove and Zoopla
- Native currency declared on every row (USD or GBP)
- Stable upstream IDs (UPRN, ZPID, Rightmove record id) for joining repeat sales
- Property attributes (beds, baths, tenure, type) where the source publishes them
- A subject-address summary row per
byAddressquery (for joining attributes to sales) - Export-ready data for AVM regression, Red Book appraisal, or insurance valuation
📥 Input Configuration
| Field | Type | Required | Description |
|---|---|---|---|
| searchMode | string | Yes | byAddress (per-property forensic lookup, US + UK) or byArea (UK comparable-sales sweep) |
| platforms | array | No | Subset of zillow, zoopla, rightmove. Defaults to all that apply for the chosen mode |
| addresses | array | byAddress | Full property addresses to look up. Country auto-detected from address |
| areas | array | byArea | UK area names, towns, postcodes, or outcodes to sweep for comps |
| soldInYears | integer | No | Restrict Rightmove results to the last N years (1, 3, 5, 10) |
| yearFrom | integer | No | Only return sales where the sale year ≥ this value |
| yearTo | integer | No | Only return sales where the sale year ≤ this value |
| maxResults | integer | No | Total row cap across all queries and platforms (default 200, FREE tier capped at 25) |
Example — per-address forensic lookup:
{"searchMode": "byAddress","addresses": ["48 Elsworthy Road, London NW3 3BU","1875 AVONDALE Circle, Jacksonville, FL 32205"]}
Example — UK area sweep with year window:
{"searchMode": "byArea","areas": ["Hampstead", "SW1A"],"yearFrom": 2020,"yearTo": 2024,"maxResults": 1000}
📤 Output
Results are saved to the Apify dataset with 20+ fields including the cross-platform disambiguation field sourcePlatform:
| Field | Type | Description |
|---|---|---|
| sourcePlatform | string | zillow, zoopla, or rightmove — the source platform that produced this row. Key disambiguation field for cross-platform overlap (the same UK sale can appear in both Rightmove and Zoopla rows) |
| country | string | us or uk |
| currency | string | USD or GBP — declared explicitly, no FX applied |
| address | string | Verbatim property address from the upstream source |
| postcode | string | Postal / ZIP code (preserved where the source publishes one) |
| sourceId | string | Stable upstream property id — UPRN (Zoopla), record id (Rightmove), or ZPID (Zillow). Primary key for joining repeat sales |
| sourceUrl | string | Deep link to the source listing or history page |
| saleDate | string | ISO sale date YYYY-MM-DD |
| year | integer | Year of sale, derived from saleDate |
| salePrice | number | Sale price in native currency (see currency field) |
| pricePerSquareFoot | number | Price per sqft at time of sale (Zillow only — UK sources do not publish sqft historically) |
| squareFeet | integer | Floor area in sqft (Zillow rows, derived from salePrice / pricePerSquareFoot) |
| propertyType | string | Property type as classified by the source (DETACHED, FLAT, Purpose Built Flat, ...) |
| bedrooms | integer | Bedroom count |
| bathrooms | integer | Bathroom count |
| tenure | string | UK tenure — Freehold, Leasehold, Share of Freehold |
| lat | number | Latitude (when the source publishes coordinates) |
| lon | number | Longitude (when the source publishes coordinates) |
| queryInput | string | Verbatim address or area the user supplied that produced this row — lets you trace every row back to its input |
| scrapedAt | string | ISO timestamp when this row was scraped |
| _summary | boolean | true for the per-address subject-property summary row (one per resolved byAddress query) |
Example row:
{"sourcePlatform": "zoopla","country": "uk","currency": "GBP","address": "48 Elsworthy Road, London NW3 3BU","postcode": "NW3 3BU","sourceId": "5189141","sourceUrl": "https://www.zoopla.co.uk/property-history/48-elsworthy-road-london-nw3-3bu/","saleDate": "2019-04-09","year": 2019,"salePrice": 28500000,"pricePerSquareFoot": null,"squareFeet": null,"propertyType": "Detached","bedrooms": 8,"bathrooms": 9,"tenure": "Freehold","lat": 51.5436632,"lon": -0.1558471,"queryInput": "48 Elsworthy Road, London NW3 3BU","scrapedAt": "2026-05-21T08:47:00Z"}
💼 Use Cases & Examples
1. Mortgage Underwriting Comparables
Underwriters and AVM teams generating 12-month comp packs for a subject property's neighbourhood.
Input: A US ZIP / state location or a UK area (Hampstead, SW1A) in byArea mode + a yearFrom window covering the trailing 12 months.
Output: One CSV of recent sold rows with price, beds, baths, sqft (where available), and lat/lon — currency declared per row.
Use: Drop directly into your AVM regression pipeline or hedonic model — no schema mapping, no FX assumptions.
2. RICS Red Book Appraisal
RICS surveyors building Red Book valuations for UK subject properties.
Input: Subject property address in byAddress mode (e.g. 48 Elsworthy Road, London NW3 3BU), optionally followed by the surrounding postcode area in byArea mode.
Output: Full UPRN-keyed sale history for the subject + recent area comps with property attributes.
Use: Replaces the day of manual Land Registry / portal scraping that traditionally precedes a Red Book valuation.
3. Cross-Border Investment Thesis
Investors comparing 10-year price velocity across US and UK markets.
Input: A US area + a UK area in the same run, with yearFrom: 2014.
Output: Normalized rows from both markets in one CSV, each tagged with currency and country.
Use: Build the cross-border price-velocity chart your London Hampstead vs. Brooklyn DUMBO IC deck needs — without juggling five scrapers.
4. AVM Model Training Data
Data scientists training valuation models across multiple markets.
Input: A list of areas + a multi-year yearFrom/yearTo window + maxResults: 50000.
Output: Bulk sold-price comparables (price, sqft where available, beds, baths, lat/lon, property type) ready for feature engineering.
Use: No per-source parser code, no CSV schema reconciliation — features land in the same columns.
5. Insurance Reinstatement & Probate Valuation
Insurance valuers and probate solicitors pulling historical sale data for properties no longer listed.
Input: The subject property address in byAddress mode.
Output: Full historical sale series for the address (often the only reference value for executor sales and damage claims).
Use: Provides the legal benchmark "last recorded sale" figure that probate and reinstatement work routinely require.
6. Property Price History Research
Journalists, researchers, and market analysts tracking neighbourhood-level price evolution.
Input: A neighbourhood or postcode in byArea mode + a multi-year window.
Output: Every recorded sale in the area over the window — preserves repeat sales of the same property.
Use: Quantify the gentrification curve, build a price index, or fact-check market commentary.
7. Real Estate Comparables for Tax Appeals
Property tax consultants assembling comp evidence for assessment appeals.
Input: Subject address + surrounding area in two queries. Output: Sale-price evidence at the address level + comparable-sales context. Use: Standard format ready to package as exhibits for an assessment appeal filing.
🔗 Integration Examples
JavaScript / Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('sian.agency/sold-prices-forensics-scraper').call({searchMode: 'byArea',areas: ['Hampstead', 'SW1A'],yearFrom: 2020,maxResults: 500});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items[0]);
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_TOKEN')run = client.actor('sian.agency/sold-prices-forensics-scraper').call(run_input={'searchMode': 'byAddress','addresses': ['48 Elsworthy Road, London NW3 3BU'],})for item in client.dataset(run['defaultDatasetId']).iterate_items():print(item['sourcePlatform'], item['saleDate'], item['salePrice'], item['currency'])
cURL
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~sold-prices-forensics-scraper/runs?token=YOUR_TOKEN' \-H 'Content-Type: application/json' \-d '{"searchMode": "byArea", "areas": ["Hampstead"], "maxResults": 100}'
Automation Workflows (N8N / Zapier / Make)
- Trigger: Schedule (weekly comp refresh) or webhook (subject-property lookup on demand)
- HTTP Request: Call the actor's run-sync-get-dataset-items endpoint with your address or area list
- Process: Filter by
sourcePlatform,year, orcurrencyas the workflow requires - Action: Push to Google Sheets, Snowflake, Airtable, your CRM, or your AVM pipeline
📊 Performance & Pricing
FREE Tier (Try It Now)
- 25 rows per run — full feature access, same normalized schema, same fields
- No credit card required
- Perfect for evaluating fit before a production rollout
- Real opportunity to validate the schema against your AVM / appraisal workflow at zero cost
PAID Tier (Production Ready)
- Unlimited rows per run, capped only by your
maxResults - Bulk-friendly pricing: bigger runs unlock cheaper per-row pricing through SILVER → DIAMOND tiers
- Pay-per-event: you only pay for the rows you actually receive
- Native bulk auto-pagination across UK area sweeps
💰 Regulated-buyer pricing posture — BRONZE $0.012/row matches the proven premium tier in the sold-prices category. Bulk runs taper through SILVER ($0.009), GOLD ($0.006), PLATINUM ($0.0048), DIAMOND ($0.0036) per row.
🔗 View current pricing on the Apify Store
❓ Frequently Asked Questions
Q: How many rows can I process in a run?
A: FREE tier: 25 rows per run. PAID tier: unlimited, capped only by your maxResults input.
Q: Why isn't Redfin included?
A: Redfin's historical sold-prices endpoint returns redacted prices through this data path — the price field is returned as a redaction marker rather than a numeric value, which makes the data unusable for forensic valuation work. We chose to ship a smaller, honest v1.0 (3 reliable platforms) rather than include a fourth source that silently degrades downstream pipelines. If the redaction lifts in future, Redfin coverage is on the v1.1 backlog.
Q: Why isn't Idealista (Spain / Italy / Portugal) included? A: Idealista does not expose a unit-level historical-transactions endpoint. Spanish, Italian and Portuguese public records do not publish per-property sold prices the way the UK Land Registry or US MLS systems do. There is no data source to wrap. If a historical endpoint becomes available, EU coverage is on the v1.1 backlog.
Q: Are sale prices converted to a common currency?
A: No — output is always in native currency (USD or GBP), with the currency column declared explicitly per row. This is a deliberate design decision: cross-border buyers (the primary audience) typically need both native and converted values, and FX-conversion conventions vary by use case (transaction-date FX vs. report-date FX vs. period-average FX). You own the conversion step on terms that match your pipeline.
Q: Will I see the same UK sale twice (in both Rightmove and Zoopla)?
A: Yes, by design. Both Rightmove and Zoopla source UK sold prices from the Land Registry, so the same sale event will sometimes appear in both feeds. The sourcePlatform column lets you filter to a single source (e.g. sourcePlatform == 'zoopla') if you want one row per sale, or keep both rows to cross-check the data. Repeat-sale rows of the same property at different dates are kept as separate rows on purpose — that pattern is what Case-Shiller-style analysis requires.
Q: How accurate is the data?
A: Sale-event accuracy is bound by the upstream sources. UK rows ultimately trace back to HM Land Registry data and are authoritative. US Zillow rows reflect Zillow's price-history feed and accuracy varies by market. All rows preserve the upstream sourceUrl so you can spot-check anything that looks off.
Q: Is this legal? A: Yes — only publicly available sale records are extracted. UK Land Registry sold-prices are public information; US Zillow price history is published on public listing pages. See our Legal section below.
Q: How long does a run take?
A: A per-address forensic lookup typically returns in 5–15 seconds. A UK area sweep paginates through the source, so runtime scales with maxResults (a 1000-row Hampstead sweep usually finishes inside 60 seconds).
🐛 Troubleshooting
No rows returned for a UK address.
- Confirm the postcode is included in the address string — Zoopla's per-address endpoint matches more reliably with the postcode present.
- Check that the address has actually recorded sales (some properties have never transacted, especially newer builds).
- Try the same property in
byAreamode (e.g. just the postcode) — area sweeps draw from a larger feed.
A US address returns no rows.
- Verify the address resolves on Zillow itself — if Zillow doesn't recognise the address, the actor can't pull its price history.
- Confirm the address ends with a recognisable state code + ZIP (e.g.
..., FL 32205).
The same sale appears twice.
- That's the cross-source overlap between Rightmove and Zoopla. Filter on
sourcePlatformto keep one source, or treat duplicates as cross-validation.
FREE tier capped before I expected.
- FREE tier hard-caps at 25 total rows per run. For production volumes, upgrade to PAID — pricing scales with usage and bulk runs unlock SILVER → DIAMOND tier rates.
A row has _summary: true and no salePrice.
- That's the subject-address summary row that
byAddressmode emits per resolved query. It carries property attributes (UPRN/ZPID, beds, baths, tenure) and the resolved address. Filter it out with_summary !== trueif you only want sale events.
⚖ Is it legal to scrape data?
Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the property listing portals have chosen to share publicly — historical sold prices in the UK are published by HM Land Registry as a matter of public record, and US sale histories on Zillow are surfaced on public listing pages. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.
However, you should be aware that your results could contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.
You can also read Apify's blog post on the legality of web scraping.
🛡 Trademark Disclaimer
This actor is an independent tool built by SIÁN Agency. It is not affiliated with, endorsed by, or sponsored by Zillow Group, Rightmove plc, Zoopla, Redfin Corporation, or any of their subsidiaries. "Zillow", "Rightmove", "Zoopla" and "Redfin" are trademarks of their respective owners and are used here only for nominative descriptive purposes — to identify the public data sources this actor reads. All product names, logos, and brands referenced in this documentation are the property of their respective owners.
🤝 Support
Join our active support community
- For issues or questions, open an issue on the actor's Apify page
- Check the SIÁN Agency Store for more real-estate automation tools
- 📧 apify@sian-agency.online
Built by SIÁN Agency | More Tools