Zoopla Scraper icon

Zoopla Scraper

Scrape UK property from Zoopla: for sale, to rent and Land Registry sold prices. Search by place with filters or paste links. Optional full detail adds…

Start using this actor on Apify ↗Need a custom scraper?Contact us ↗

Zoopla Scraper at a glance

Zoopla Scraper is a ready-to-run Apify actor from abotapi for collecting web data. Its documented output includes photo, title, change type (incremental mode), address and price, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $2.00 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify.

Runs on
Apify cloud: console, API, schedules and integrations
Data type
Web data
Region
Europe
Pricing
$2.00 per 1,000 results (Free plan), from $1.00 on paid plans
Output
Documented below · JSON, CSV, Excel
Inputs
40 options

Scrape UK property from Zoopla: for sale, to rent and Land Registry sold prices. Search by place with filters or paste links. Optional full detail adds EPC, floor plans, tenure, price history, stations and agent phone. Incremental mode for change monitoring.

What Zoopla Scraper can do

  • Four channels, one actor. For sale, to rent, new homes and Land Registry sold prices: the same UK place search covers all four, and pasted links also cover estate-agent branch pages.
  • Search by place or paste links. Look up a city, postcode or district with Zoopla's own filters, or scrape the exact results page, house-prices page or listing page you already have.
  • Full listing detail on demand. Switch on EPC rating and graph images, floor plans, tenure, council tax band, service charge, ground rent, UPRN, price history, nearest stations, EV charge points, virtual tours, brochures and the agent's phone number, billed only per listing you actually enrich.
  • UK-specific fields throughout. Postcode, outcode, UPRN, council tax band and EPC rating are first-class fields, and every price is in GBP.
  • Built for monitoring. Incremental mode returns only new, updated and reappeared listings on a recurring search, so a daily run does not rebill what has not changed.
  • Resume without repaying. Continue an interrupted crawl from its run id and skip everything it already collected.

Choose what to collect

These inputs let you configure Zoopla Scraper - Property Listings, Sold Prices & Monitoring. Open the actor on Apify to enter your values and review the current options.

Supported input fields
InputWhat it controls
modestring · requiredChoose 'search' to look up places by name and apply filters, or 'url' to scrape Zoopla links you paste, results pages, house-price pages and individual listing pages are all accepted.

Choices: search, url

locationsarrayOne or more UK places, for example 'London', 'Manchester', 'SW19', or 'Islington, London' for a district inside a city. Each place is searched separately on every channel you pick below.
channelsarrayWhich parts of Zoopla to search. 'For sale', 'To rent' and 'New homes' (new-build developments) return live listings; 'Sold prices' returns Land Registry sale records from the house-prices section (address, sold price, sold date, UPRN, tenure, floor area). Pick more than one to cover several at once.
minPriceintegerOptional. Lowest price to include. For rentals this is read together with 'Rent price shown per' below.
maxPriceintegerOptional. Highest price to include. For rentals this is read together with 'Rent price shown per' below.
minBedsintegerOptional. Only return properties with at least this many bedrooms. 0 keeps studios and drops listings that state no bedroom count.
maxBedsintegerOptional. Only return properties with at most this many bedrooms. Set 0 for studios only.
Show 33 more inputs
More input fields
InputWhat it controls
minBathsintegerOptional. Only return properties with at least this many bathrooms.
propertySubTypesarrayOptional. Narrow to specific property types. Leave empty for every type. On the 'Sold prices' channel Zoopla accepts a single type only, so the first one you pick is used there.
mustHaveFeaturesarrayOptional. Only return listings that have ALL the features you pick. Applies to For sale, To rent and New homes searches; sold prices ignore it.
radiusstringOptional. Widen the search around the place you named. 'This area only' is Zoopla's own default.

Choices: 0, 0.25, 0.5, 1, 3, 5, 10, 15, 20, 30, 40

addedSincestringOptional. Only return listings published within this window. Very useful for a daily monitoring run.

Choices: , 24_hours, 3_days, 7_days, 14_days, 30_days

keywordsstringOptional. Free-text keyword Zoopla matches against the listing, for example 'garden', 'garage' or 'balcony'.
sortBystringOrder Zoopla returns results in. Note that paid-for premium listings are pinned to the top of the first page whatever you pick here.

Choices: recommended, newest_listings, highest_price, lowest_price, most_reduced

chainFreeOnlybooleanOptional, for sale only. Only return properties advertised as chain free.
auctionOnlybooleanOptional, for sale only. Only return properties being sold at auction.
sharedOwnershipOnlybooleanOptional, for sale only. Only return shared-ownership properties.
retirementOnlybooleanOptional, for sale only. Only return retirement properties.
reducedPriceOnlybooleanOptional. Only return listings whose asking price has been reduced.
includeUnderOfferbooleanOptional, for sale only. Also return properties marked under offer or sold subject to contract, which Zoopla hides by default.
includeLetAgreedbooleanOptional, to rent only. Also return properties marked let or let agreed, which Zoopla hides by default.
furnishedStatestringOptional, to rent only. Narrow rentals by how they are furnished.

Choices: , furnished, part_furnished, unfurnished

availableFromstringOptional, to rent only. Only return rentals available within this window.

Choices: , now, 1months, 3months, 6months, 12months

priceFrequencystringOptional, to rent only. Whether the minimum and maximum price above are per month or per week. Zoopla treats rents as per month unless you change this.

Choices: , per_month, per_week

petsAllowedbooleanOptional, to rent only. Only return rentals that accept pets.
billsIncludedbooleanOptional, to rent only. Only return rentals where bills are included.
soldPeriodMonthsstringOptional, sold prices only. How far back to look for sold records.

Choices: all-time, 3, 6, 12, 60, 120, 240

startUrlsarrayPaste Zoopla addresses: a results page such as https://www.zoopla.co.uk/for-sale/property/london/islington/ (also to-rent and new-homes), a house-prices page such as https://www.zoopla.co.uk/house-prices/london/islington/ , a single listing such as https://www.zoopla.co.uk/for-sale/details/73365838/ (also to-rent and new-homes listings), or an estate-agent page: one branch such as https://www.zoopla.co.uk/find-agents/branch/alwyne-estates-london-24416/ or an area list such as https://www.zoopla.co.uk/find-agents/estate-agents/london/islington/ . A bare numeric listing id also works. A pasted page number is honoured as the starting page.
includeDetailsbooleanAdd the full detail set to every record: EPC rating and EPC graph images, floor plan images, tenure, council tax band, service charge, ground rent, UPRN, price history, full description, features, nearest stations with distances, EV charge points, virtual tours, brochures and the agent's phone number. Billed as a per-listing surcharge, so leave it off for a fast, cheap listing-level pull. It has no effect on the 'Sold prices' channel, which publishes no per-property detail.
maxItemsintegerMaximum number of records to return across the whole run. Use 0 for unlimited.
maxPagesintegerMaximum result pages to cover per place and channel. Leave empty or 0 to cover every result page Zoopla offers, which is at most 40 pages (about 1000 records) per search, the site's own limit.
resumeFromRunIdstringPaste a previous run ID or dataset ID to continue a large crawl without returning, or charging for, records already collected there. For recurring monitoring of the same search use Incremental mode below instead.
incrementalModebooleanTurn this on for daily or recurring monitoring. The first run returns everything as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. State is kept separately for each combination of places, channels, filters and detail setting; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.
stateKeystringOptional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key from the search itself, so two different searches never mix state.
emitUnchangedbooleanOff by default. Turn on to also return records that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you want a full snapshot every run.
emitExpiredbooleanOff by default. Turn on to also return records that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, never when Max results capped it or when Resume was used. This returns, and bills, extra synthetic rows.
ignoreFieldsForChangesarrayOptional. Field names that must not count as a change in incremental mode, in addition to the ones already ignored (scrape time, source URL, search mode, the 'just added' style status badge, and paid-placement flags). Use it when another field turns out to be noisy, for example images or description. A dotted name such as priceHistory.date ignores that key inside each entry of a list or object. Ignored fields are still returned in the output; they only stop a row being marked UPDATED and are left out of changedFields. Changing this list never causes a one-off wave of UPDATED rows.
mcpConnectorsarrayOptionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; this never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).
notionParentPageUrlstringURL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.
maxNotifyListingsintegerCap on items written to each connector per run. Does not affect the dataset.

Fields in the output

The documented dataset includes the fields below. Availability can depend on the source page and selected mode.

imageUrlPhoto (image)
titleTitle
changeTypeChange type (incremental mode) (text)
addressAddress
pricePrice (number)
priceLabelPrice shown
listingTypeSale / rent / sold
bedroomsBeds (number)
bathroomsBaths (number)
receptionRoomsReceptions (number)
propertyTypeType
sizeSqftSize (sq ft) (number)
Show 38 more fields
tenureTenure
epcRatingEPC
councilTaxBandCouncil tax band
chainFreeChain free (boolean)
lastSoldPriceSold price (number)
lastSoldDateSold date (date)
postcodePostcode
latitudeLatitude (number)
longitudeLongitude (number)
uprnUPRN
branchNameAgent
branchPhoneAgent phone
publishedOnListed on
listingIdListing ID
urlURL (link)
detailScrapedFull detail fetched (boolean)
changedFieldsChanged fields (incremental mode) (array)
firstSeenAtFirst seen (incremental mode) (date)
lastSeenAtLast seen (incremental mode) (date)
scrapedAtScraped at (date)
serviceChargeService charge
groundRentGround rent
nearestStationsNearest stations
priceHistoryPrice history
featuresFeatures
epcImagesEPC images
floorPlanImagesFloor plans
channelChannel
branchIdBranch ID
branchSaleListingsHomes for sale (number)
branchRentListingsHomes to rent (number)
branchAverageSalePriceAverage asking price (number)
branchAverageRentAverage asking rent (number)
branchSaleWeeksOnMarketWeeks on market (sale) (number)
branchRentWeeksOnMarketWeeks on market (rent) (number)
branchSellsPropertySells property (boolean)
branchLetsPropertyLets property (boolean)
branchLogoUrlLogo (image)

Example output

An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.

{
  "listingId": "10000001",
  "listingType": "sale",
  "channel": "for-sale",
  "url": "https://www.zoopla.co.uk/for-sale/details/10000001/",
  "title": "2 bed flat for sale",
  "address": "Example House, Sample Street, Manchester M1",
  "price": 285000,
  "priceLabel": "£285,000",
  "currency": "GBP",
  "bedrooms": 2,
  "bathrooms": 1,
  "receptionRooms": 1,
  "propertyType": "flat",
  "sizeSqft": 720,
  "tenure": "leasehold",
  "epcRating": "D",
  "epcImages": [
    "https://lid.zoocdn.com/1024/768/example-epc.png"
  ],
  "floorPlanImages": [
    "https://lid.zoocdn.com/1024/768/example-floorplan.jpg"
  ],
  "councilTaxBand": "B",
  "serviceCharge": "£1,200 per year",
  "groundRent": "£100 per year",
  "chainFree": true,
  "uprn": "0000000000",
  "postcode": "M1 0AA",
  "latitude": 53.48,
  "longitude": -2.24,
  "nearestStations": [
    {
      "name": "Example Street",
      "miles": 0.4
    }
  ],
  "features": [
    "Private balcony",
    "Allocated parking",
    "Open-plan kitchen"
  ],
  "priceHistory": [],
  "images": [
    "https://lid.zoocdn.com/1024/768/example-photo.png"
  ],
  "branchName": "Example Estates",
  "branchPhone": "01000 000000",
  "branchUrl": "https://www.zoopla.co.uk/find-agents/branch/example-estates-1/",
  "publishedOn": "2026-09-12T08:30:00",
  "detailScraped": true,
  "scrapedAt": "2026-09-30T11:00:00Z"
}

Ways to use this data

  • Property investment and comparables: compare current asking prices against Land Registry sold prices for the same postcode to judge whether a listing is fairly priced.
  • PropTech and market research: build historical datasets of prices, EPC ratings, tenure and property types across areas for analysis or machine learning.
  • Listing and price-drop monitoring: run incremental mode daily to catch newly listed, reduced, let-agreed or sold properties in a target area.
  • Agent and branch tracking: paste an estate-agent branch page (or an agents-by-area list) to get the branch's name, address, phone and live listing counts, and track how a listing's price changes over time.
  • Relocation and house-hunting tools: feed a personal search (place, budget, bedrooms, property type) into a spreadsheet, bot or app.

Before you run

Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.

Questions about this actor

What data does Zoopla Scraper return?

The documented output for Zoopla Scraper includes photo, title, change type (incremental mode), address, price, price shown, sale / rent / sold and beds. Availability of each field depends on the source page and the selected mode.

How much does Zoopla Scraper cost?

It costs $2.00 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.

Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared records, and unchanged ones are not billed unless you turn emitUnchanged on.

Why did an incremental run come back with fewer rows than Max results?

Max results caps how many listings are scanned, not how many survive incremental filtering. Listings that turn out unchanged still use up the cap, and once it is used up no further listings or pages are read, so a run can even return zero rows while new listings exist further down the results, and the same thing happens again on the next run. Set Max results well above the number of listings your search shows (or 0), or sort by newest listings, for monitoring runs.

Why did every field show as changed on my first run after using Resume with incremental mode?

When a new incremental campaign is started with resumeFromRunId, the listings from that earlier run are recorded by id only, without their field values. On the next normal run each of them is returned once as UPDATED with every field in changedFields, and billed like any other row, even when nothing changed on Zoopla. It happens once per listing; later runs compare real values. To avoid it, start the campaign with a plain incremental run instead of a resume.

Why can an EXPIRED batch push more rows than Max results?

Once a run fully scans its tracked search, emitExpired computes and bills every listing that disappeared since the last run in one batch, without trimming it to Max results. On a search with a large tracked history, this can add more billed rows than Max results implies. Turn emitExpired off on very large monitoring campaigns if this matters to you.

Ready to collect with Zoopla Scraper?

Run it on Apify with your own input and export the results as JSON, CSV or Excel.