# Zoopla.co.uk Scraper (`dhrumil/zoopla-scraper`) Actor

Scrape Zoopla.co.uk to crawl millions of sale/rent real estate properties from United Kingdom. Our real estate scraper also lets you monitor specific listing for new updates/listing. You can provide multiple search result listings to scrape/monitor.

- **URL**: https://apify.com/dhrumil/zoopla-scraper.md
- **Developed by:** [Dhrumil Bhankhar](https://apify.com/dhrumil) (community)
- **Categories:** Real estate, Automation
- **Features:** Full permissions
- **Stats:** 305 total users, 3 monthly users, 100.0% runs succeeded, 9 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $4.00 / 1,000 starter tier per 1k properties

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

### 🏡 What is Zoopla Real Estate Properties Scraper?

This Zoopla properties Scraper will enable you scrape any sale/rent listing from collection from [zoopla.co.uk](https://www.zoopla.co.uk/).

You can simply take your listing url from browser and enter it into this actor. This actor will crawl through all pages of particular listing and generate dataset for you.

Listing url is something you get when you perform the search on Zoopla site. Example listing urls :

- https://zoopla.co.uk/to-rent/property/nw2/?results_sort=newest_listings\&search_source=refine\&view_type=list
- https://zoopla.co.uk/for-sale/property/nw2/?results_sort=newest_listings
- https://www.zoopla.co.uk/for-sale/property/london-fields/?search_source=home

### 🚪 What can this Zoopla Scraper do?

📈 Extract Zoopla market data listings on Zoopla

👀 This actor is not just scraper but also has monitoring capability. You can turn on monitoring mode and it will give you only newly added properties compared to your previous scrapes.

📩 This actor also helps you identify which properties are not listed anymore. Please refer to [Identifying delisted properties](#identifying-delisted-properties)

⬇️ Download Zoopla real estate data in Excel, CSV, JSON, and other formats

### 📚 How do I start scraping with this scraper?

1. Register for your free Apify account [here](https://apify.com/pricing?fpr=z2di7)
2. You don't need to provide your credit card details for free account. Just click on "Get Started" button on above link and complete the registration only.
3. Free account comes with reasonable credits to try out this actor. This actor also comes with free trial of 3 days without any commitment/upfront charge.
4. Run this actor and verify the scraped data. Apify has huge integration possibilities. You can download the data or push the data into any 3rd party platform directly.

### 🌳 What Zoopla data can I extract using this tool?

|       📝         |             📝            |
|------------------|----------------------------|
| Listing Title    | Full Address               |
| UPRN             | EPC                        |
| Listing URL      | Category                   |
| Postal Code      | Livingrooms                |
| Bathrooms        | Bedrooms                   |
| Agent Name       | Agent Phone                |
| Listing Type     | Property Type              |
| Latitude         | Longitude                  |
| Floor            | Points Of Interest         |
| Text Description | Formatted HTML Description |
| Amenities        | Images                     |
| Price            | Size                       |
| Incode           | Outcode                    |
| Price Indicators | Rent Price                 |
| Property Name    | Property Number            |
| Last Seen Date   | Under Offer Status         |
| Property Tags    | Property Flags             |

### ⬇️ Input

For simple usecase, you just need to provide browser url of zoopla search result page & that's all. You can leave other fields as they are to be sensible defaults.

#### Input example

```json
{
    "listUrls": [
        "https://zoopla.co.uk/for-sale/property/london/?results_sort=newest_listings"
    ],
    "monitoringMode": false,
    "fullPropertyDetails": true,
    "enableDelistingTracker": false,
    "addEmptyTrackerRecord": false,
    "email": "user@example.com",
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB"
    }
}
```

You can provide `listUrls` to search properties from on Zoopla.

**Understanding input parameters:**

- `listUrls` : Array of Zoopla search result URLs to scrape. These URLs should be from zoopla.co.uk domain. Example:
  - `https://zoopla.co.uk/for-sale/property/london/?results_sort=newest_listings`
  - `https://zoopla.co.uk/to-rent/property/nw2/?results_sort=newest_listings`

- `monitoringMode` : This option when turned on will only scrape newly added property listings compared to previously scraped properties by this actor. When you keep this option on, it will scrape full list for the first time and then in next run, it will scrape only newly found incremental data.

- `fullPropertyDetails` : By default it will scrape every single property page to get full details of property. If you don't need full details but basic details is enough for you, turning off this setting would scrape a lot more faster and save costs.

- `enableDelistingTracker` : When enabled, the actor will track every property with its last seen date so that you can identify which properties are delisted from the platform. Uses Key-Value Store for state tracking.

- `addEmptyTrackerRecord` : When enabled in monitoring/incremental mode, it will add tracker ID records so that you can identify delisted properties if you have custom data processing logic.

- `email` : Email address to send notifications or reports to (for errors or important updates).

- `proxy` : Proxy configuration for the scraper. You can use Apify's residential proxy for better results on Zoopla. Default configuration uses UK-based residential proxies which is recommended.

### ⬆️ Output

The scraped data is stored in the dataset of each run. The data can be viewed or downloaded in many popular formats, such as *JSON, CSV, Excel, XML, RSS, and HTML*.

#### Output example

The result for scraping a single property:

```json
{
  "title": "4 bed flat for sale",
  "uprn": "10033640629",
  "nameOrNumber": "62, Wren House",
  "address": "Blenheim House, One Tower Bridge, London SE1",
  "epc": "https://lid.zoocdn.com/u/1024/768/b28985f714d7078fc72fcd5ab8ac8b45facf5bf5.png",
  "epcRating": "B",
  "bedrooms": "4",
  "bathrooms": "5",
  "livingroom": "1",
  "sizeSqFeet": "2470",
  "price": "£6,900,000",
  "description": "This unique apartment offers the ultimate in luxurious living. The property is set in prime position and features stunning views of the River Thames and Tower Bridge from both the entertaining space and principle suite.",
  "coordinates": {
    "latitude": "51.504199",
    "longitude": "-0.083677"
  },
  "incode": "2SF",
  "outcode": "SE1",
  "floor": "2470",
  "category": "residential",
  "type": "for-sale",
  "postalCode": "SE1 2SF",
  "features": [
    "A premium river facing four bedroom apartment",
    "2,470 sq ft (229.5 sqm)",
    "Secure Parking space",
    "Views over Tower Bridge"
  ],
  "agent": "Prime London (Riverside)",
  "agentPhone": "020 7768 6617",
  "images": [
    "https://lid.zoocdn.com/u/2400/1800/18d1a9db7827dbcf88ce7a0ccc9cbbc4b6dabdb5.jpg",
    "https://lid.zoocdn.com/u/2400/1800/afdd00de998138425cb1c2490bcbec6c83487657.jpg"
  ],
  "pointsOfInterest": [
    {
      "title": "London Bridge",
      "distance": "0.1 miles"
    },
    {
      "title": "Snowsfields Primary School",
      "distance": "0.2 miles"
    }
  ],
  "id": "66233218",
  "url": "https://www.zoopla.co.uk/for-sale/details/66233218/?search_identifier=969b7386fdcc5abdb724a45659b6e132aeb73fad3cd811c37bba93110afe3c37",
  "lastSeen": "2024-03-15T10:30:00.000Z",
  "underOffer": false,
  "tags": ["NEW_ON_MARKET"],
  "flag": null
}
```

### ❓Limitations

Since Zoopla paginates search results, you might want to break down your listing urls into smaller area if it has more than 5K results to optimize scraping efficiency. Good News is that even if multiple list urls contains overlapping results, they will get deduplicated within same run data.

This actor has ability to bypass captcha. However, please run this actor with residential proxy with country United Kingdom to get results smoothly.

### 💸 Pricing Model & Usage Logic

This actor uses a tiered pay-per-event pricing model, with usage tracked and charged based on the number of properties processed and additional multipliers. Charges are triggered at specific usage thresholds and events.

#### 🟢 Charge Events & Tiers

The actor uses a tiered pricing model based on the number of properties processed. Each tier has a specific charge event and rate per 1,000 properties:

> **🔻 Cost Efficiency as You Scale:**
> The tier-based pricing model is designed to reduce your cost per property as your usage increases. The more properties you process, the lower your per-unit cost becomes, helping keep your overall costs under control as you scale up to higher volumes.

##### Starter Tier (`starter-tier-1K`)

For the first 25,000 properties processed, the cost per 1,000 properties is **$4 USD**.
This tier is ideal for small to medium jobs and ensures a low entry cost for initial usage.

##### Growth Tier (`growth-tier-1K`)

For properties processed from 25,000 up to 50,000 the cost per 1,000 properties drops to **$3.5 USD**.
This tier rewards higher volume usage with a reduced rate, making it cost-effective for scaling up.

##### Scale Tier (`scale-tier-1K`)

For properties processed from 50,000 up to 200,000 the cost per 1,000 properties is **$3 USD**.
This tier is designed for large-scale operations, offering further discounts as your volume increases.

##### Enterprise Tier (`enterprise-tier-1K`)

For properties processed above 200,000 the cost per 1,000 properties is **$2.5 USD**.
This tier is for enterprise-level usage, providing the lowest rate for very high-volume processing.

Each charge event is triggered automatically as your processed property count crosses into the next tier. The actor tracks usage and applies the correct rate for each tier, ensuring transparent and predictable billing.

These pricing tiers are applied on a **monthly** basis, and your usage count resets at the start of each new month. This ensures you always start fresh and only pay for what you use each month.

##### Example Usage Costs:

**Scenario 1: Basic Scraping (No multipliers)**

- Input: Default settings (monitoringMode=false, fullPropertyDetails=true, enableDelistingTracker=false)
- Scraping 10,000 properties
- Multiplier: 2.0x (only fullPropertyDetails)
- Actual usage: 10,000 × 2.0 = 20,000 units
- Cost: 20,000 ÷ 1000 × $4 = **$80**

**Scenario 2: Monitoring with Tracking**

- Input: monitoringMode=true, enableDelistingTracker=true, fullPropertyDetails=true
- Scraping 5,000 properties (incremental)
- Multipliers: 3.0x (monitoring) + 2.0x (delisting) + 2.0x (full details) = 7.0x
- Actual usage: 5,000 × 7.0 = 35,000 units
- Cost: 35,000 ÷ 1000 × $4 = **$140**

**Scenario 3: Residential Proxy**

- Input: Basic setup with residential proxy enabled
- Scraping 20,000 properties
- Multipliers: 2.0x (full details) + 5.0x (residential proxy) = 7.0x
- Actual usage: 20,000 × 7.0 = 140,000 units
- Cost breakdown:
  - First 25,000 units @ $4/1K = $100
  - Remaining 105,000 units @ $3.5/1K = $367.50
  - **Total: $467.50**

#### 📊 Cost Per 1K Units – How Billing Works

The pricing is calculated in **batches of 1,000 units**. This means:

- **Initial Charge:** When you start the actor, it reserves and charges you for **1K units** (1,000 properties or their equivalent based on multipliers).
- **Continuous Usage:** You can continue scraping in the same run or across multiple runs. As long as your usage stays within that 1K batch, **no additional charges** are applied.
- **Next Batch:** Only when you **exhaust the 1K quota**, the system charges you for the **next 1K batch**. This billing cycle repeats for every 1K units consumed.
- **Pay-As-You-Go:** You only pay for the batches you actually use. If you scrape 1,500 properties in total (across runs), you'll be charged for 2 batches (2K units).

**Example Timeline:**

1. Start run #1 → Charged for 1K units (can scrape up to 1,000 properties)
2. Scrape 800 properties in run #1 (200 units remaining in current 1K batch)
3. Start run #2 → Use the remaining 200 units + 100 from next 1K batch → Charged for 2nd 1K batch
4. Continue in run #3 → Still within the 2K batch until you exceed it
5. When you exceed 2K total → Automatically charged for 3rd 1K batch

This ensures **predictable billing** in discrete 1K chunks, making it easier to manage your usage and costs.

#### ⚡ Additional Usage Parameters (Multipliers & Penalties)

The actor may apply additional usage multipliers based on your input settings. These do **not** directly charge you extra, but they affect how quickly you use up your monthly quota. The more features you enable, the faster your included usage is consumed.

##### Feature Multipliers:

- **🌐 Residential Proxy Usage:** If you use a residential proxy (`apifyProxyGroups` includes 'RESIDENTIAL'), an additional **5x** usage multiplier will apply. This is due to the higher cost and complexity of residential proxy traffic.

- **🧠 Memory Usage:** Base memory is **2 GB (2048 MB)**. If you run the actor with more than 2 GB of memory, you will be charged an additional usage multiplier. For example, running at 4 GB (2 GB above base) will add 1x multiplier, and running at 6 GB (4 GB above base) will add 2x multiplier. The charge is cumulative per 2 GB block above the base.

- **🔄 Monitoring Mode:** Enabling `monitoringMode` adds a **3.0x** multiplier, as it requires additional logic and storage for incremental scraping and state tracking.

- **📄 Full Property Details:** Enabling `fullPropertyDetails` adds a **2.0x** multiplier. This requires fetching and processing individual property pages for extended information.

- **🕵️ Delisting Tracker:** Enabling `enableDelistingTracker` adds a **2.0x** multiplier, as it requires additional logic and storage for tracking property removal and maintaining state.

- **📋 Empty Tracker Records:** Enabling `addEmptyTrackerRecord` adds **0.5x** multiplier for tracking records in incremental mode.

##### Penalties:

- **⚠️ Invalid Domain URLs:** If you provide URLs not from zoopla.co.uk domain, it will cause a **10x multiplier** penalty on your usage charge.

- **❌ Missing Input:** If no URLs are provided for scraping, it will incur a **10x multiplier** penalty to discourage empty runs.

- **🚫 Blocked Requests (403/429):** When the actor encounters HTTP 403 (Forbidden) or 429 (Too Many Requests) responses, it will charge **2x multiplier** for each blocked request. The session will be automatically retired to change the user/proxy. This charge helps offset the cost of proxy rotation and additional resources needed to recover from blocks.

These multipliers are **cumulative**. For example, if you enable both `monitoringMode` and `enableDelistingTracker`, your usage for each property will be multiplied by 5.0x (3.0x + 2.0x).

> **💡 Tip:**
> For best cost efficiency, run this actor on **2 GB memory** with **RESIDENTIAL proxy disabled** (basic proxy only). The actor is optimized for this setting, which is the base memory allocation. Using more than 2 GB will increase your additional usage charges (1x multiplier per 2 GB block above base). Only increase if you have a specific need.

#### 📊 Safeguarding & Monitoring

The actor includes several safeguarding mechanisms to protect your account and ensure fair usage:

1. **Billing Watchdog:** The actor monitors billing activity every hour. If no billing events are detected for more than 1 hour during a run, the actor will automatically abort to prevent unexpected charges.

2. **Subscription Verification:** At the start of each run, the actor verifies your subscription status to ensure you're authorized to use paid features.

3. **URL Validation:** All input URLs are validated to ensure they're from the Zoopla domain before scraping begins.

4. **Usage Buffering:** Usage is buffered and validated against your account limits before charges are applied.

### 🔎 Identifying delisted properties

This actor provides you monitoring mode configuration using which you can get only incremental updates about newly added properties. In case, you also want to identify which properties are delisted from platform, you can use any of the following techniques with the help of this actor.

#### 1. Running Always in full scraper mode

Run this actor always in full scrape mode and cross check the new incoming batch of data with your existing database. If any property that exists in your database but not in newly scraped data batch, that means it's not listed anymore.

#### 2. Use Key Value Store generated by scraper

If you are monitoring very large batch of data and you don't want to scrape everything all the time, this method involves bit of technicality but achieves the goal effectively. Apify has storage feature called [Key-value store](https://docs.apify.com/api/v2/#/reference/key-value-stores/key-collection/get-list-of-keys). When you run this scrape, this scraper stores every single property in key value store along with timestamp in `zoopla-properties` store. Inside this store, key is property id itself and value is timestamp like this:

```json
{ 
  "lastSeen": "2024-03-15T10:30:25.763Z",
  "price": "£525,000",
  "underOffer": false,
  "tags": ["New on market"],
  "flag": null
}
```

Whenever you run this scraper, it will update the timestamp against particular id if it finds property on the platform. For example if we have 2 properties with id `prop1` and `prop2` and we scraped them both on March 1, key value storage would look like this:

```
prop1 -> { "lastSeen": "2024-03-01T05:59:25.763Z", "price": "£500,000", ... }
prop2 -> { "lastSeen": "2024-03-01T05:59:25.763Z", "price": "£550,000", ... }
```

Now if you run this scraper again on March 15 and prop1 is not on the platform anymore but prop2 is still there, key value storage would change like this:

```
prop1 -> { "lastSeen": "2024-03-01T05:59:25.763Z", "price": "£500,000", ... }
prop2 -> { "lastSeen": "2024-03-15T05:59:25.763Z", "price": "£550,000", ... }
```

That means if any property has `lastSeen` less than latest batch you loaded, that property is delisted now. You can directly iterate through whole Key value storage using Apify key value storage API to identify this. Please refer to [this](https://docs.apify.com/api/v2/#/reference/key-value-stores/key-collection/get-list-of-keys) API documentation to do the same. Please remember store name generated by this scrape will be `zoopla-properties`.

Alternatively, you can iterate through your existing database active properties and use [this](https://docs.apify.com/api/v2/#/reference/key-value-stores/record/get-record) API to identify listing status.

For this approach to work, it's important that you enable this feature via `enableDelistingTracker` (Enable Delisting tracker) input.

### 🤝 Related Actors

- [Rightmove Scraper](https://apify.com/dhrumil/rightmove-scraper?fpr=z2di7): Scrape property sale/rent listings, prices, and details from Rightmove.
- [OnTheMarket Scraper](https://apify.com/dhrumil/onthemarket-scraper?fpr=z2di7) : Scrape property sale/rent listings, prices, and details from OnTheMarket.
- [Rightmove Full Address & House Number Finder](https://apify.com/dhrumil/rightmove-full-address-house-number-finder?fpr=z2di7): Find full addresses and house numbers for Rightmove listings.
- [Rightmove Land Registry Full Address & House Number Finder](https://apify.com/dhrumil/rightmove-landregistry-full-address-house-number-finder?fpr=z2di7): Get full address and house number using Land Registry data for Rightmove properties.
- [Rightmove EPC Full Address Finder](https://apify.com/dhrumil/rightmove-epc-full-address-finder?fpr=z2di7): Find EPC and full address details for Rightmove listings.
- [Rightmove Commercial Scraper](https://apify.com/dhrumil/rightmove-commercial-scraper?fpr=z2di7): Scrape commercial property listings from Rightmove.
- [Rightmove Sold House Properties Scraper](https://apify.com/dhrumil/rightmove-sold-house-properties-scraper?fpr=z2di7): Scrape sold house price data from Rightmove.
- [Rightmove Agents Scraper](https://apify.com/dhrumil/rightmove-agents-scraper?fpr=z2di7): Extract agent and agency details from Rightmove.
- [Zoopla Sold Properties Scraper](https://apify.com/dhrumil/zoopla-sold-properties-scraper?fpr=z2di7): Scrape sold property data from Zoopla.
- [Zoopla Commercial Properties Scraper](https://apify.com/dhrumil/zoopla-commercial-properties-scraper?fpr=z2di7): Scrape commercial property listings from Zoopla.

### 🙋‍♀️ For custom solutions

In case you need some custom solution, you can contact me : <dhrumil@techvasu.com>

Or learn more about me on github : <https://github.com/dhrumil4u360>

# Actor input Schema

## `listUrls` (type: `array`):

Any zoopla sale or rent property listing url which has list of properties

## `monitoringMode` (type: `boolean`):

If checked, it will only scrape newly listed properties compared to what has been scraped in previous runs. Please turn off full scrape setting above in case you are tunring this on.

## `fullPropertyDetails` (type: `boolean`):

If checked, it will scrape each individual property to get more details about property. If you need only limited information, turning off this option would scrape a lot more faster.

## `addEmptyTrackerRecord` (type: `boolean`):

If checked, it will add tracker ID record in incremental mode so that you can identify delisted properties if you have custom loader

## `enableDelistingTracker` (type: `boolean`):

If checked, it will track every single property with date so that you can find out which property is delisted. ( Enabling this has impact on billing )

## `email` (type: `string`):

Email address to send notifications or reports to.

## `proxy` (type: `object`):

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "listUrls": [
    {
      "url": "https://www.zoopla.co.uk/for-sale/property/london/ec4/fleet-street-temple-blackfriars-st-pauls/?beds_min=4&q=ec4&radius=0.25&results_sort=newest_listings&search_source=for-sale"
    }
  ],
  "monitoringMode": false,
  "fullPropertyDetails": true,
  "addEmptyTrackerRecord": false,
  "enableDelistingTracker": false,
  "email": "",
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# 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 = {
    "listUrls": [
        {
            "url": "https://www.zoopla.co.uk/for-sale/property/london/ec4/fleet-street-temple-blackfriars-st-pauls/?beds_min=4&q=ec4&radius=0.25&results_sort=newest_listings&search_source=for-sale"
        }
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "GB"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dhrumil/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 = {
    "listUrls": [{ "url": "https://www.zoopla.co.uk/for-sale/property/london/ec4/fleet-street-temple-blackfriars-st-pauls/?beds_min=4&q=ec4&radius=0.25&results_sort=newest_listings&search_source=for-sale" }],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("dhrumil/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 '{
  "listUrls": [
    {
      "url": "https://www.zoopla.co.uk/for-sale/property/london/ec4/fleet-street-temple-blackfriars-st-pauls/?beds_min=4&q=ec4&radius=0.25&results_sort=newest_listings&search_source=for-sale"
    }
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}' |
apify call dhrumil/zoopla-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dhrumil/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/teOj85DgYAQSZUKeJ/builds/5qm8eLPLC7QRBaRUr/openapi.json
