# Zoopla Uk Property Scraper with Contacts & Features (`fatihtahta/zoopla-uk-property-scraper`) Actor

Extract structured Zoopla UK sale and rental listings with asking prices, full descriptions, property specs, photos, floor plans, coordinates, agency details and public phone numbers. Built for market research, comps, inventory monitoring, CRM enrichment, BI and AI workflows.

- **URL**: https://apify.com/fatihtahta/zoopla-uk-property-scraper.md
- **Developed by:** [Fatih Tahta](https://apify.com/fatihtahta) (community)
- **Categories:** Real estate, Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Zoopla UK Property Scraper

**Slug:** `fatihtahta/zoopla-uk-property-scraper`

### Overview

Zoopla UK Property Scraper collects public UK sale and rental listings with structured identity, location, asking-price, property, availability, media and advertiser fields. [Zoopla](https://www.zoopla.co.uk/) is a major UK property portal whose public listings are useful for property discovery, asking-price research, inventory monitoring and market segmentation. The actor supports location-driven searches, direct individual Zoopla listing URLs and a documented set of sale, rental and shared property filters. Optional enrichment can add richer listing details and additional public contact information when available. Runs are repeatable, configurable and suitable for scheduled monitoring as well as one-time research. Results are delivered as structured dataset records for review, export, ETL pipelines, BI dashboards, AI-agent workflows and downstream processing. The actor is designed for dependable recurring acquisition of publicly visible listing data while keeping source availability, optional-field variability and point-in-time status clear.

### What Makes This Actor Different

- **Pipeline-ready property records:** every row uses a documented `property_listing` envelope with stable identity and nested `source_context`, `entity`, `location`, `pricing`, `property`, `listing`, `media`, `contact_details`, `relationships` and `attributes` groups.
- **Buy and rent modes with mode-specific filters:** choose one listing mode, then apply common filters plus supported sale-only or rental-only criteria without mixing incompatible controls.
- **Direct listing collection:** provide one or more individual Zoopla property-detail URLs when you already know exactly which listings to collect.
- **Optional detail and contact enrichment:** request richer descriptions, specifications, material information, media and advertiser context, plus an additional public phone number when Zoopla makes one available.
- **Coverage-aware collection:** `maximize_coverage` can collect deeper within the same selected criteria when a broad search reports more matches than are normally visible at once. It does not relax the selected location or filters.
- **Operational run receipts:** `RUN-SUMMARY`, `RUN-SUMMARY.html` and `results-map` provide saved counts, completion state, coverage status, enrichment outcomes, coordinate coverage, warnings and map readiness outside the listing dataset.
- **Map-ready review:** coordinate-capable listings are placed on an interactive map, while invalid or missing coordinates are counted rather than silently represented as valid points.
- **Agent-friendly handoff:** optional user-authorized MCP connectors receive a concise run summary and available Apify output links after the dataset and run artifacts are ready; the full listing dataset remains the primary output.

### Who Should Use This Actor

- **Real estate investors and analysts:** assemble scoped public listing sets for asking-price comparisons, property-mix analysis and analyst review without treating listing prices as valuations.
- **Brokerages and agency operations teams:** monitor public inventory, location segments, listing status, advertiser visibility and contact-ready records for internal workflows.
- **Market research and analytics teams:** create repeatable snapshots by geography, property type, price band, publication window or keyword for dashboards and reporting.
- **Proptech and data engineering teams:** ingest schema-aware property records into warehouses, CRMs, search indexes, applications and enrichment pipelines.
- **AI agents and workflow automations:** generate a valid scoped input, collect records, inspect the run receipt and route normalized listings to research or review steps.
- **Lead enrichment teams:** add current public listing, agency and phone attributes to existing records when the relevant fields are publicly available.
- **Monitoring and operations teams:** schedule recurring runs and compare stable listing identifiers, asking prices, statuses and selected property attributes over time.

### Common Use Cases

- **Market intelligence:** monitor public sale or rental supply, asking prices, property types, locations, listing statuses and advertiser mix.
- **Comparable-listing research:** collect listings for a specific geography, price band, bedroom range, property type or keyword.
- **New-listing monitoring:** use a publication window and repeatable input to review recently added public inventory.
- **Price and status change detection:** compare repeated exports by `record_id`, then inspect asking-price, status and history fields that are available in both runs.
- **CRM and catalog enrichment:** attach public listing, property, agency, media and contact attributes to internal records.
- **Geographic review:** use coordinates and the interactive map to inspect the distribution of saved listings.
- **Recurring reporting:** schedule the same search for dashboard refreshes, inventory snapshots, alerts and operational reports.
- **Agentic property research:** let an internal agent define a supported segment, collect it, verify the run summary and hand records to analysis or human review.

### Real-World Questions This Data Can Answer

- Which public Zoopla listings match a UK location, buy or rent mode, price band, property type, bedroom range or keyword?
- What asking prices and rental frequencies are displayed for the selected segment at run time?
- Which saved listings are marked available, chain free, shared ownership, retirement, auction-related or otherwise status-qualified when those fields are published?
- Which property types, bedroom counts, regions and agencies are most visible in this scoped result set?
- Which records contain richer descriptions, floor plans, EPC information, material information or public contact phones?
- Which listings have usable coordinates for geographic review and mapping?
- Which listings appear new, repriced or status-changed when this run is compared with an earlier internal snapshot?
- Did the run reach its requested limit, use deeper matching coverage or finish with skipped or partial outcomes?

### Quick Start

1. Choose `deal_type` as `buy` or `rent`.
2. Enter one focused UK `location`, or provide individual Zoopla listing-detail URLs in `url`.
3. Add only the filters relevant to the selected listing mode and start with a small `limit`, such as 10 or 25.
4. Run the actor in Apify Console and inspect the first dataset records.
5. Review `RUN-SUMMARY` and `results-map`, then increase the limit, enable enrichment or schedule the input once the output fits your workflow.

### Input Parameters

Inputs define one sale or rental collection scope, optional enrichment, a maximum output count and optional post-run summary delivery.

| Parameter | Type | Description | Default |
| --- | --- | --- | --- |
| `deal_type` | single select | Listing mode: `buy` or `rent`. Determines which mode-specific filters are valid. | `buy` |
| `location` | string | UK city, postcode, neighborhood, county or market, such as `South London`, `Birmingham` or `SW1A`. | – |
| `url` | string array | Individual Zoopla `/for-sale/details/.../`, `/to-rent/details/.../` or `/new-homes/details/.../` URLs. Search-result URLs are not accepted. | Empty |
| `radius` | single select | Distance around the selected location in miles: `0`, `0.25`, `0.5`, `1`, `3`, `5`, `10`, `15`, `20`, `30` or `40`. `0` means the selected area only. | – |
| `min_bedroom` | single select | Minimum bedrooms from `0` through `10`; `0` includes studios. | – |
| `max_bedroom` | single select | Maximum bedrooms from `0` through `10`; `0` means studios only. | – |
| `min_bathroom` | single select | Minimum bathrooms from `1` through `10`. | – |
| `max_bathroom` | single select | Maximum bathrooms from `1` through `10`. | – |
| `min_price` | integer | Minimum asking price in GBP. Rent searches use Zoopla's monthly rent scale. | – |
| `max_price` | integer | Maximum asking price in GBP. Rent searches use Zoopla's monthly rent scale. | – |
| `property_type` | string array | Any of `semi-detached`, `detached`, `terraced`, `bungalow`, `park-home`, `flats` or `farms-land`. | Empty |
| `retirement_home` | single select | `include`, `exclude` or `only` retirement-home listings. | – |
| `features` | string array | Any supported feature: `period-property`, `cottage`, `modern`, `ev-charging`, `utility-room`, `basement`, `conservatory`, `home-office`, `en-suite`, `bathtub`, `patio`, `kitchen-island` or `needs-modernisation`. | Empty |
| `publication_date` | single select | Listings added within `24-hours`, `3-days`, `7-days`, `14-days` or `30-days`. | – |
| `keyword` | string | Free-text listing keyword, such as `balcony`, `parking` or `air conditioning`. | – |
| `rental_house_share` | single select | For rent mode: `include`, `exclude` or `only` shared accommodation. | – |
| `rental_student_accommodation` | single select | For rent mode: `include`, `exclude` or `only` student accommodation. | – |
| `rental_availability` | single select | For rent mode: `now`, `one-month`, `three-months`, `six-months` or `twelve-months`. | – |
| `furnishment` | single select | For rent mode: `furnished`, `part-furnished` or `unfurnished`. | – |
| `include_let_agreed` | boolean | Include rental listings marked let or let agreed. | `false` |
| `sale_new_build_home` | single select | For buy mode: `include`, `exclude` or `only` new-build homes. | – |
| `sale_shared_ownership` | single select | For buy mode: `include`, `exclude` or `only` shared-ownership listings. | – |
| `sale_owner_type` | string array | For buy mode: any of `leasehold`, `freehold` or `share-of-freehold`. | Empty |
| `sale_property_status` | string array | For buy mode: any of `chain-free`, `reduced-price` or `under-offer-or-sold-stc`. | Empty |
| `sale_low_deposit_mortgage` | boolean | Require a supported low-deposit mortgage incentive on buy listings. | `false` |
| `enrich_data` | boolean | Add richer public listing details to query-driven results. Individual `url` inputs always read their detail pages. | `true` |
| `get_contact` | boolean | Add an additional public agent or agency phone number when available. This works independently of `enrich_data`. | `false` |
| `maximize_coverage` | boolean | For requested limits of at least 1,100, collect deeper within the same selected criteria when the source reports more matching listings than are normally visible. | `false` |
| `limit` | integer | Maximum number of listing records to save; minimum `1`. Leave empty to continue through the available selected scope. | – |
| `mcpConnectors` | MCP connector array | User-authorized Apify connectors that can receive a concise post-run summary and available dataset, report and map links. Full listing rows are not sent. | Empty |

### Choosing Inputs

Use `location` when you want a readable, reusable search built from the documented fields. Keep one main geography per run when city, neighborhood or postcode comparisons need clean segmentation. Use `url` when you already know the individual listings to collect. Each URL is fetched directly as one property and does not create or modify a search.

Choose `buy` or `rent` before adding filters. Price values represent sale asking prices in buy mode and Zoopla's monthly rent scale in rent mode. Bedrooms, bathrooms, radius, property type, publication date, keyword, retirement status and features can narrow either mode; rental and sale controls apply only to their matching mode. Narrower criteria produce more targeted datasets, while fewer filters support broader discovery.

Start with a small `limit` and inspect a few records before increasing collection size. Use `enrich_data` when descriptions, material information, specifications and expanded media matter; use `get_contact` when an additional public phone is useful. Keep `maximize_coverage` for broad, high-volume searches where deeper matching collection matters more than the shortest exploratory run. It preserves the selected criteria and respects `limit`, but it can increase run time.

### Input Recipes

- **Validation run:** choose one location and deal type, keep optional filters empty and set `limit` to 10. Inspect identity, pricing, location and property groups before scaling.
- **Targeted rental search:** use `rent`, one location, a monthly price range, bedroom range, property type, availability and furnishing state. Enable contact collection only if phone data is needed.
- **Targeted sale segment:** use `buy`, one location, sale price range, property type, tenure and a supported sale status such as chain free or reduced price.
- **Known listing set:** paste individual Zoopla detail URLs into `url` to collect those properties directly without running a search.
- **Maximum matching coverage:** use a broad location or high-volume segment, set a limit of at least 1,100 and enable `maximize_coverage` to collect deeper within the same criteria.
- **Recurring monitoring:** save one validated input, run it on a schedule and compare `record_id`, asking price, listing status and available history fields between exports.

### Example Inputs

#### Targeted sale listings in South London

```json
{
  "deal_type": "buy",
  "location": "South London",
  "min_price": 300000,
  "max_price": 750000,
  "property_type": ["flats", "terraced"],
  "publication_date": "7-days",
  "limit": 25
}
````

#### Enriched furnished rentals in Birmingham

```json
{
  "deal_type": "rent",
  "location": "Birmingham",
  "min_bedroom": "2",
  "rental_availability": "three-months",
  "furnishment": "furnished",
  "enrich_data": true,
  "get_contact": true,
  "limit": 25
}
```

#### Individual Zoopla listing URLs

```json
{
  "url": [
    "https://www.zoopla.co.uk/for-sale/details/70000001/",
    "https://www.zoopla.co.uk/new-homes/details/70000002/"
  ],
  "get_contact": false,
  "limit": 2
}
```

### Output

#### Output destination

The actor writes results to an Apify dataset as JSON records. The dataset is designed for direct consumption by analytics tools, ETL pipelines, AI agents, and downstream APIs with minimal post-processing.

The current public dataset contains one record family: `property_listing`. Run-level summaries, the HTML report and the interactive map are separate key-value-store artifacts rather than dataset rows.

#### Record envelope and stable identifiers

Every record requires `record_type`, `record_id`, `url`, `source_context` and `entity`. The recommended idempotency key is the composite `source_context.source_id + record_id`; for a Zoopla-only table, `record_id` is sufficient. Use this key for deduplication and upserts instead of result position, title or address. Stable identifiers make records easier to merge, sync and compare across repeated runs.

The canonical `url` opens the public listing. `source_context.source_url` identifies the search scope that produced the row when available, while page, position and enrichment fields provide collection context. `location.uprn` can support property-level joins when published, but it is optional and should not replace the listing-level idempotency key.

#### Example: enriched rental property listing

The following is a synthetic, sample-safe record using the current public structure and value types. Optional groups and fields vary by listing.

```json
{
  "record_type": "property_listing",
  "record_id": "70000000",
  "url": "https://www.zoopla.co.uk/to-rent/details/70000000/",
  "source_context": {
    "source_id": "zoopla_uk_property_scraper",
    "source": "zoopla",
    "source_domain": "zoopla.co.uk",
    "source_url": "https://www.zoopla.co.uk/to-rent/property/birmingham/?q=Birmingham&search_source=to-rent",
    "page_number": 1,
    "position": 1,
    "country": "United Kingdom",
    "language": "en",
    "enrichment_status": "enriched",
    "enriched_fields": [
      "entity.description",
      "property.material_information",
      "contact_details.phones"
    ],
    "detail_enrichment_status": "enriched",
    "contact_enrichment_status": "enriched"
  },
  "entity": {
    "title": "2 bed flat to rent",
    "description": "Sample description for a furnished two-bedroom apartment close to local transport."
  },
  "location": {
    "address": "18 Example Road, Birmingham B15",
    "city": "Birmingham",
    "county": "West Midlands",
    "region": "West Midlands",
    "postal_code": "B15 1AA",
    "outcode": "B15",
    "country": "United Kingdom",
    "latitude": 52.4691,
    "longitude": -1.9322,
    "is_approximate": true,
    "neighborhood": "Edgbaston",
    "nearby_transport": [
      {
        "name": "Birmingham Five Ways",
        "type": "train",
        "distance_miles": 0.7
      }
    ]
  },
  "pricing": {
    "price": 1250,
    "price_text": "£1,250 pcm",
    "currency": "GBP",
    "price_frequency": "pcm",
    "alternate_price": {
      "price": 288,
      "price_text": "£288 pw",
      "frequency": "pw"
    }
  },
  "property": {
    "property_type": "flat",
    "bedrooms": 2,
    "bathrooms": 1,
    "living_rooms": 1,
    "floor_area": 780,
    "area_unit": "sqft",
    "epc_rating": "C",
    "council_tax_band": "Band B",
    "features": ["Furnished", "Close to transport"],
    "material_information": [
      {
        "key": "deposit",
        "title": "Deposit",
        "value": "£1,440"
      }
    ]
  },
  "listing": {
    "deal_type": "rent",
    "listing_type": "residential",
    "listing_status": "available",
    "posted_at": "2026-07-10T09:30:00",
    "posted_at_label": "Listed on",
    "available_from": "1st Aug 2026",
    "available_from_label": "Available from",
    "furnishment": "furnished",
    "condition": "pre-owned",
    "member_type": "agent",
    "is_premium": false,
    "is_retirement_home": false,
    "is_shared_ownership": false,
    "is_auction": false
  },
  "media": {
    "main_image_url": "https://lid.zoocdn.com/sample-listing.jpg",
    "image_urls": [
      "https://lid.zoocdn.com/sample-listing.jpg"
    ],
    "image_count": 12,
    "floorplan_count": 1,
    "floorplans": [
      {
        "url": "https://lc.zoocdn.com/sample-floorplan.jpg"
      }
    ]
  },
  "contact_details": {
    "phones": ["0121 000 0000"]
  },
  "relationships": {
    "agency": {
      "agency_id": "50000",
      "name": "Example Property Partners",
      "url": "https://www.zoopla.co.uk/find-agents/branch/example-property-partners-birmingham-50000/",
      "is_developer": false
    }
  },
  "attributes": {
    "source_specific": {
      "listing_revision_id": "sample-revision-id",
      "smart_tags": ["Modern", "Home office"]
    }
  }
}
```

#### Run Summary, Map, And Artifacts

The default dataset remains the authoritative listing export. The actor also exposes these run-level outputs through the run's key-value-store links:

| Artifact | Purpose |
| --- | --- |
| `RUN-SUMMARY` | Machine-readable run receipt with input scope, saved and parsed counts, requested limit, stop reason, duplicate and skipped counts, coverage state, enrichment outcomes, price and property breakdowns, coordinate coverage, map counts, warnings and artifact names. |
| `RUN-SUMMARY.html` | Human-readable report presenting the main completion, enrichment, location, pricing and warning indicators. |
| `results-map` | Interactive clustered map for saved listings with valid coordinates, including mapped, skipped-coordinate and duplicate-marker counts. |

Property teams can use these artifacts to review a run without opening every row. Data teams and AI agents can use them as run receipts for completion checks, recurring-run comparison, alert routing and retry decisions. When `maximize_coverage` is enabled, the summary indicates that state, reports deeper-coverage activity and records whether the requested limit or another stop condition ended the run.

### Field Reference

Only `record_type`, `record_id`, `url`, `source_context` and `entity` are required at the top level. All other groups and nested fields are optional unless stated otherwise.

#### Record identity

- **record\_type** *(string, required)*: record family; currently always `property_listing`.
- **record\_id** *(string, required)*: stable Zoopla listing identifier.
- **url** *(string, required)*: canonical public Zoopla listing URL.

#### Source context

- **source\_context** *(object, required)*: provenance, result position and enrichment context.
- **source\_context.source\_id** *(string, optional)*: stable source identifier used for lineage and composite idempotency.
- **source\_context.source / source\_context.source\_domain** *(string, optional)*: normalized source label and public domain.
- **source\_context.source\_url** *(string, optional)*: public Zoopla source page that produced the row: a search-result page for query runs or the detail page for direct listing-URL runs.
- **source\_context.page\_number / source\_context.position** *(integer, optional)*: observed result page and position; neither is a stable identity.
- **source\_context.country / source\_context.language** *(string, optional)*: source country and content language.
- **source\_context.enrichment\_status** *(string, optional)*: `lightweight` or `enriched`.
- **source\_context.enriched\_fields** *(string array, optional)*: field paths added or changed by enrichment.
- **source\_context.detail\_enrichment\_status** *(string, optional)*: present as `enriched` when richer listing details added useful fields.
- **source\_context.detail\_enriched\_fields** *(string array, optional)*: fields changed by detail enrichment.
- **source\_context.contact\_enrichment\_status** *(string, optional)*: present as `enriched` when public contact collection adds a phone.
- **source\_context.contact\_enriched\_fields** *(string array, optional)*: fields changed by contact enrichment.

#### Entity

- **entity** *(object, required)*: human-readable listing identity.
- **entity.title** *(string, optional)*: compact source-provided listing title.
- **entity.description** *(string, optional)*: public listing summary or richer description when available.

#### Location

- **location** *(object, optional)*: public address, geographic labels and coordinates.
- **location.address** *(string, optional)*: displayed address, which can be partial.
- **location.city / location.county / location.region** *(string, optional)*: normalized geographic labels.
- **location.postal\_code / location.outcode** *(string, optional)*: public postcode and postcode district.
- **location.country** *(string, optional)*: normalized country label.
- **location.latitude / location.longitude** *(number, optional)*: coordinate pair used for mapping when valid.
- **location.is\_approximate** *(boolean, optional)*: indicates that the public map point is approximate.
- **location.neighborhood** *(string, optional)*: local area label.
- **location.property\_number\_or\_name / location.street\_name** *(string, optional)*: separately published address components.
- **location.uprn** *(string, optional)*: published Unique Property Reference Number; availability varies.
- **location.nearby\_transport** *(object array, optional)*: nearby public transport entries.
- **location.nearby\_transport\[].name / type** *(string, optional)*: transport point name and category.
- **location.nearby\_transport\[].distance\_miles** *(number, optional)*: approximate distance in miles.

#### Pricing

- **pricing** *(object, optional)*: displayed asking-price or rent values.
- **pricing.price** *(number, optional)*: numeric asking price or rent.
- **pricing.price\_text / pricing.short\_price\_text** *(string, optional)*: full and compact source display labels.
- **pricing.currency** *(string, optional)*: normalized currency code, typically `GBP`.
- **pricing.original\_price** *(number, optional)*: earlier or original asking price when published.
- **pricing.price\_per\_area** *(number, optional)*: asking price per area unit; interpret with `property.area_unit`.
- **pricing.price\_qualifier** *(string, optional)*: wording such as guide price or offers over.
- **pricing.price\_frequency** *(string, optional)*: rental period such as `pcm` or `pw`.
- **pricing.alternate\_price** *(object, optional)*: equivalent rent at another frequency.
- **pricing.alternate\_price.price** *(number, optional)*: alternate numeric rent.
- **pricing.alternate\_price.price\_text / frequency** *(string, optional)*: alternate display label and frequency.
- **pricing.price\_change** *(object, optional)*: compact source price-change summary.
- **pricing.price\_change.first\_price\_date / last\_price\_change\_date** *(string, optional)*: source-formatted price dates.
- **pricing.price\_change.percentage\_change\_label** *(string, optional)*: source display value for percentage change.

#### Property

- **property** *(object, optional)*: physical, tenure and material property attributes.
- **property.property\_type** *(string, optional)*: normalized residential property category.
- **property.bedrooms / property.bathrooms / property.living\_rooms** *(number, optional)*: published room counts.
- **property.floor\_area** *(number, optional)*: numeric floor area; always interpret with `area_unit`.
- **property.area\_unit** *(string, optional)*: floor-area unit such as `sqft` or `sq. ft`.
- **property.floor\_area\_source** *(string, optional)*: source context for the floor-area value.
- **property.epc\_rating** *(string, optional)*: published energy performance rating.
- **property.tenure** *(string, optional)*: ownership or tenure label, mainly for sale listings.
- **property.council\_tax\_band** *(string, optional)*: published council-tax band or availability label.
- **property.features** *(string array, optional)*: deduplicated public features, highlights and tags.
- **property.material\_information** *(object array, optional)*: structured public topics such as deposit, utilities, parking or restrictions.
- **property.material\_information\[].key / title / value** *(string, optional)*: machine key, display label and published value.

#### Listing

- **listing** *(object, optional)*: mode, publication, availability, promotion and status values.
- **listing.deal\_type** *(string, optional)*: normalized `buy` or `rent` mode.
- **listing.listing\_type / listing.display\_type** *(string, optional)*: source listing and display categories.
- **listing.featured\_type / listing.result\_group** *(string, optional)*: result presentation labels, not property-quality signals.
- **listing.listing\_status** *(string, optional)*: point-in-time availability status such as `available` or `under_offer`.
- **listing.posted\_at / listing.posted\_at\_label** *(string, optional)*: publication value and its source label.
- **listing.available\_from / listing.available\_from\_label** *(string, optional)*: rental availability value and label.
- **listing.is\_premium** *(boolean, optional)*: premium result-treatment flag, not a verification signal.
- **listing.condition / listing.furnishment / listing.member\_type** *(string, optional)*: condition, furnishing and advertiser classification.
- **listing.chain\_free** *(boolean, optional)*: source-provided chain-free sale signal.
- **listing.is\_auction / listing.is\_shared\_ownership / listing.is\_retirement\_home** *(boolean, optional)*: source-provided listing flags.
- **listing.history** *(object array, optional)*: source price-history events added when available.
- **listing.history\[].is\_price\_drop** *(boolean, optional)*: whether the event represents a price reduction.
- **listing.history\[].changed\_at** *(string, optional)*: source timestamp for the event.
- **listing.history\[].price / price\_text** *(number/string, optional)*: historical numeric and displayed asking price.

#### Media

- **media** *(object, optional)*: public listing images, plans, documents, brochures, videos and tours.
- **media.main\_image\_url** *(string, optional)*: primary public listing image URL.
- **media.image\_urls** *(string array, optional)*: deduplicated gallery URLs in source order.
- **media.image\_count / floorplan\_count / video\_count** *(number, optional)*: source-reported or normalized media counts.
- **media.floorplans / media.epc\_documents / media.virtual\_tours** *(object array, optional)*: media items containing a public `url`.
- **media.brochure\_urls / media.video\_urls** *(string array, optional)*: public brochure and video links.

#### Contact details and relationships

- **contact\_details** *(object, optional)*: public agent or agency contact values.
- **contact\_details.phones** *(string array, optional)*: deduplicated public phone numbers.
- **contact\_details.phone\_source** *(string, optional)*: source label for an additionally revealed public phone.
- **relationships** *(object, optional)*: public advertiser relationship.
- **relationships.agency** *(object, optional)*: agency or branch attached to the listing.
- **relationships.agency.agency\_id / name** *(string, optional)*: public advertiser identifier and name.
- **relationships.agency.url / logo\_url** *(string, optional)*: public agency profile and logo URLs.
- **relationships.agency.is\_developer** *(boolean, optional)*: source-provided developer classification.

#### Source-specific attributes

- **attributes** *(object, optional)*: non-duplicate Zoopla-specific values for specialist workflows.
- **attributes.source\_specific** *(object, optional)*: source-specific listing values that do not duplicate the canonical groups.
- **attributes.source\_specific.listing\_revision\_id** *(string, optional)*: source revision identifier; not the primary listing ID.
- **attributes.source\_specific.smart\_tags** *(string array, optional)*: deduplicated Zoopla smart-tag labels.

### Data Model Notes

- **Identity:** use `source_context.source_id + record_id` for cross-source upserts, or `record_id` within a Zoopla-only table.
- **Provenance:** use `url` to open the listing and `source_context.source_url` to audit the search scope when present.
- **Property value:** `entity`, `location`, `pricing`, `property`, `listing` and `media` carry the main consumer-facing attributes.
- **Point-in-time values:** asking prices, availability, descriptions, public contact details and listing statuses reflect what was visible at run time.
- **Nested groups:** related values remain grouped to support JSON-first ETL, review and agent context without ambiguous flat column names.
- **Optionality:** null-check or existence-check every non-required group and nested field; availability depends on the listing, mode and public source record.
- **Repeated runs:** compare stable identifiers and selected business fields, while keeping Apify run metadata and input configuration alongside the export for auditability.

### Data Quality, Guarantees, And Handling

- **Structured records:** results are normalized into predictable JSON objects for downstream use.
- **Field preservation:** meaningful schema-supported listing and property values are retained in stable public fields or grouped objects; optional source values can still be absent for a specific record.
- **Best-effort extraction:** fields may vary by region, availability, account visibility, listing type, UI experiments or source-side changes.
- **Optional fields:** null-check optional values in downstream code, models and dashboards.
- **Deduplication:** use `source_context.source_id + record_id`, or `record_id` in a Zoopla-only dataset.
- **Freshness:** results reflect publicly available information at run time.
- **Repeated runs:** use the recommended idempotency key when syncing into warehouses, CRMs, search indexes, vector stores or monitoring systems.
- **Schema awareness:** rely on documented fields and handle newly missing optional values gracefully.
- **Run receipts:** use the summary and map artifacts to audit counts, coverage state, skipped outcomes, enrichment, map readiness and export readiness; they do not replace listing rows.

### Tips For Best Results

- Start with a small `limit` to validate the record shape before scaling up.
- Use one city, postcode, neighborhood, property type or price segment per run for cleaner comparisons.
- Leave optional filters empty when the goal is broad discovery.
- Add filters gradually so their effect on the matching result set is easy to understand.
- Use `enrich_data` only when richer fields justify the additional run time.
- Keep `maximize_coverage` for high-volume searches where deeper matching retrieval matters and the limit is at least 1,100.
- Use the stable idempotency key when retaining records across recurring runs.
- Review `RUN-SUMMARY` and `results-map` before importing a changed or expanded configuration into a production workflow.

### How to Run on Apify

1. Open the Actor in Apify Console.
2. Configure a location and supported search filters, or add individual listing-detail URLs.
3. Set the maximum number of listings to save.
4. Click **Start** and wait for the run to finish.
5. Open the dataset, inspect the first records and review the run summary and map.
6. Download results in JSON, CSV, Excel or another Apify-supported format.

### Agentic And API-First Usage

The actor can serve as a structured public property-data acquisition step inside larger automated workflows. Its documented input schema, stable listing identity, nested output contract and run receipts let workflow builders separate collection from downstream analysis and action.

#### Agent workflow pattern

1. Generate or select a scoped input from the supported parameters.
2. Run the actor manually, on a schedule or through Apify platform automation.
3. Wait for completion and read the dataset records.
4. Validate records against the Field Reference.
5. Read the summary or map artifact to verify counts, coverage state, stop reason, skipped outcomes, coordinates and export readiness.
6. Upsert records into the destination using `source_context.source_id + record_id`.
7. Trigger market analysis, enrichment, alerts, BI refreshes, search indexing, lead review or human verification.

For agentic use, keep prompts grounded in documented inputs and start with small validation runs. Give downstream AI steps the Field Reference and one representative record rather than asking them to infer the schema. Treat optional fields as nullable, and store run ID, input configuration and export metadata outside the listing record for audit trails. When context is limited for Claude, Codex, an internal copilot or a property workflow agent, provide the input schema, idempotency key, relevant field groups, run summary and one output example.

### Scheduling & Automation

#### Scheduling

**Automated Data Collection**

Schedule validated inputs to maintain recurring public listing snapshots for monitoring and reporting.

1. Navigate to **Schedules** in Apify Console.
2. Create a daily, weekly or custom-cron schedule.
3. Configure and save the input parameters.
4. Enable notifications for run completion.
5. Add webhooks when another system should process completed runs.

#### Integration Options

- **BI dashboards:** monitor asking prices, property mix, listing status, geography and coordinate coverage over time.
- **Data warehouses and ETL:** load nested JSON into historical listing tables and curated analytical models.
- **CRM enrichment:** attach public listing, agency, property and available phone attributes to internal records.
- **Webhooks and alerts:** trigger validation, ingestion or stakeholder notifications after a completed run.
- **Google Sheets or Airtable:** review smaller exports, annotate listings and share scoped research with operational teams.
- **Search and vector indexes:** support listing discovery, retrieval workflows and grounded agent context.
- **MCP connectors:** authorize a compatible connector in Apify and select it in the input to receive a concise run summary plus available dataset, report and map links in the destination tool.

For connector delivery, the actor receives only the selected connector IDs. Apify keeps the destination credentials server-side. Connector delivery is optional and best effort; it does not replace the dataset or run artifacts.

### Export Formats And Downstream Use

- **JSON:** preserves nested objects and arrays for APIs, applications, AI agents and data pipelines.
- **CSV or Excel:** supports spreadsheet review and lightweight analysis; nested values may need deliberate flattening.
- **API access:** enables automated ingestion into internal applications and services.
- **BI and warehouses:** supports reporting, dashboards, historical analysis and monitoring.
- **Search or vector indexes:** supports structured discovery, semantic retrieval and agent context using listing text and metadata.

### Downstream Pipeline Guide

- **Idempotency:** upsert on `source_context.source_id + record_id`; use `record_id` alone only in a source-isolated table.
- **Null handling:** treat every non-required group and nested value as nullable or absent.
- **Type handling:** preserve numbers, booleans, arrays and nested objects in JSON-first destinations.
- **Flattening:** flatten nested groups deliberately for CSV or relational tables and retain the original JSON for full fidelity.
- **Partitioning:** store run date, input segment, geography, deal type and workflow name alongside records for analysis.
- **Change detection:** compare repeated runs by stable key and selected fields such as `pricing.price`, `listing.listing_status`, `listing.available_from` and relevant property attributes.
- **Quality checks:** monitor saved counts, duplicate counts, required IDs, asking-price availability, coordinate fill rate and enrichment status using dataset rows and the run summary.
- **Human review:** route records with missing critical values, unusual prices, changed status or important segments into a review queue.
- **Retention:** choose separate retention periods for raw exports, run receipts and normalized warehouse tables based on the workflow.

### Performance And Coverage Expectations

Recent validation runs provide examples, not guarantees:

| Run type | Example scope | Listings | Duration | Coverage notes |
| --- | --- | ---: | ---: | --- |
| Lightweight buy | South London, limit 3 | 3 | 9.693 seconds | Limit reached; 3 lightweight rows, 3 valid map markers, no skipped or duplicate rows. |
| Detail and contact enriched rent | Birmingham, limit 3 | 3 | 14.347 seconds | Limit reached; 3 detail-enriched and 3 contact-enriched rows, 3 valid map markers, no recorded warnings. |

Execution time varies with filters, result volume, target availability, response size, enrichment depth, coordinate and map artifact creation, and the amount of public information returned per listing. Highly filtered runs can finish sooner, while broad discovery, detail-rich records, contact collection or `maximize_coverage` can take longer. Coverage mode prioritizes deeper retrieval within the selected criteria and can trade speed for a more complete matching collection. The actor does not promise the fastest runtime, complete market coverage or lossless availability of optional source fields.

### Limitations

- Results depend on what Zoopla publicly exposes at run time.
- Optional descriptions, coordinates, media, floor area, EPC, material information, history, agency and contact fields may be absent.
- A requested `limit` is a maximum, not a promise that the source contains that many matching public listings.
- Very broad searches and coverage-aware runs can take longer than focused validation runs.
- Source-side presentation or field changes can affect availability and naming.
- Asking prices, availability, status, descriptions and contact details are point-in-time public signals and should be verified before operational decisions.
- The actor provides structured public listing data, not legal, financial, investment, valuation, appraisal or brokerage advice.

### Troubleshooting

- **No results returned:** check location spelling, deal type, filters, direct URLs and whether Zoopla currently shows matching public listings.
- **Fewer results than expected:** raise `limit` if it is restrictive, remove overly narrow filters or enable `maximize_coverage` for eligible high-volume searches.
- **Some fields are empty:** optional fields depend on what each listing and advertiser publicly provides and whether enrichment is enabled.
- **Duplicate-looking records:** compare `record_id`; similar properties can be separate listings, units or advertiser records.
- **Run takes longer than expected:** lower the limit for validation, disable optional enrichment or split a broad workflow into focused segments.
- **Output changed:** compare records with the current Field Reference and retain a small sample for support.
- **Downstream import failed:** check JSON validity, nullable values, arrays, nested objects and whether the destination expects flattened columns.
- **Connector delivery did not arrive:** confirm that the connector remains authorized and compatible; the dataset and key-value-store artifacts remain the primary outputs.

### FAQ

#### What data does this actor collect?

Public Zoopla sale and rental listing records, including stable listing identity, source context, title, location, asking price, property attributes, listing status, media, agency relationships and optional enrichment.

#### Which search filters are supported?

The actor supports direct individual listing URLs or a location-based query using buy or rent mode, radius, bedroom and bathroom ranges, price, property type, retirement status, features, publication window and keyword, plus documented sale-only and rental-only filters.

#### Why did I receive fewer records than my limit?

`limit` is a maximum. The selected criteria may contain fewer visible public matches, records may become unavailable, or the run may report another stop condition in `RUN-SUMMARY`.

#### What does `maximize_coverage` do?

For limits of at least 1,100, it can collect deeper within the same selected criteria when a broad search reports more matches than are normally visible. It does not relax the filters and can increase run time.

#### Where are the run summary and map?

Open the run's Outputs section or key-value store links for `RUN-SUMMARY`, `RUN-SUMMARY.html` and `results-map`.

#### How should I choose a first-run limit?

Start with 10 or 25 records, verify the output groups and optional-field fill rate, then increase the limit for the validated workflow.

#### Can I schedule recurring runs?

Yes. Save a tested input and configure an Apify schedule for daily, weekly or custom execution.

#### How do I avoid duplicates across runs?

Upsert using `source_context.source_id + record_id`, or `record_id` in a Zoopla-only table. Do not use title, address or result position as the unique key.

#### Can AI agents use the output?

Yes. Give the agent the input schema, relevant field reference, one output example and the run summary, and require it to treat optional fields as nullable.

#### Which export formats are available?

Apify datasets can be consumed as JSON and exported to formats such as CSV and Excel, subject to the standard platform options.

#### Does the actor collect private data or provide official valuations?

It collects publicly available listing information. It does not provide private property records, MLS completeness, ownership verification, appraisal-grade valuations or investment advice.

### Compliance & Ethics

#### Responsible Data Collection

This actor collects publicly available property listing information from Zoopla for legitimate business purposes, including:

- **Real estate** research and public market analysis
- Property inventory monitoring and operational reporting
- Schema-aware enrichment of internal property datasets

Users are responsible for ensuring that their collection, storage and use are lawful and appropriate. This section is informational and not legal advice.

#### Best Practices

- Use collected data in accordance with applicable laws, regulations and Zoopla's terms.
- Respect individual privacy and personal information.
- Use data responsibly and avoid disruptive or excessive collection.
- Do not use this actor for spamming, harassment, discrimination, unlawful housing practices or other harmful purposes.
- Follow relevant data-protection, fair-housing, consumer-protection and sector-specific requirements.
- Review retention, access-control and data-sharing policies before operationalizing the dataset.

### Support

Use the **Issues** tab on the Actor page to ask for help. Include the redacted input, Apify run ID, expected versus actual behavior and, when useful, a small output sample. For export or pipeline issues, also include the downstream destination and format, such as JSON, CSV, Excel, CRM or warehouse ingestion.

# Actor input Schema

## `deal_type` (type: `string`):

Choose Buy for properties listed for sale or Rent for rental listings. This choice sets the search path and determines which sale-only or rental-only filters apply when the actor builds the search.

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

Enter a Zoopla-supported UK location such as South London, Birmingham, SW1A, or West Midlands. Use one focused location per run for cleaner market comparisons, scheduled monitoring, CRM imports, or dashboard refreshes; leave it empty for a broader mode-based search.

## `radius` (type: `string`):

Choose how far beyond the selected location Zoopla should look. A larger radius broadens discovery across nearby areas; choose This area only for tighter neighborhood comparisons and more targeted monitoring.

## `min_bedroom` (type: `string`):

Set the fewest bedrooms a matching property may have. Select Studio or more to include studio listings alongside properties with bedrooms.

## `max_bedroom` (type: `string`):

Set the greatest number of bedrooms a matching property may have. Select Studios only when the search should exclude properties with one or more bedrooms.

## `min_bathroom` (type: `string`):

Set the fewest bathrooms a matching property may have. Pair this with bedroom and property-type filters when building comparable family-home or multi-occupancy datasets.

## `max_bathroom` (type: `string`):

Set the greatest number of bathrooms a matching property may have. Leave empty when bathroom count should not narrow the search.

## `min_price` (type: `integer`):

Enter the lowest listing price in pounds. Buy searches use sale asking prices; Rent searches use Zoopla's monthly rent scale, so use values that match the selected listing mode.

## `max_price` (type: `integer`):

Enter the highest listing price in pounds. Use a focused range for comparable market slices, price monitoring, dashboards, or bounded CRM enrichment; leave empty when no upper price cap is needed.

## `property_type` (type: `array`):

Select the residential categories that should match, such as detached homes, terraced homes, flats, or farms and land. Leave empty to include every property type available for the selected search scope.

## `retirement_home` (type: `string`):

Include retirement homes with other matches, exclude them, or return only retirement-home listings. Leave empty when retirement status should not narrow the dataset.

## `features` (type: `array`):

Select one or more Zoopla-supported features, styles, or conditions that matching listings should contain. Multiple selections make the search more targeted and may substantially reduce the number of results.

## `publication_date` (type: `string`):

Limit results to listings added within the selected period. Use shorter windows for alerts and frequent monitoring, or longer windows for broader market analysis and backfills.

## `keyword` (type: `string`):

Enter optional free text such as balcony, air conditioning, or parking to narrow the Zoopla search. Use precise terms because keyword matching can exclude otherwise relevant listings.

## `rental_house_share` (type: `string`):

For Rent searches, include shared accommodation with other rentals, exclude it, or return only house-share listings. This field does not apply to Buy searches.

## `rental_student_accommodation` (type: `string`):

For Rent searches, include student accommodation with other rentals, exclude it, or return only student listings. This field does not apply to Buy searches.

## `rental_availability` (type: `string`):

For Rent searches, choose how soon a property must be available. Use Available now for immediate-move monitoring, or a longer window for forward planning and relocation workflows.

## `furnishment` (type: `string`):

For Rent searches, return furnished, part-furnished, or unfurnished properties. Leave empty when furnishing should not narrow the rental dataset.

## `include_let_agreed` (type: `boolean`):

Enable this to retain rental listings already marked let or let agreed, which can be useful for market history and monitoring. Keep it disabled when the dataset should focus on currently marketed rentals.

## `sale_new_build_home` (type: `string`):

For Buy searches, include new-build homes with other properties, exclude them, or return only new-build listings. This field does not apply to Rent searches.

## `sale_shared_ownership` (type: `string`):

For Buy searches, include shared-ownership listings, exclude them, or return only shared-ownership properties. Leave empty when ownership scheme should not narrow the dataset.

## `sale_owner_type` (type: `array`):

For Buy searches, select leasehold, freehold, or share of freehold. Multiple selections broaden the accepted ownership types; leave empty to avoid filtering by tenure.

## `sale_property_status` (type: `array`):

For Buy searches, select supported status signals such as chain-free, reduced-price, or under offer and sold STC. Use these filters for targeted alerts, pipeline review, or price-change monitoring.

## `sale_low_deposit_mortgage` (type: `boolean`):

Enable this for Buy searches that should only return listings carrying Zoopla's supported low-deposit mortgage incentives. Keep it disabled when mortgage incentive status should not restrict results.

## `url` (type: `array`):

Paste individual property-detail URLs such as `https://www.zoopla.co.uk/for-sale/details/12345678/`, `https://www.zoopla.co.uk/to-rent/details/12345678/`, or `https://www.zoopla.co.uk/new-homes/details/12345678/`. Each valid URL produces at most one listing record.

## `enrich_data` (type: `boolean`):

Keep enabled for detailed ETL, CRM enrichment, research, or AI-assisted review. Disable it for faster, lightweight location searches. Individual URLs always read their detail pages because there is no search-result record to use as a fallback.

## `maximize_coverage` (type: `boolean`):

This option applies when the requested limit is at least 1,100 listings. It preserves the selected deal type and filters while expanding collection for oversized searches; keep it disabled for faster exploratory runs where the first visible matching set is sufficient.

## `limit` (type: `integer`):

Choose the maximum number of property records to save. Leave empty to continue through the listings available to the selected search scope, or start with a small value to confirm the record shape before increasing the run size.

## `mcpConnectors` (type: `array`):

Choose user-authorized connectors to receive a compact run summary after the listing dataset, summary report and map are saved. The delivery includes run totals and available Apify output links, not the full listing dataset. Leave empty to keep all outputs in Apify only.

## Actor input object example

```json
{
  "deal_type": "buy",
  "location": "Birmingham West Midlands",
  "include_let_agreed": false,
  "sale_low_deposit_mortgage": false,
  "enrich_data": true,
  "maximize_coverage": true,
  "limit": 100,
  "mcpConnectors": []
}
```

# Actor output Schema

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

Grouped Zoopla sale or rental listing records saved by this run, including provenance, asking price, location, property attributes, media, agency details and optional enrichment when available.

## `runSummaryJson` (type: `string`):

Machine-readable end-of-run summary with saved totals, search mode, filters, coverage, enrichment, pricing, location, media, agency and warning breakdowns.

## `runSummaryHtml` (type: `string`):

Human-readable end-of-run report with key listing, enrichment, location, asking-price and completion indicators.

## `resultsMap` (type: `string`):

Interactive map of saved listings with valid public coordinates. Runs without usable coordinates still produce a report showing zero mapped listings.

# 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 = {
    "deal_type": "buy",
    "location": "Birmingham West Midlands",
    "limit": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("fatihtahta/zoopla-uk-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 = {
    "deal_type": "buy",
    "location": "Birmingham West Midlands",
    "limit": 100,
}

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

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

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

```

## CLI example

```bash
echo '{
  "deal_type": "buy",
  "location": "Birmingham West Midlands",
  "limit": 100
}' |
apify call fatihtahta/zoopla-uk-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fatihtahta/zoopla-uk-property-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Zoopla Uk Property Scraper with Contacts & Features",
        "description": "Extract structured Zoopla UK sale and rental listings with asking prices, full descriptions, property specs, photos, floor plans, coordinates, agency details and public phone numbers. Built for market research, comps, inventory monitoring, CRM enrichment, BI and AI workflows.",
        "version": "0.0",
        "x-build-id": "k0g8fnUq3xmX61Rq9"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fatihtahta~zoopla-uk-property-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fatihtahta-zoopla-uk-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/fatihtahta~zoopla-uk-property-scraper/runs": {
            "post": {
                "operationId": "runs-sync-fatihtahta-zoopla-uk-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/fatihtahta~zoopla-uk-property-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-fatihtahta-zoopla-uk-property-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "deal_type": {
                        "title": "Choose Listing Mode (buy or rent)",
                        "enum": [
                            "buy",
                            "rent"
                        ],
                        "type": "string",
                        "description": "Choose Buy for properties listed for sale or Rent for rental listings. This choice sets the search path and determines which sale-only or rental-only filters apply when the actor builds the search.",
                        "default": "buy"
                    },
                    "location": {
                        "title": "Set a UK Location (city, postcode, neighborhood, county, or market)",
                        "type": "string",
                        "description": "Enter a Zoopla-supported UK location such as South London, Birmingham, SW1A, or West Midlands. Use one focused location per run for cleaner market comparisons, scheduled monitoring, CRM imports, or dashboard refreshes; leave it empty for a broader mode-based search."
                    },
                    "radius": {
                        "title": "Set the Search Radius Around the Location",
                        "enum": [
                            "0",
                            "0.25",
                            "0.5",
                            "1",
                            "3",
                            "5",
                            "10",
                            "15",
                            "20",
                            "30",
                            "40"
                        ],
                        "type": "string",
                        "description": "Choose how far beyond the selected location Zoopla should look. A larger radius broadens discovery across nearby areas; choose This area only for tighter neighborhood comparisons and more targeted monitoring."
                    },
                    "min_bedroom": {
                        "title": "Set the Minimum Number of Bedrooms",
                        "enum": [
                            "0",
                            "1",
                            "2",
                            "3",
                            "4",
                            "5",
                            "6",
                            "7",
                            "8",
                            "9",
                            "10"
                        ],
                        "type": "string",
                        "description": "Set the fewest bedrooms a matching property may have. Select Studio or more to include studio listings alongside properties with bedrooms."
                    },
                    "max_bedroom": {
                        "title": "Set the Maximum Number of Bedrooms",
                        "enum": [
                            "0",
                            "1",
                            "2",
                            "3",
                            "4",
                            "5",
                            "6",
                            "7",
                            "8",
                            "9",
                            "10"
                        ],
                        "type": "string",
                        "description": "Set the greatest number of bedrooms a matching property may have. Select Studios only when the search should exclude properties with one or more bedrooms."
                    },
                    "min_bathroom": {
                        "title": "Set the Minimum Number of Bathrooms",
                        "enum": [
                            "1",
                            "2",
                            "3",
                            "4",
                            "5",
                            "6",
                            "7",
                            "8",
                            "9",
                            "10"
                        ],
                        "type": "string",
                        "description": "Set the fewest bathrooms a matching property may have. Pair this with bedroom and property-type filters when building comparable family-home or multi-occupancy datasets."
                    },
                    "max_bathroom": {
                        "title": "Set the Maximum Number of Bathrooms",
                        "enum": [
                            "1",
                            "2",
                            "3",
                            "4",
                            "5",
                            "6",
                            "7",
                            "8",
                            "9",
                            "10"
                        ],
                        "type": "string",
                        "description": "Set the greatest number of bathrooms a matching property may have. Leave empty when bathroom count should not narrow the search."
                    },
                    "min_price": {
                        "title": "Set the Minimum Asking Price or Monthly Rent (£)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Enter the lowest listing price in pounds. Buy searches use sale asking prices; Rent searches use Zoopla's monthly rent scale, so use values that match the selected listing mode."
                    },
                    "max_price": {
                        "title": "Set the Maximum Asking Price or Monthly Rent (£)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Enter the highest listing price in pounds. Use a focused range for comparable market slices, price monitoring, dashboards, or bounded CRM enrichment; leave empty when no upper price cap is needed."
                    },
                    "property_type": {
                        "title": "Choose One or More Property Types",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Select the residential categories that should match, such as detached homes, terraced homes, flats, or farms and land. Leave empty to include every property type available for the selected search scope.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "semi-detached",
                                "detached",
                                "terraced",
                                "bungalow",
                                "park-home",
                                "flats",
                                "farms-land"
                            ],
                            "enumTitles": [
                                "Semi-detached",
                                "Detached",
                                "Terraced",
                                "Bungalow",
                                "Park home",
                                "Flats",
                                "Farms and land"
                            ]
                        }
                    },
                    "retirement_home": {
                        "title": "Choose How to Handle Retirement Homes",
                        "enum": [
                            "include",
                            "exclude",
                            "only"
                        ],
                        "type": "string",
                        "description": "Include retirement homes with other matches, exclude them, or return only retirement-home listings. Leave empty when retirement status should not narrow the dataset."
                    },
                    "features": {
                        "title": "Require Specific Property Features",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Select one or more Zoopla-supported features, styles, or conditions that matching listings should contain. Multiple selections make the search more targeted and may substantially reduce the number of results.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "period-property",
                                "cottage",
                                "modern",
                                "ev-charging",
                                "utility-room",
                                "basement",
                                "conservatory",
                                "home-office",
                                "en-suite",
                                "bathtub",
                                "patio",
                                "kitchen-island",
                                "needs-modernisation"
                            ],
                            "enumTitles": [
                                "Period property",
                                "Cottage",
                                "Modern",
                                "EV charging",
                                "Utility room",
                                "Basement",
                                "Conservatory",
                                "Home office",
                                "En-suite",
                                "Bathtub",
                                "Patio",
                                "Kitchen island",
                                "Needs modernisation"
                            ]
                        }
                    },
                    "publication_date": {
                        "title": "Filter by When the Listing Was Added",
                        "enum": [
                            "24-hours",
                            "3-days",
                            "7-days",
                            "14-days",
                            "30-days"
                        ],
                        "type": "string",
                        "description": "Limit results to listings added within the selected period. Use shorter windows for alerts and frequent monitoring, or longer windows for broader market analysis and backfills."
                    },
                    "keyword": {
                        "title": "Add a Listing Keyword",
                        "type": "string",
                        "description": "Enter optional free text such as balcony, air conditioning, or parking to narrow the Zoopla search. Use precise terms because keyword matching can exclude otherwise relevant listings."
                    },
                    "rental_house_share": {
                        "title": "Choose How to Handle Rental House Shares",
                        "enum": [
                            "include",
                            "exclude",
                            "only"
                        ],
                        "type": "string",
                        "description": "For Rent searches, include shared accommodation with other rentals, exclude it, or return only house-share listings. This field does not apply to Buy searches."
                    },
                    "rental_student_accommodation": {
                        "title": "Choose How to Handle Student Accommodation",
                        "enum": [
                            "include",
                            "exclude",
                            "only"
                        ],
                        "type": "string",
                        "description": "For Rent searches, include student accommodation with other rentals, exclude it, or return only student listings. This field does not apply to Buy searches."
                    },
                    "rental_availability": {
                        "title": "Filter Rentals by Availability Window",
                        "enum": [
                            "now",
                            "one-month",
                            "three-months",
                            "six-months",
                            "twelve-months"
                        ],
                        "type": "string",
                        "description": "For Rent searches, choose how soon a property must be available. Use Available now for immediate-move monitoring, or a longer window for forward planning and relocation workflows."
                    },
                    "furnishment": {
                        "title": "Choose the Required Furnishing State",
                        "enum": [
                            "furnished",
                            "part-furnished",
                            "unfurnished"
                        ],
                        "type": "string",
                        "description": "For Rent searches, return furnished, part-furnished, or unfurnished properties. Leave empty when furnishing should not narrow the rental dataset."
                    },
                    "include_let_agreed": {
                        "title": "Include Rentals Marked Let Agreed",
                        "type": "boolean",
                        "description": "Enable this to retain rental listings already marked let or let agreed, which can be useful for market history and monitoring. Keep it disabled when the dataset should focus on currently marketed rentals.",
                        "default": false
                    },
                    "sale_new_build_home": {
                        "title": "Choose How to Handle New-Build Homes",
                        "enum": [
                            "include",
                            "exclude",
                            "only"
                        ],
                        "type": "string",
                        "description": "For Buy searches, include new-build homes with other properties, exclude them, or return only new-build listings. This field does not apply to Rent searches."
                    },
                    "sale_shared_ownership": {
                        "title": "Choose How to Handle Shared-Ownership Listings",
                        "enum": [
                            "include",
                            "exclude",
                            "only"
                        ],
                        "type": "string",
                        "description": "For Buy searches, include shared-ownership listings, exclude them, or return only shared-ownership properties. Leave empty when ownership scheme should not narrow the dataset."
                    },
                    "sale_owner_type": {
                        "title": "Choose Accepted Ownership or Tenure Types",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "For Buy searches, select leasehold, freehold, or share of freehold. Multiple selections broaden the accepted ownership types; leave empty to avoid filtering by tenure.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "leasehold",
                                "freehold",
                                "share-of-freehold"
                            ],
                            "enumTitles": [
                                "Leasehold",
                                "Freehold",
                                "Share of freehold"
                            ]
                        }
                    },
                    "sale_property_status": {
                        "title": "Filter Sale Listings by Property Status",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "For Buy searches, select supported status signals such as chain-free, reduced-price, or under offer and sold STC. Use these filters for targeted alerts, pipeline review, or price-change monitoring.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "chain-free",
                                "reduced-price",
                                "under-offer-or-sold-stc"
                            ],
                            "enumTitles": [
                                "Chain-free",
                                "Reduced price",
                                "Under offer or sold STC"
                            ]
                        }
                    },
                    "sale_low_deposit_mortgage": {
                        "title": "Require Supported Low-Deposit Mortgage Offers",
                        "type": "boolean",
                        "description": "Enable this for Buy searches that should only return listings carrying Zoopla's supported low-deposit mortgage incentives. Keep it disabled when mortgage incentive status should not restrict results.",
                        "default": false
                    },
                    "url": {
                        "title": "Add Zoopla Listing URLs (one per line)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Paste individual property-detail URLs such as `https://www.zoopla.co.uk/for-sale/details/12345678/`, `https://www.zoopla.co.uk/to-rent/details/12345678/`, or `https://www.zoopla.co.uk/new-homes/details/12345678/`. Each valid URL produces at most one listing record.",
                        "items": {
                            "type": "string",
                            "pattern": "^https://(www\\.)?zoopla\\.co\\.uk/(for-sale|to-rent|new-homes)/details/[0-9]+/?(?:[?#].*)?$"
                        }
                    },
                    "enrich_data": {
                        "title": "Collect Richer Details from Individual Listings",
                        "type": "boolean",
                        "description": "Keep enabled for detailed ETL, CRM enrichment, research, or AI-assisted review. Disable it for faster, lightweight location searches. Individual URLs always read their detail pages because there is no search-result record to use as a fallback.",
                        "default": true
                    },
                    "maximize_coverage": {
                        "title": "Collect More Matching Listings Beyond the Visible Search Cap",
                        "type": "boolean",
                        "description": "This option applies when the requested limit is at least 1,100 listings. It preserves the selected deal type and filters while expanding collection for oversized searches; keep it disabled for faster exploratory runs where the first visible matching set is sufficient.",
                        "default": true
                    },
                    "limit": {
                        "title": "Set the Maximum Number of Listings to Save",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Choose the maximum number of property records to save. Leave empty to continue through the listings available to the selected search scope, or start with a small value to confirm the record shape before increasing the run size."
                    },
                    "mcpConnectors": {
                        "title": "Deliver the Run Summary to MCP Connectors",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Choose user-authorized connectors to receive a compact run summary after the listing dataset, summary report and map are saved. The delivery includes run totals and available Apify output links, not the full listing dataset. Leave empty to keep all outputs in Apify only.",
                        "default": []
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
