Zoopla Property Scraper (UK)
Pricing
from $0.56 / 1,000 results
Zoopla Property Scraper (UK)
Scrapes property listings for sale or rent from Zoopla, the UK's #2 property portal. Search by location, property type and price/bedroom filters; returns price, address, coordinates, features and agent from a single search call, with an optional detail pass.
Pricing
from $0.56 / 1,000 results
Rating
0.0
(0)
Developer
Ibnu Adzim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Scrapes property listings for sale or rent from
Zoopla — the UK's #2/#3 property portal.
UK coverage in this portfolio was OnTheMarket only; this adds a second,
larger source (Rightmove, the #1 portal, blocks ClaudeBot/CCBot in
robots.txt and was not pursued).
Public data only. No login, no cookies, no browser.
The one thing you need to know before using this
Zoopla sits behind a Cloudflare managed challenge. Two TLS profiles
(chrome99_android, edge101) are blocked deterministically and excluded
from the pool entirely; the remaining profiles are challenged
intermittently (roughly 1 in 3–4 requests). The client retries with a
rotated profile on every challenge — this is normal, expected traffic for
this target, not a sign something is broken. Give it a real retry budget
(the default maxConcurrency/minRequestInterval already do this) rather
than lowering concurrency to "fix" occasional log warnings.
Rendering is Next.js App Router RSC streaming (self.__next_f.push(...)),
not __NEXT_DATA__ — same protocol family as
boligsiden-properties-scraper and justjoinit-jobs-scraper elsewhere in
this portfolio. See CRAWLING_METHOD.md for the full
trail.
What you get
Three record types share one dataset, told apart by recordType.
PROPERTY — one row per listing
Search rows (listing) already carry price, full address, coordinates,
title, features, tags, photo gallery and the listing agent/branch. Turn on
Fetch listing detail pages to also attach propertyDetail, which adds
floor area, bed/bath counts, tenure, EPC, nearby stations and price
history — none of which are present in search results.
SEARCH_SUMMARY — one row per (section, property type, location) query
Pages fetched, rows returned, upstream's own totalResults, and
segmentResolved — whether the requested location/property-type
combination actually matched something upstream.
ERROR — one row per input that failed
So every entry in Locations maps to at least one output row.
Input
| Field | What it does |
|---|---|
| Locations | place slugs as they appear in Zoopla's own URLs (london, manchester, rye) — one search per entry |
| For sale or to rent | applies to every location in the run |
| Property type | all types, houses, flats, bungalows or retirement homes — each verified live to genuinely narrow the result count |
| Min/max price, min/max bedrooms | all four verified live as real filters, not silently ignored |
| Fetch listing detail pages | adds floor area/tenure/EPC/stations/price history (off by default — one extra request per listing) |
| Max properties / max pages per search | pagination caps — Zoopla pages honestly and caps itself at ~1,000 listings/query regardless |
| Max concurrent requests / Min seconds between requests | tuned for the Cloudflare challenge described above — lowering these will not remove the occasional retry, it will just make the run slower |
Example
{"locations": ["london", "manchester"],"section": "for-sale","propertyType": "houses","priceMax": 500000,"includePropertyDetails": true,"maxItems": 100}
Notes on reliability
- Filters are genuinely honest, a rare case in this portfolio's
REAL_ESTATE family: an unrecognised location OR an unrecognised
property-type path segment both answer a clean Next.js "not found" page
(
segmentResolved: false, zero rows) — Zoopla does not silently widen to a national/parent baseline the way most other targets here do. - Pagination is genuinely honest:
?pn=Nreally advances (verified: 0 listing-id overlap between consecutive pages), and a page past the real ceiling (pageNumberMax, ~40 pages/query) answers a clean HTTP 404 — no clamp-back-to-page-1 trap like several other actors in this portfolio have to work around. totalResultsis a real structured field (not scraped from page copy), but Zoopla itself caps the displayed figure at 50,000 and flags this viatotalResultsWasLimited: true— the true count can be higher.- A dead/renamed detail listing answers HTTP 200 with a "not found" page
shell, not a 404 —
propertyDetailis simplynullfor that row rather than treated as a run failure. - An invalid
section/propertyTypefrom the API/CLI (bypassing the Console's enum picker) is refused up front with a clearERRORrow — never silently substituted with the default.
Output envelope
Every record carries _input, _source and _scrapedAt. Upstream field
names pass through verbatim under listing (and propertyDetail when
requested) — no renaming.
See CRAWLING_METHOD.md for the full reverse-engineering trail, including the Cloudflare TLS-profile ladder, the RSC flight-stream parsing approach, and the property types/filters that were probed but NOT verified (so are deliberately not offered).