Real estate
Zoopla UK Property Scraper
Zoopla listing data — price, address, bedrooms, agent phone, floor plan, EPC — exported to JSON/CSV, no public API needed.
Free Apify credit covers a first run. No credit card to try.
What this Actor scrapes
Give this Actor a UK location and a listing type and it returns structured Zoopla property rows — price, address, bedrooms, bathrooms, floor area, tenure, EPC rating, key features, agent details, photos, and (optionally) the full listing description and floor plan straight from each property's detail page.
1. Searches Zoopla for the location + listing type you give it, with optional price and minimum-bedroom filters. 2. Collects up to your configured cap of listing rows from the search results. 3. Optionally visits each listing's detail page for the fuller field set — full description, floor plan URL, EPC graph, and full agent phone. 4. Emits one row per property to the default dataset.
What we handle for you
- 🛡️ We clear the JS-execution gate Zoopla puts in front of raw HTTP requests — a hardened browser layer renders the page like a real visitor instead of bouncing off a challenge screen.
- 🌐 We rotate proxy sessions through Apify Proxy — a fresh exit IP and session on every block.
- 🧭 Built-in UK geo-splash guard — every fetched page is checked for genuine UK Zoopla markers (currency symbol, canonical domain) before its data is trusted, so a bad proxy exit never silently returns wrong-country data.
- 🧱 We back off when the target pushes back. Partial successes surface with a clear status message — we never silently return an empty dataset.
- 🎯 Per-listing fault isolation — one bad listing is logged and skipped; it never fails the whole run.
- 🧊 Pydantic v2 input + output validation — every row is a typed, schema-enforced record; nullable fields are always
null, never silently dropped. - 💰 Pay-Per-Event pricing — you're charged per listing row written to your dataset, not per page fetched.
Use cases
- Market research — track UK listing supply, pricing, and inventory mix by area over time.
- Estate agent competitor monitoring — see what other agents have listed in your patch, at what price, and with what features.
- Investment screening — filter for-sale or to-rent inventory by area, price, and bedroom count for deal sourcing.
- Proptech / analytics pipelines — feed structured listing data into a warehouse or model without maintaining your own scraper.
Input
Paste this into the Apify Console, or send it as the run input over the API. Proxy settings are on by default; you rarely need to touch them.
| Field | Type | Required | What it does |
|---|---|---|---|
searchLocation | string | yes | Free-form UK location — city, district, postcode prefix, or region. |
listingType | string | no | Which Zoopla channel to scrape. |
maxPriceGbp | integer | no | Upper price filter. GBP total for for-sale; GBP/month for to-rent. Leave empty for no cap. |
minBedrooms | integer | no | Minimum number of bedrooms (1-10). Leave empty for no floor. |
maxProperties | integer | no | Hard cap on dataset rows. Zoopla search pagination is shallower than Rightmove's. |
enrichDetails | boolean | no | Fetch each property's detail page for full description, floor plan, EPC rating, and full agent phone. Roughly doubles the request count. |
countryCode | string | no | Pinned to GB in v1 — declares the expectation the geo-splash guard checks fetched pages against. |
{
"searchLocation": "London",
"listingType": "for-sale",
"maxProperties": 5,
"enrichDetails": true,
"countryCode": "GB",
"proxyConfiguration": {
"useApifyProxy": true
}
} Output
One row per result, schema-validated before it is written. Export JSON, CSV, Excel or XML from the run, or read it over the API.
listing_idzoopla_urladdressprice_gbpbedroomsagent_phonefloor_plan_urlepc_rating
{
"listing_id": "68912345",
"zoopla_url": "https://www.zoopla.co.uk/for-sale/details/68912345/",
"address": "Gainsford Road, Walthamstow, London",
"postcode": "E17 6ZL",
"latitude": 51.587363,
"longitude": -0.027555,
"price_gbp": 300000,
"price_qualifier": "Offers in Excess of",
"price_frequency": "not specified",
"listing_type": "for-sale",
"property_type": "Flat",
"bedrooms": 1,
"bathrooms": 1,
"sqft": 443,
"tenure": "Leasehold",
"epc_rating": "C",
"epc_graph_url": "https://lc.zoocdn.com/.../epc.png",
"description": "Set on the quiet side ...",
"key_features": [
"One Bedroom",
"Rear Garden"
],
"listing_added_date": "2026-07-19T10:24:23Z",
"agent_name": "Foxtons, Walthamstow",
"agent_phone": "020 3910 6244",
"agent_url": "https://www.zoopla.co.uk/find-agents/branch/foxtons-walthamstow-.../",
"photo_urls": [
"https://lc.zoocdn.com/..."
],
"floor_plan_url": "https://lc.zoocdn.com/.../floorplan.png",
"country_code": "GB",
"scraped_at": "2026-08-13T10:00:00+00:00"
} Pricing
| Event | Price | When |
|---|---|---|
| Actor start | $0.20 | Once per run, covers warm-up and proxy session setup. |
| Listing row | $0.0035 | Per result written to the dataset. |
You pay only for results that land. Cap any run with maxTotalChargeUsd. See pricing & billing for worked examples.
FAQ
Is this legal?
Why is a field `null`?
epc_graph_url, description, agent_phone, floor_plan_url) are null when enrichDetails is false, or when Zoopla doesn't expose that field publicly for a given listing.Do I need my own proxy?
Why did I get fewer rows than `maxProperties`?
Ready to run it?
Open the listing on Apify, paste the input above, and watch rows land. If it ever breaks, it is our problem before it is yours.
Related Actors