# Zoopla Scraper - UK Property Data, No Login (`benthepythondev/zoopla-scraper`) Actor

Zoopla UK property listings for sale and to rent: price, beds, baths, address, coordinates, estate agent name and phone, photos and listing dates. Full records: description, postcode, tenure, EPC, floor area, price history, nearby stations. No browser, no login; whole cities via price bands.

- **URL**: https://apify.com/benthepythondev/zoopla-scraper.md
- **Developed by:** [Ben](https://apify.com/benthepythondev) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.85 / 1,000 properties

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 🏡 Zoopla Scraper — UK Property Listings, Agents and Prices, No Login

Scrape **Zoopla**, one of the UK's two big property portals: homes **for sale**, **to rent** and **new homes**. Every listing comes back as a clean row with price, bedrooms, bathrooms, receptions, size, address, postcode district, coordinates, the **estate agent's name and phone number**, photo, tags and listing date. Switch on details to add the full description, key features, full postcode, tenure, EPC rating, floor area, price per sq ft, price history, every photo and floorplan, and nearby schools and stations. No browser, no login, no cookies: a default run finishes in a few seconds. Export to JSON/CSV/Excel, run on a schedule, call via API, or connect to Make, Zapier or n8n.

**What a run costs:** you pay per listing saved, plus one event per listing whose full record you asked for. A search that finds nothing, a place Zoopla does not know and a link that is not a Zoopla search cost nothing.

### 🔎 What is the Zoopla Scraper?

Give it UK places ("London", "Camden", "Leeds", "NW8") or paste Zoopla search links with your filters, and it reads Zoopla's own search results through the data service Zoopla's website uses. One Zoopla list stops after **40 pages (1,000 listings)**; when you ask for more, the run splits the search into price bands and reads band after band, so a whole city is reachable: all **5,534** Manchester homes for sale in **26 seconds** in our test, and 2,500 London rentals with full records in 49 seconds.

#### What users of other Zoopla scrapers report, and what this one does

| Reported elsewhere | Here |
|---|---|
| Runs blocked by Cloudflare, empty datasets | No browser and no page loads; the data service answers plain requests. A refused address is replaced by another one automatically. |
| Results stop at 1,000 | Price bands beyond 1,000, until your `maxResults` or the end of the search |
| Slow, 2–4 GB browser runs | 512 MB, about 200 listings a second without details |
| Ambiguous place names (Leeds, Newport) | Matched to Zoopla's own location list; the run logs which place it chose |
| Same listing twice | Saved once per run, also after a restart |

#### What data does it extract?

- **Listing:** id, link, title, address, town, postcode district, coordinates, property type, bedrooms, bathrooms, receptions, size in sq ft and its source, tags (Freehold, New home, Shared ownership, Retirement), summary, card photo
- **Price:** amount, display text ("£1,200 pcm", "Offers over £350,000"), short price, latest price reduction and its date
- **Agent:** branch name, phone number, logo, branch id and page
- **Dates and flags:** last published, available from (rentals), Zoopla's flag ("Just added", "Reduced"), premium listing
- **With `includeDetails`:** full description, key features, full postcode, street, county, UPRN, tenure, condition (new or pre-owned), furnishing, chain free, shared ownership, retirement home, floor area, price per sq ft, auction flag, rent frequency, EPC rating and certificate, all photos, floorplans, virtual tours, first listed date and price, every price change, nearby schools and stations with distance, agent brand and company id

### ⬇️ Input

| Field | Type | Description |
|-------|------|-------------|
| `location` | array | UK places: towns, cities, boroughs, areas or outcodes (`NW8`). A full postcode falls back to its outcode. |
| `searchUrls` | array | Zoopla search links with your filters (price, beds, property type, radius, sort, new homes). |
| `channel` | string | For location searches: `BUY` or `RENT`. A pasted link keeps its own. Default `BUY`. |
| `maxResults` | integer | Most listings per place or link. Default `50`, up to 100,000. |
| `includeDetails` | boolean | Also read each listing's full record (25 listings per request). Default `false`. |

#### Example input

```json
{
  "location": ["Manchester", "NW8"],
  "searchUrls": ["https://www.zoopla.co.uk/to-rent/property/manchester/?beds_min=2&price_frequency=per_month&price_max=1500"],
  "channel": "BUY",
  "maxResults": 500,
  "includeDetails": false
}
```

### ⬆️ Output

One row per listing (fields of the details step appear when `includeDetails` is on):

```json
{
  "id": "74069260",
  "url": "https://www.zoopla.co.uk/to-rent/details/74069260/",
  "transaction_type": "RENT",
  "price": 200,
  "currency": "GBP",
  "price_display": "£200 pcm",
  "bedrooms": 0,
  "bathrooms": 0,
  "receptions": 0,
  "property_type": "parking",
  "area_value": 656,
  "area_unit": "sqft",
  "address": "Oval Road, Croydon CR0",
  "city": "Croydon",
  "postcode": "CR0 6BS",
  "latitude": 51.3782,
  "longitude": -0.087428,
  "agent": "Benson & Partners",
  "agent_phone": "020 8166 7682",
  "agent_logo": "https://st.zoocdn.com/zoopla_static_agent_logo_(59596).jpeg",
  "image": "https://lid.zoocdn.com/645/430/6eb9979548c1448eeff322834e0e9e94688226e8.jpg",
  "listing_status": null,
  "listed_on": "2026-09-22T09:48:20",
  "search": "London",
  "title": "Parking to rent",
  "price_short": "£200",
  "summary": "Detached garage for rent. With an up and over door to the front and side access...",
  "tags": [],
  "price_drop": null,
  "agent_id": 21315,
  "agent_url": "https://www.zoopla.co.uk/find-agents/branch/benson-and-partners-addiscombe-21315/",
  "rent_frequency": "pcm",
  "street": "Oval Road",
  "county": "London",
  "uprn": "100022907677",
  "description": "Detached garage for rent. With an up and over door to the front and side access. Ideal for storage or as office space...",
  "key_features": ["Detached garage", "Up and over door", "Suitable as storage or office space"],
  "listing_state": "to_rent",
  "furnished_state": "unfurnished",
  "epc_rating": "D",
  "images": ["https://lc.zoocdn.com/6eb9979548c1448eeff322834e0e9e94688226e8.jpg"],
  "floorplans": ["https://lc.zoocdn.com/d26a0e0c684635a6761c9cd4b7beea325bcfb287.png"],
  "first_published": "2026-08-26T09:21:27",
  "first_price": "£200 pcm",
  "price_changes": [],
  "nearby": [{"name": "Al-Khair School", "type": "uk_school_primary_and_secondary", "distance_miles": 0.1}],
  "detailed": true,
  "scraped_at": "2026-10-15T10:42:27.623602+00:00"
}
```

### 💡 Use cases

- 📈 **Market analysis:** asking prices, price per sq ft and reductions by area, property type and size
- 📇 **Agent lead lists:** estate and letting agents active in a postcode, with phone numbers and listing counts
- 🔔 **Monitoring:** a daily scheduled run for a search, sorted by newest, to catch new listings and price drops
- 🏗️ **New homes research:** developments, shared ownership and retirement homes per region

### 🤖 For AI agents

One input to copy:

```json
{"location": ["Leeds"], "channel": "RENT", "maxResults": 20}
```

No credential is needed. `location` and `searchUrls` are arrays; every row has the same fields.

### ❓ FAQ

**Do I need a login, cookies or an API key?** No.

**Can I scrape rentals and new homes?** Yes. Set `channel` to `RENT`, or paste a link from Zoopla's rental or new-homes section.

**Can I keep my filters?** Yes. Paste the search link from your browser; bedrooms, price, property type, radius, keywords and sort are kept.

**How many listings can I get?** Zoopla's own list stops at 1,000. Above that the run reads the search in price bands, lowest prices first, until it has `maxResults` or the search is exhausted. In band mode rows come in price order. For London Zoopla only says "50,000+"; the bands still reach every listing.

**Why are bedrooms 0 for some rows?** Zoopla gives 0 for parking, garages, land and some studios.

**What is the difference between `price` and `price_display`?** `price` is the first number of the display text (for "£1,200 pcm" it is 1200). With details on, `price` becomes Zoopla's exact value and `rent_frequency` says per month or per week.

**What happens when a run is stopped or moved to another server?** It continues where it stopped and does not save or charge a listing twice.

**Is it legal?** It collects listing data that Zoopla shows to any visitor. Agent phone numbers are business contacts published by the agents; follow UK GDPR and PECR when you contact them, and respect Zoopla's terms for how you use the data.

### ⚠️ Limits

- Current listings only; sold prices and valuations are not read.
- Zoopla's data service sits behind Cloudflare. Some addresses are turned away; the run moves to another address and, if all else fails, to UK residential addresses.
- A price band that holds more than 1,000 listings at a single price cannot be split further; the run then saves the first 1,000 and says so in its status message.
- Featured listings that Zoopla shows above the results, and listings from nearby areas, are not saved: only the search's own results.

### 🔗 You might also like

- [Rightmove Scraper](https://apify.com/benthepythondev/rightmove-scraper): the other big UK portal, same row layout ideas.
- [OnTheMarket Scraper](https://apify.com/benthepythondev/onthemarket-scraper): more UK property.
- [Real Estate Agent Lead Scraper](https://apify.com/benthepythondev/real-estate-agent-lead-scraper): agent contact leads from Google Maps.

***

**Keywords:** zoopla scraper, zoopla api, uk property data, property scraper uk, zoopla listings, estate agent leads, uk real estate data, property for sale uk, property to rent uk, new homes uk, zoopla data export, house prices uk, letting agents, zoopla csv, rental market uk

# Actor input Schema

## `location` (type: `array`):

UK places to search: towns, cities, London boroughs, areas or outcodes, e.g. 'London', 'Camden', 'Leeds', 'NW8'. Each is matched to Zoopla's own location list. A full postcode falls back to its outcode.

## `searchUrls` (type: `array`):

Zoopla search links to read with their own filters (price, beds, property type, radius, sort, new homes). Paste the address of a results page from your browser, e.g. https://www.zoopla.co.uk/to-rent/property/manchester/?beds_min=2\&price_frequency=per_month\&price_max=1500. Used in addition to any locations.

## `channel` (type: `string`):

BUY (for sale) or RENT (to rent). Applies to location searches; a pasted link keeps its own.

## `maxResults` (type: `integer`):

Listings to save per location or link. One Zoopla list shows at most 1,000; above that the run reads the search in price bands, so a whole city is reachable.

## `includeDetails` (type: `boolean`):

Also read each listing's full record: description, key features, postcode, tenure, EPC rating, floor area, price per sq ft, price history, all photos and floorplans, nearby schools and stations, 30-day views. Read 25 listings per request; billed as one extra event per listing.

## Actor input object example

```json
{
  "location": [
    "London"
  ],
  "searchUrls": [
    "https://www.zoopla.co.uk/for-sale/property/manchester/?beds_min=3"
  ],
  "channel": "BUY",
  "maxResults": 10,
  "includeDetails": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "location": [
        "London"
    ],
    "searchUrls": [
        "https://www.zoopla.co.uk/for-sale/property/manchester/?beds_min=3"
    ],
    "channel": "BUY",
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/zoopla-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "location": ["London"],
    "searchUrls": ["https://www.zoopla.co.uk/for-sale/property/manchester/?beds_min=3"],
    "channel": "BUY",
    "maxResults": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("benthepythondev/zoopla-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "location": [
    "London"
  ],
  "searchUrls": [
    "https://www.zoopla.co.uk/for-sale/property/manchester/?beds_min=3"
  ],
  "channel": "BUY",
  "maxResults": 10
}' |
apify call benthepythondev/zoopla-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,benthepythondev/zoopla-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/h5stDcMljKz0ypTAl/builds/JNQnCybi4cF6zQ4ud/openapi.json
