# OnTheMarket Scraper — Listings & Agent Contacts (`muhammadafzal/onthemarket-scraper`) Actor

Scrape public OnTheMarket UK sale, rental, new-home, and auction listings for research, comparables, monitoring, and agent leads. Returns one stable record per property with price, address, beds, coordinates, photos, EPC, broadband, and agent contacts. Not for private data. $0.003/listing.

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

## Pricing

from $3.00 / 1,000 property listings

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## OnTheMarket Scraper — Listings & Agent Contacts

**OnTheMarket Scraper** extracts public UK property listings from OnTheMarket search, category, and detail pages. It returns stable JSON records with prices, addresses, property types, bedrooms, bathrooms, coordinates, photos, features, tenure, EPC ratings, broadband speeds, nearby schools and stations, and estate-agent contact details. Use it for property-market research, inventory monitoring, comparable listings, relocation analysis, and public agent lead generation.

The Actor accepts for-sale, to-rent, new-home, and auction URLs. Search pages are paginated automatically, duplicate listing IDs are removed across all inputs, and `maxResults` is enforced as an output and billing cap. Detail enrichment is enabled by default. Each saved property costs **$0.003**, plus the documented Actor start event.

Do not use this Actor for Rightmove, Zoopla, OnTheMarket sold prices, private account data, saved searches, or property alerts. Those are outside its public listing scope.

### What data can I extract with OnTheMarket Scraper?

Each dataset item represents one unique property listing. Optional values remain present as explicit `null` values or empty arrays, which keeps exports and AI-agent integrations predictable.

| Field group | Included data |
|---|---|
| Identity | Listing ID, canonical listing URL, source search URL, listing status |
| Property | Title, address, postcode, type, beds, baths, tenure, features, description |
| Price | Displayed price, numeric GBP price, qualifier, rental frequency |
| Location | Latitude, longitude, nearby stations, nearby schools |
| Property signals | New home, student, commercial, auction, featured, exclusive, recently added |
| Enrichment | EPC rating, broadband download/upload speed, photos, floorplans, virtual tours |
| Agent | Branch name, phone, OnTheMarket profile, external website, branch address |
| Provenance | Scrape timestamp, response format, warnings |

`responseFormat: "concise"` keeps records compact for MCP clients and large exports. `responseFormat: "detailed"` adds a capped description, more photos, floorplans, virtual tours, nearby schools and stations, and the full public agent address. Both modes use the same keys.

### Use cases for OnTheMarket property data

- Track newly listed or reduced properties in selected towns, postcodes, or neighbourhoods.
- Build current for-sale and rental inventory datasets for UK housing analysis.
- Compare asking prices, property types, bedroom counts, tenure, and listing recency.
- Collect public estate-agent branch contacts for compliant business-development research.
- Monitor new homes, shared-ownership inventory, retirement properties, or auction stock.
- Feed normalized listing data into spreadsheets, databases, BI tools, valuation models, or AI agents.
- Schedule repeated runs and compare listing IDs or statuses in your downstream database.

For broad locations, use several narrow postcode or price-filtered search URLs. OnTheMarket can limit the depth exposed by one broad search, so partitioning London or another large area produces more complete coverage than repeatedly paging one very broad result set.

### How much will scraping OnTheMarket cost?

OnTheMarket Scraper uses predictable pay-per-event pricing.

| Event | Price |
|---|---:|
| Actor start | $0.00005 per run, scaled according to the Apify event definition |
| `property-listing` | $0.003 per unique property saved |

Worked examples for result-event charges:

- 1 property: about **$0.00305** including the base start event.
- 100 properties: about **$0.30005**.
- 1,000 properties: about **$3.00005**.
- 10,000 properties: about **$30.00005**.

The Actor prints the maximum result-event cost before scraping and the actual billed result events at the end. `maxResults`, `ACTOR_MAX_PAID_DATASET_ITEMS`, and `ACTOR_MAX_TOTAL_CHARGE_USD` are enforced before another record is produced. Apify platform compute, proxy, storage, and transfer charges depend on the caller's Apify plan and selected billing option.

### How to use OnTheMarket Scraper

1. Open OnTheMarket and configure the exact property search you need.
2. Copy the resulting search URL, category URL, or individual `/details/{id}/` URL.
3. Add one or more URLs to `startUrls`.
4. Set `maxResults` to the largest number of unique listings you want to pay for.
5. Keep `enrichDetails` enabled for EPC, broadband, floorplans, nearby places, and richer agent data.
6. Run the Actor and export the dataset as JSON, CSV, Excel, XML, or RSS.

The default input uses a London for-sale search and saves at most 100 listings. It is suitable for Apify's automated health check. For a quick canary, set `maxResults` to 1–10.

### Input

```json
{
  "startUrls": [
    {
      "url": "https://www.onthemarket.com/for-sale/property/london/?page=1"
    },
    {
      "url": "https://www.onthemarket.com/to-rent/property/manchester/"
    },
    {
      "url": "https://www.onthemarket.com/details/18712479/"
    }
  ],
  "maxResults": 250,
  "enrichDetails": true,
  "responseFormat": "concise",
  "maxConcurrency": 5
}
```

| Input | Default | Notes |
|---|---:|---|
| `startUrls` | London for-sale search | Search/category or `/details/{id}/` URLs on `onthemarket.com` |
| `maxResults` | 100 | Overall unique-record and billing cap, from 1 to 10,000 |
| `enrichDetails` | `true` | Opens each property page after search-card discovery |
| `responseFormat` | `concise` | `concise` or `detailed`; output keys stay stable |
| `maxConcurrency` | 5 | Simultaneous HTTP requests, from 1 to 20 |

Unsupported domains and OnTheMarket account, agent-directory, or sold-price URLs are ignored with a warning. If every input is invalid, the run exits successfully with an actionable terminal message instead of recording a runtime failure.

### Output

```json
{
  "listingId": "18712479",
  "listingUrl": "https://www.onthemarket.com/details/18712479/",
  "sourceUrl": "https://www.onthemarket.com/details/18712479/",
  "searchUrl": "https://www.onthemarket.com/for-sale/property/london/?page=1",
  "scrapedAt": "2026-08-11T09:15:00.000Z",
  "responseFormat": "concise",
  "status": "live",
  "transactionType": "sale",
  "title": "5 bedroom semi-detached house for sale",
  "address": "Sandpiper Road, South Croydon, Surrey, CR2",
  "postcode": "CR2 8PQ",
  "price": "£625,000",
  "priceValue": 625000,
  "priceQualifier": "Offers in excess of",
  "priceFrequency": null,
  "currency": "GBP",
  "propertyType": "Semi-detached house",
  "bedrooms": 5,
  "bathrooms": 2,
  "tenure": "Freehold",
  "description": null,
  "features": ["Tenure: Freehold", "Nearest station 1.1mi."],
  "latitude": 51.339126,
  "longitude": -0.053157,
  "isNewHome": false,
  "isStudent": false,
  "isCommercial": false,
  "isAuction": false,
  "isFeatured": true,
  "isExclusive": false,
  "isRecentlyAdded": false,
  "addedOrReduced": "Added > 14 days",
  "epcRating": "C",
  "broadbandMaxDownloadMbps": 1800,
  "broadbandMaxUploadMbps": 220,
  "imageUrl": "https://media.onthemarket.com/properties/18712479/example/image-0.jpg",
  "imageUrls": ["https://media.onthemarket.com/properties/18712479/example/image-0.jpg"],
  "floorplanUrls": [],
  "virtualTourUrls": [],
  "nearbyStations": [],
  "nearbySchools": [],
  "agentName": "Bairstow Eves - Selsdon",
  "agentPhone": "020 4645 2088",
  "agentProfileUrl": "https://www.onthemarket.com/agents/branch/bairstow-eves-selsdon/",
  "agentWebsiteUrl": "https://www.bairstoweves.co.uk/estate-agents/selsdon",
  "agentAddress": null,
  "warnings": []
}
```

The default dataset contains records. The `OUTPUT` key in the default key-value store contains the final status, output and charge counts, settings, failed-request count, warnings, timing, and build number.

### Use OnTheMarket Scraper with the API

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('muhammadafzal/onthemarket-scraper').call({
  startUrls: [{ url: 'https://www.onthemarket.com/to-rent/property/bristol/' }],
  maxResults: 100,
  enrichDetails: true,
  responseFormat: 'concise'
});

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

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient('YOUR_APIFY_TOKEN')
run = client.actor('muhammadafzal/onthemarket-scraper').call(run_input={
    'startUrls': [{'url': 'https://www.onthemarket.com/new-homes/property/birmingham/'}],
    'maxResults': 100,
    'enrichDetails': True,
    'responseFormat': 'detailed',
})

items = list(client.dataset(run['defaultDatasetId']).iterate_items())
print(items)
```

### Use OnTheMarket Scraper through MCP

Connect an MCP client to `https://mcp.apify.com` and add `muhammadafzal/onthemarket-scraper`, or filter the hosted server with:

```text
https://mcp.apify.com?tools=muhammadafzal/onthemarket-scraper
```

Use the concise response format for ordinary agent calls. The declared dataset schema supplies semantic field names, nullable types, examples, and descriptions; `get-actor-output` can page through larger datasets without putting every property into one model context.

### Reliability and limits

OnTheMarket currently provides server-rendered HTML plus a structured page-state payload. The Actor uses lightweight HTTP requests, a session pool, proxy rotation, retries, deduplication, selector-independent state parsing, and a canary request before paid work. If detail enrichment fails after retries but a valid search card was collected, the Actor preserves that partial property record and adds a warning.

Target websites can change without notice. A valid search with no matching properties is treated as a graceful empty result. A run where every request is blocked or exhausted is reported honestly as failed. Large searches should be divided by postcode, price band, bedroom count, or property type because OnTheMarket may expose only a limited result depth for one broad query.

### Related property and research actors

- [Rightmove Market Intelligence](https://apify.com/muhammadafzal/rightmove-market-intelligence)
- [Realtor.ca Scraper](https://apify.com/muhammadafzal/realtor-ca-api-scraper)
- [Realtor Lead Scraper](https://apify.com/muhammadafzal/realtor-lead-scraper)
- [Fast Realtor.com Agents Scraper](https://apify.com/muhammadafzal/fast-realtor-agents-api-scraper)
- [Apartments.com Email Scraper](https://apify.com/muhammadafzal/apartments-com-email-scraper)
- [Idealista Scraper](https://apify.com/muhammadafzal/idealista-scraper)
- [Domain.com.au Scraper](https://apify.com/muhammadafzal/domain-scraper)
- [Craigslist Scraper](https://apify.com/muhammadafzal/craigslist-scraper)
- [Google Maps Scraper](https://apify.com/muhammadafzal/google-maps-scraper)
- [Email Address Validator](https://apify.com/muhammadafzal/email-address-validator)

### FAQ

#### How many results can I scrape with OnTheMarket Scraper?

One run can save up to 10,000 unique listings, subject to the URLs' available inventory, OnTheMarket's search-depth limits, Apify run resources, and your charge cap. Split very broad areas into narrower searches for deeper coverage.

#### Can I integrate OnTheMarket Scraper with other apps?

Yes. Use Apify integrations, webhooks, schedules, Make, Zapier, Google Sheets, cloud storage, or your own database pipeline. Dataset exports are available in JSON, CSV, Excel, XML, and other Apify formats.

#### Can I use OnTheMarket Scraper with the Apify API?

Yes. Start runs through the Apify REST API or official JavaScript and Python clients, then read records from the run's default dataset and the summary from its default key-value store.

#### Can I use OnTheMarket Scraper through an MCP Server?

Yes. The Actor is designed for the hosted Apify MCP server. Its concise mode, stable keys, explicit nulls, output schema, bounded price, and actionable terminal messages are suitable for Claude, ChatGPT, and other MCP clients.

#### Do I need proxies to scrape OnTheMarket?

The deployed Actor uses Apify Proxy by default for stable cloud execution. Local parser tests can run without a proxy. The implementation uses HTTP rather than a browser because the public listing data is currently server-rendered.

#### Is it legal to scrape OnTheMarket data?

Scraping legality depends on your jurisdiction, purpose, volume, contractual obligations, and treatment of personal data. This Actor only extracts information publicly visible without logging in. You are responsible for reviewing OnTheMarket's terms, robots guidance, database rights, copyright, privacy law, and any rules applicable to marketing or automated decision-making. Do not use the data for unlawful discrimination, harassment, spam, or privacy invasion.

#### Your feedback

If a field changes, a page type stops working, or you need a public-data field that is genuinely available on OnTheMarket, open an issue on the Actor's Apify page and include a non-sensitive example URL and run ID.

# Actor input Schema

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

Use this when you have OnTheMarket search, category, or property-detail URLs. Enter one URL per item, for example 'https://www.onthemarket.com/to-rent/property/manchester/'. Defaults to a London for-sale search. This is not for Rightmove, Zoopla, agent-directory, or sold-price URLs.

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

Use this when you need a hard output and billing cap across every input URL. Enter an integer such as 250. Defaults to 100 and accepts 1 through 10000. This limits unique property records, not search pages or retry requests.

## `enrichDetails` (type: `boolean`):

Use this when search results should visit each property page for descriptions, EPC, broadband, floorplans, nearby places, and full agent data. For example, enable it for comparable-property research. Defaults to true and adds one lightweight request per listing. Direct detail URLs are always fully parsed.

## `responseFormat` (type: `string`):

Use this when an AI agent or export needs smaller or richer records. Choose 'concise' for core property and contact fields or 'detailed' for descriptions, more photos, floorplans, schools, and stations. Defaults to 'concise'. This never returns OnTheMarket's raw internal payload.

## `maxConcurrency` (type: `integer`):

Use this when tuning crawl speed for a large batch. Enter an integer such as 5. Defaults to 5 and accepts 1 through 20; lower values are gentler on the target. This controls simultaneous HTTP requests, not the number of Actor runs.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.onthemarket.com/details/18712479/"
    }
  ],
  "maxResults": 250,
  "enrichDetails": true,
  "responseFormat": "detailed",
  "maxConcurrency": 8
}
```

# Actor output Schema

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

Schema-valid property records from the default dataset.

## `summary` (type: `string`):

Run counts, warnings, timing, and charge totals stored under OUTPUT.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.onthemarket.com/for-sale/property/london/?page=1"
        }
    ],
    "maxResults": 100,
    "enrichDetails": true,
    "responseFormat": "concise",
    "maxConcurrency": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/onthemarket-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 = {
    "startUrls": [{ "url": "https://www.onthemarket.com/for-sale/property/london/?page=1" }],
    "maxResults": 100,
    "enrichDetails": True,
    "responseFormat": "concise",
    "maxConcurrency": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/onthemarket-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 '{
  "startUrls": [
    {
      "url": "https://www.onthemarket.com/for-sale/property/london/?page=1"
    }
  ],
  "maxResults": 100,
  "enrichDetails": true,
  "responseFormat": "concise",
  "maxConcurrency": 5
}' |
apify call muhammadafzal/onthemarket-scraper --silent --output-dataset

```

## MCP server setup

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