# Zoopla Commercial Property Scraper — UK Offices, Retail, Land (`studio-amba/zoopla-commercial-scraper`) Actor

Get commercial property listings from Zoopla.co.uk: offices, retail premises, industrial units, land and hospitality, for sale and to rent. Prices with the quoted unit (pcm, pa, POA preserved), floor area, address, coordinates and agent contact details for any UK location.

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

## Pricing

from $20.00 / 1,000 result scrapeds

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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 Commercial Property Scraper

Get commercial property listings from [Zoopla.co.uk](https://www.zoopla.co.uk), one of the UK's largest property portals. Offices, retail premises, industrial units and warehouses, land, and hospitality businesses (pubs, restaurants, hotels), both for sale and to rent, for any UK location.

Each listing comes with the price exactly as quoted (commercial prices are quoted in different units, and many listings are price-on-application), the floor area, full address with coordinates, the marketing agent with phone number, and photos.

### Why scrape Zoopla commercial listings

- **Market research**: track asking prices and rents for offices, retail units or industrial space in a city or region over time.
- **Deal sourcing**: investors and developers get a structured feed of new land plots and commercial buildings the moment they are listed.
- **Lead generation**: every listing includes the commercial agent's branch name and phone number.
- **Relocation and expansion**: compare available office or warehouse space across multiple UK cities in one dataset.
- **Valuation benchmarks**: build comparables sets with quoted prices, floor areas and locations.

### What data you get

| Field | Example | Notes |
|---|---|---|
| `title` | `"Office to let"` | Listing headline |
| `listingId` | `"74000966"` | Zoopla listing ID |
| `listingType` | `"rent"` | `sale` or `rent` |
| `segment` | `"office"` | office, retail, industrial, land, hospitality, other |
| `propertyType` | `"light_industrial"` | Zoopla's own type label |
| `price` | `7188` | Number parsed from the quote, null for price-on-application |
| `priceText` | `"£7,188 pcm"` | The price exactly as quoted on Zoopla |
| `priceUnit` | `"pcm"` | Quote unit as worded; null for plain sale prices |
| `priceQualifier` | `"Guide price"` | Guide price, Offers over, Fixed price, From |
| `annualPrice` | `86250` | Per-annum rent in GBP (rental listings only) |
| `weeklyPriceText` | `"£1658.65 pw"` | Zoopla's per-week equivalent |
| `currency` | `"GBP"` | Always alongside the price |
| `surface` | `2500` | Floor or plot area |
| `surfaceUnit` | `"sq ft"` | |
| `address` | `"129 Deansgate, Manchester M3"` | Display address |
| `postalCode` | `"M3"` | Postcode outcode |
| `latitude` / `longitude` | `53.4797` / `-2.2480` | Coordinates |
| `description` | `"Fully fitted office suite..."` | Card summary |
| `publishedOn` | `"17th Aug 2026"` | Listing date |
| `underOffer` | `false` | |
| `agencyName` | `"Sanderson Weatherall - Manchester"` | Commercial agent branch |
| `agencyPhone` | `"0161 506 9132"` | |
| `imageUrl` / `imageUrls` | CDN URLs | All listing photos |
| `url` | listing detail URL | |
| `source`, `scrapedAt` | | Provenance |

#### A note on commercial prices

Commercial property pricing is not like residential pricing. Rents are quoted per calendar month on Zoopla (with a per-week equivalent), sale prices are plain figures often softened with a qualifier like "Guide price" or "Offers over", and a large share of listings quote no price at all ("Non quoting" on Zoopla, also known as POA). This actor never invents a number: when the source quotes no price, `price` is `null` and `priceText` preserves the exact wording. The `currency` field is always present so the numbers are unambiguous.

### How to scrape Zoopla commercial property data

1. Open the actor and enter a **Location** — any UK place name works: `london`, `manchester`, `leeds`, `bristol`, `glasgow`. Zoopla resolves the location itself, so you don't need to know its exact URL structure.
2. Pick a **Listing Type**: for sale or to rent.
3. Pick a **Property Segment**: offices, retail premises, industrial/warehouses, land, hospitality, or any.
4. Set **Max Results** and run. The actor paginates automatically (25 listings per page).
5. Download the dataset as JSON, CSV, Excel, or feed it into your own system via the API.

Example input — office space to rent in Manchester:

```json
{
    "searchQuery": "manchester",
    "listingType": "to-rent",
    "segment": "office",
    "maxResults": 100
}
```

Example input — land for sale around Leeds:

```json
{
    "searchQuery": "leeds",
    "listingType": "for-sale",
    "segment": "land",
    "maxResults": 50
}
```

You can also paste Zoopla commercial search URLs directly into **Start URLs** (for example `https://www.zoopla.co.uk/to-rent/commercial/offices/manchester/`), which overrides the search fields.

#### Nearby results

When a search has only a handful of exact matches (common for land searches in smaller cities), Zoopla pads the page with listings from nearby areas. These are excluded by default so your dataset matches your search. Turn on **Include nearby results** to get them too — they are marked with `isNearbyResult: true`.

### Example output

```json
{
    "title": "Office to let",
    "listingId": "74000966",
    "listingType": "rent",
    "segment": "office",
    "propertyType": "office",
    "price": 7188,
    "priceText": "£7,188 pcm",
    "priceUnit": "pcm",
    "priceQualifier": null,
    "annualPrice": 86250,
    "weeklyPriceText": "£1658.65 pw",
    "currency": "GBP",
    "surface": 2500,
    "surfaceUnit": "sq ft",
    "address": "Suite 5B, Centurion House, 129 Deansgate, Manchester M3",
    "postalCode": "M3",
    "latitude": 53.479783,
    "longitude": -2.248057,
    "description": "Fully Fitted Office Suite Available To Let",
    "publishedOn": "17th Aug 2026",
    "underOffer": false,
    "agencyName": "Sanderson Weatherall - Manchester",
    "agencyPhone": "0161 506 9132",
    "imageUrl": "https://lid.zoocdn.com/645/430/00c465659f8922260fc0072c51784e8e0b1383fc.jpg",
    "imageUrls": ["https://lid.zoocdn.com/645/430/00c465659f8922260fc0072c51784e8e0b1383fc.jpg"],
    "isNearbyResult": false,
    "url": "https://www.zoopla.co.uk/to-rent/commercial/details/74000966/",
    "source": "zoopla.co.uk",
    "scrapedAt": "2026-08-18T12:00:00.000Z"
}
```

### How much does it cost to scrape Zoopla commercial property

Pricing is per result plus a small run-start fee. On top of that, the run uses Apify platform resources: Zoopla sits behind bot protection, so the actor uses a real browser and residential proxies, which makes a page load heavier than a plain HTTP scraper. One page load returns 25 listings. As a rough guide, expect the platform usage to stay in the range of a few tenths of a cent per result on typical runs.

Note that a run's usage cost only settles after the run reports SUCCEEDED — reading the cost mid-run shows a number far below the final one.

### Tips

- One browser page load returns 25 listings, so `maxResults` values that are multiples of 25 are the most efficient.
- Broad locations work: `"west yorkshire"`, `"greater manchester"` and `"scotland"` resolve just like city names.
- `segment: "any"` returns every commercial listing for the location, with the `segment` field telling you what each one is.
- Land searches in smaller towns often return few exact results — that is the market, not a scraper problem. Check `isNearbyResult` and the nearby-results option if you want wider coverage.
- Keep the default proxy settings (residential, country GB). Zoopla's bot protection blocks datacenter traffic.

### Limitations

- The actor scrapes search-result data, which covers everything in the output table above. It does not visit each listing's detail page, so long-form descriptions and floorplan documents are not included.
- Zoopla quotes commercial rents per calendar month. Where an agent quotes per sq ft per annum, Zoopla has already converted it; the original per-sq-ft figure only appears in the listing's long description.
- Listing availability changes constantly; a listing present in one run can be gone the next.

### Legality

This actor scrapes publicly available listing data only. It collects no personal data beyond the business contact details agents publish with their listings. You are responsible for using the data in compliance with Zoopla's terms of service and applicable law.

### Support

Found an issue or missing a field you need? Open an issue on the actor's Issues tab and it will be looked at quickly.

# Actor input Schema

## `searchQuery` (type: `string`):

UK location to search, e.g. 'london', 'manchester', 'leeds', 'birmingham'. Free text — Zoopla resolves it to the right area. Leave empty to search London.

## `listingType` (type: `string`):

Commercial property for sale or to rent.

## `segment` (type: `string`):

Commercial property type to filter on. 'Any' returns every commercial listing for the location.

## `startUrls` (type: `array`):

Zoopla commercial search-result URLs to scrape directly (e.g. https://www.zoopla.co.uk/to-rent/commercial/offices/manchester/). Overrides Location, Listing Type and Segment when provided. Maximum 20 URLs.

## `includeNearbyResults` (type: `boolean`):

OFF by default. When a search has few exact matches, Zoopla also shows listings from nearby areas. Turn this on to include those extra listings (marked with isNearbyResult=true in the output).

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

Maximum number of listings to return. Zoopla serves 25 listings per page; each page is one browser request.

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

Zoopla is Cloudflare-protected — residential proxies with country GB are required (see docs/site-recon/zoopla-commercial.md). Keep the default unless you know what you are doing.

## Actor input object example

```json
{
  "searchQuery": "london",
  "listingType": "for-sale",
  "segment": "any",
  "includeNearbyResults": false,
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "searchQuery": "london",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "GB"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/zoopla-commercial-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 = {
    "searchQuery": "london",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB",
    },
}

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

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

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

```

## CLI example

```bash
echo '{
  "searchQuery": "london",
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}' |
apify call studio-amba/zoopla-commercial-scraper --silent --output-dataset

```

## MCP server setup

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

```

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

## OpenAPI specification

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