# Zoopla Property Scraper (`parsebird/zoopla-property-scraper`) Actor

Scrape Zoopla property listings by search URL, location, bedrooms, price, and property type. Extract price, size, beds, baths, agent, and photo data as JSON, CSV, or Excel.

- **URL**: https://apify.com/parsebird/zoopla-property-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.69 / 1,000 property listings

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 Property Scraper

Scrape **Zoopla property listings** for sale anywhere in the UK — no coding, no API key, no browser required. Point the Zoopla Property Scraper at a search URL, a location, or a postcode, and get structured price, size, bedroom, agent, and photo data as clean JSON, CSV, or Excel.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Search any UK city or postcode on Zoopla.co.uk, filter by bedrooms, price range, and property type, and get 30+ structured data fields per listing — including price history, floor size, agent contact details, and full photo galleries.
</td>
</tr></table>

<br>

##### Copy to your AI assistant

```
Use the Apify Actor "parsebird/zoopla-property-scraper" to scrape Zoopla.co.uk property listings. Call it with the ApifyClient: from apify_client import ApifyClient; client = ApifyClient("<APIFY_TOKEN>"); run = client.actor("parsebird/zoopla-property-scraper").call(run_input={"startUrl": "https://www.zoopla.co.uk/for-sale/property/london/?q=London&search_source=home&recent_search=true", "results_wanted": 20}); items = client.dataset(run["defaultDatasetId"]).list_items().items. Key inputs: startUrl (string, a full Zoopla search-results URL), location (string, e.g. "london" or a postcode like "SW1A", overrides the URL's location), minBedrooms/maxBedrooms (integer), minPrice/maxPrice (integer, GBP), propertyType (string, "houses" or "flats"), results_wanted (integer, default 20), proxyConfiguration (object, default Apify Unblocker proxy for UK). Output fields per listing include listingId, title, address, postalCode, propertyType, price, priceValue, priceCurrency, beds, baths, receptions, sizeSqft, summaryDescription, priceDrop, features, tags, underOffer, image, gallery, branch (agent name/phone/id), url, detailUrl, contactUrl, pagination, and scrapedAt. Full API docs and schema: https://apify.com/parsebird/zoopla-property-scraper/api
```

### What does Zoopla Property Scraper do?

[Zoopla](https://www.zoopla.co.uk/) is one of the UK's largest property portals, listing hundreds of thousands of homes for sale and to rent. The **Zoopla Property Scraper** extracts structured data from Zoopla search results without you writing a single line of scraping code — it's a ready-to-run **Zoopla API alternative** for anyone who needs Zoopla data at scale.

With this Zoopla scraper you can:

- 🔍 Search by **any UK location or postcode** — cities, towns, or postcode areas like `SW1A`
- 🏠 Filter by **minimum/maximum bedrooms**, **price range**, and **property type** (houses or flats)
- 🖼️ Pull full **photo galleries**, floor size, price-drop history, and estate agent contact details for every listing
- 📈 **Monitor a market** over time by scheduling recurring runs and tracking price changes and new listings
- 🔗 Integrate results directly into Google Sheets, Airtable, Make, Zapier, or your own pipeline via Apify's API and integrations

Unlike scraping Zoopla yourself with `requests` or Selenium, this Actor already handles Zoopla's Cloudflare bot protection, pagination, and the site's internal data format — you just provide a search URL or filters and get clean rows back.

### What data can you extract from Zoopla?

| Field | Description |
|-------|-------------|
| `listingId` | Zoopla's unique listing identifier |
| `title` | Listing title (e.g. "3 bed semi-detached house for sale") |
| `address` | Full address text as shown on Zoopla |
| `postalCode` | UK postcode or postcode area extracted from the address |
| `propertyType` | Zoopla property type (flat, terraced, semi\_detached, detached, etc.) |
| `price` / `priceValue` / `priceCurrency` | Formatted and numeric asking price, with currency |
| `beds` / `baths` / `receptions` | Bedroom, bathroom, and reception room counts |
| `sizeSqft` | Floor size in square feet, when Zoopla provides it |
| `priceDrop` | Price change history, when available |
| `underOffer` | Whether the listing is marked under offer |
| `branch` | Estate agent name, phone number, and branch ID |
| `gallery` | Full-size URLs for every photo in the listing gallery |
| `url` / `detailUrl` / `contactUrl` | Absolute links to the listing and its contact form |

See the [Output example](#output-example) below for the full JSON shape, including `features`, `tags`, `searchContext`, and `pagination` metadata.

### How to scrape Zoopla property listings

1. **Open the Zoopla Property Scraper** on Apify and click **Try for free**.
2. **Paste a Zoopla search URL** — for example, open [zoopla.co.uk](https://www.zoopla.co.uk/for-sale/), run a search for the location you want, and copy the resulting URL into the `startUrl` field. Alternatively, just set the `location` field (city name or postcode).
3. **Set optional filters** — `minBedrooms`, `maxBedrooms`, `minPrice`, `maxPrice`, and `propertyType` narrow the search without editing the URL by hand.
4. **Set `results_wanted`** to the number of listings you need.
5. Click **Start** and download your results as **JSON, CSV, Excel, or HTML** once the run finishes.

### How much does it cost to scrape Zoopla?

The Zoopla Property Scraper uses **pay-per-result pricing** — you only pay for listings actually returned, not for compute time or failed requests. See the [Pricing](#pricing) section below for the exact rate. Scraping 1,000 listings costs under a dollar; a typical run of 20–50 listings costs a few cents. Apify's free monthly platform credits cover a meaningful number of runs before any paid usage kicks in.

### Input

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `startUrl` | string | No | London search URL | A public Zoopla search-results URL, including location and any filters supported by Zoopla's URL parameters |
| `location` | string | No | `london` | Zoopla location slug (e.g. `manchester`) or UK postcode (e.g. `SW1A`). Overrides the location in `startUrl` and updates its `q` parameter |
| `minBedrooms` | integer | No | — | Minimum bedrooms, sent as Zoopla's `beds_min` filter |
| `maxBedrooms` | integer | No | — | Maximum bedrooms, sent as Zoopla's `beds_max` filter |
| `minPrice` | integer | No | — | Minimum asking price in GBP, sent as `price_min` |
| `maxPrice` | integer | No | — | Maximum asking price in GBP, sent as `price_max` |
| `propertyType` | string | No | Any | Restrict to `houses` or `flats` |
| `results_wanted` | integer | No | 20 | Maximum number of unique listings to save |
| `proxyConfiguration` | object | No | Unblocker (GB) | Apify Proxy configuration; Zoopla requires Unblocker proxy for reliable access |

Structured filters (`minBedrooms`, `maxPrice`, etc.) override matching values already present in `startUrl`, while any other filters in the URL are preserved.

### Output example

```json
{
  "listingId": "72151138",
  "title": "1 bed flat for sale",
  "address": "Percy Road, London W12",
  "postalCode": "W12",
  "propertyType": "flat",
  "price": "£419,500",
  "priceUnformatted": 419500,
  "priceValue": 419500,
  "priceCurrency": "GBP",
  "beds": 1,
  "baths": 1,
  "receptions": 1,
  "sizeSqft": 409,
  "summaryDescription": "Raised ground-floor Victorian one-bed flat with spacious reception, open plan kitchen, double bedroom, and stylish shower room.",
  "underOffer": false,
  "image": "https://lid.zoocdn.com/645/430/044b61a0b89c96aba420e595ddaae737d6644e70.jpg",
  "branch": {
    "branchId": 77168,
    "name": "Nested",
    "phone": "020 8128 9373"
  },
  "url": "https://www.zoopla.co.uk/for-sale/details/72151138/",
  "detailUrl": "https://www.zoopla.co.uk/for-sale/details/72151138/",
  "searchContext": {
    "pageNumber": 1,
    "pageNumberMax": 40,
    "totalResults": 50000,
    "searchLocation": "London",
    "sourceUrl": "https://www.zoopla.co.uk/for-sale/property/london/?q=London&search_source=home&recent_search=true"
  },
  "scrapedAt": "2026-08-02T13:29:49.528Z"
}
```

Every run's results can be downloaded as **JSON, CSV, Excel, XML, or HTML** from the Apify Console, or pulled programmatically via the [Apify API](https://docs.apify.com/api/v2) and [dataset export formats](https://docs.apify.com/platform/storage/dataset).

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("parsebird/zoopla-property-scraper").call(run_input={
    "startUrl": "https://www.zoopla.co.uk/for-sale/property/london/?q=London&search_source=home&recent_search=true",
    "minBedrooms": 2,
    "maxBedrooms": 4,
    "minPrice": 300000,
    "maxPrice": 800000,
    "propertyType": "houses",
    "results_wanted": 50,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["address"], item["price"])
```

#### JavaScript

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

const client = new ApifyClient({ token: '<APIFY_TOKEN>' });

const run = await client.actor('parsebird/zoopla-property-scraper').call({
    startUrl: 'https://www.zoopla.co.uk/for-sale/property/manchester/?q=Manchester&search_source=home&recent_search=true',
    results_wanted: 50,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Use cases

- **Market research** — track average asking prices, bedroom counts, and size per square foot across UK cities and postcodes
- **Lead generation** — build a list of estate agents and their listings for a given area
- **Investment analysis** — filter by price range and property type to find deals matching an investment thesis
- **Price monitoring** — schedule daily or weekly runs and compare `priceDrop` and `price` fields over time to catch reductions
- **Portfolio tracking** — feed listing data into a spreadsheet or BI tool via CSV/Excel export or the API

### Pricing

This Actor uses Apify's **Pay-Per-Event (PPE)** model — you pay only for listings actually returned.

| Event | Price per event | Price per 1,000 |
|-------|-----------------|------------------|
| listing-scraped | $0.00099 | **$0.99** |

A run that returns 50 listings costs about $0.05. Apify accounts include monthly platform usage credits that cover a number of runs before any paid usage applies.

### Is it legal to scrape Zoopla?

Scraping publicly available data, such as property listings visible without logging in, is generally considered legal in most jurisdictions, including under UK and EU law, as established in cases like *hiQ Labs v. LinkedIn*. This Actor only accesses publicly viewable Zoopla search-results pages. However, you are responsible for how you use the extracted data — always review [Zoopla's Terms of Service](https://www.zoopla.co.uk/terms-of-use/) and avoid using scraped data for spam, harassment, or in violation of GDPR when it includes personal data such as agent contact details. See Apify's [web scraping legality guide](https://blog.apify.com/is-web-scraping-legal/) for more detail.

### Related Actors

- [Daft.ie Property Scraper](https://apify.com/parsebird/daft-ie-property-scraper) — the equivalent scraper for Ireland's largest property portal
- [Domain.com.au Property Scraper](https://apify.com/parsebird/domain-com-au-scraper) — Australian property listings
- [Realestate.com.au Scraper](https://apify.com/parsebird/realestate-au-scraper) — a second major Australian property portal

### FAQ

**Do I need an API key or to log in to Zoopla?**
No. The Actor scrapes publicly available search-results pages and needs no Zoopla account or API key. You only need an Apify account to run it.

**Why does this Actor need a residential/unblocker proxy?**
Zoopla is protected by Cloudflare and blocks most datacenter and even shared residential IPs. The default proxy configuration uses Apify's Unblocker proxy group, which is required for consistently successful runs.

**Can I scrape a specific postcode instead of a city?**
Yes. Set `location` to a UK postcode area, e.g. `SW1A`, or paste a Zoopla search URL for that postcode into `startUrl`.

**Does this Actor scrape rental listings?**
The default configuration targets `for-sale` listings. If you paste a `to-rent` Zoopla search URL into `startUrl`, the Actor will attempt to parse it using the same underlying data format, though field availability (e.g. rent frequency) may vary.

**Can I schedule this Actor to run automatically?**
Yes. Use [Apify's Scheduler](https://docs.apify.com/platform/schedules) to run it daily, weekly, or at any interval, and combine it with [integrations](https://apify.com/integrations) like Google Sheets, Slack, or Make to get notified of new or changed listings.

**What if a run returns 0 results?**
Zoopla's Cloudflare protection occasionally blocks even the Unblocker proxy. The Actor retries automatically with a fresh session; if a run still returns 0 results, try again or reduce `results_wanted`. If the issue persists, please open an issue on the Actor's Issues tab.

**Can I access this Actor's data via API?**
Yes. Every run's dataset is available through the [Apify API](https://docs.apify.com/api/v2) and the Actor's [API tab](https://apify.com/parsebird/zoopla-property-scraper/api), with client libraries for Python, JavaScript, and more.

Found a bug or have a feature request? Open an issue on the Actor's Issues tab in Apify Console — feedback is always welcome.

# Changelog

This Actor's version history is a separate document: https://apify.com/parsebird/zoopla-property-scraper/changelog.md

# Actor input Schema

## `startUrl` (type: `string`):

A public Zoopla search-results URL. Use a complete URL containing the location and any source-supported search filters, e.g. https://www.zoopla.co.uk/for-sale/property/london/?q=London

## `location` (type: `string`):

Zoopla location slug (e.g. london, manchester) or UK postcode (e.g. SW1A). Overrides the location in the search URL and updates the q parameter.

## `minBedrooms` (type: `integer`):

Only return listings with at least this many bedrooms. Sent as Zoopla's beds\_min filter.

## `maxBedrooms` (type: `integer`):

Only return listings with at most this many bedrooms. Sent as Zoopla's beds\_max filter.

## `minPrice` (type: `integer`):

Minimum asking price or rent, in GBP. Sent as Zoopla's price\_min filter.

## `maxPrice` (type: `integer`):

Maximum asking price or rent, in GBP. Sent as Zoopla's price\_max filter.

## `propertyType` (type: `string`):

Restrict results to a Zoopla property type category.

## `results_wanted` (type: `integer`):

Maximum number of unique listing records to save. Values below 1 are raised to 1.

## `proxyConfiguration` (type: `object`):

Zoopla is protected by Cloudflare and blocks most datacenter and residential IPs. Unblocker proxy is required for reliable runs.

## Actor input object example

```json
{
  "startUrl": "https://www.zoopla.co.uk/for-sale/property/london/?q=London&search_source=home&recent_search=true",
  "location": "london",
  "propertyType": "",
  "results_wanted": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "startUrl": "https://www.zoopla.co.uk/for-sale/property/london/?q=London&search_source=home&recent_search=true",
    "results_wanted": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/zoopla-property-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 = {
    "startUrl": "https://www.zoopla.co.uk/for-sale/property/london/?q=London&search_source=home&recent_search=true",
    "results_wanted": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/zoopla-property-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 '{
  "startUrl": "https://www.zoopla.co.uk/for-sale/property/london/?q=London&search_source=home&recent_search=true",
  "results_wanted": 20
}' |
apify call parsebird/zoopla-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parsebird/zoopla-property-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/u7HGu24Ysd6vyiQBk/builds/bt8TsZt9T3Uakgle6/openapi.json
