# Rightmove Scraper - UK Property API, Rent, Sale & New Homes (`epctex/rightmove-scraper`) Actor

Scrape Rightmove rent, sale, new homes and student listings by location or URL. At $0.40 per 1,000 properties and 51 fields per record, it fits agents, investors and PropTech teams. Filters in pasted URLs are honoured.

- **URL**: https://apify.com/epctex/rightmove-scraper.md
- **Developed by:** [epctex](https://apify.com/epctex) (community)
- **Categories:** Real estate
- **Features:** Limited permissions
- **Stats:** 222 total users, 33 monthly users, 99.2% runs succeeded, 16 bookmarks
- **User rating**: 4.98 out of 5 stars

## Pricing

from $0.30 / 1,000 dataset items

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Rightmove Scraper

Rightmove Scraper is an Apify actor that extracts Rightmove property listings and full property records from a `search` location term or `startUrls`. Full property records cost **$0.0004 each, or $0.40 per 1,000 properties**, plus **$0.005 per search**.

The Rightmove Scraper runs 3 request flows, accepts 21 input fields, returns 51 top-level fields per full property record, and bills through 3 charge events. A 1,000-property search with full details costs **$0.3978 all-in**. Every price below is a per-event charge, with no subscription and no monthly minimum on paid plans.

### What Does the Rightmove Scraper Extract?

The Rightmove Scraper extracts Rightmove data from 5 sources: properties to rent, properties for sale, new homes, student accommodation, and individual property pages. Location search, direct URLs, or both feed the same run.

| Rightmove Source | How the Rightmove Scraper Targets It | What It Covers |
|---|---|---|
| Properties to rent | `channel: rent`, or `/property-to-rent/find...` URLs in `startUrls` | Rental listings, with lettings terms and deposit |
| Properties for sale | `channel: sale`, or `/property-for-sale/find...` URLs in `startUrls` | Sale listings, with tenure and living costs |
| New homes | `channel: new`, or `/new-homes-for-sale/find...` URLs in `startUrls` | New build listings for sale |
| Student accommodation | `channel: student`, or `/student-accommodation/find...` URLs in `startUrls` | Student lettings, including private halls |
| Individual properties | `/properties/{id}` URLs in `startUrls` | One full property record per URL, archived listings included |

The Rightmove Scraper runs 3 request flows: a search with full details (the default), a summaries-only search (`includeDetails: false`), and a direct `/properties/{id}` lookup.

Commercial property (`/commercial-property-to-let/...`) is not one of the 5 sources. The Rightmove Scraper skips those URLs with a warning and charges nothing for them.

### Which Identifiers Does the Rightmove Scraper Accept?

The Rightmove Scraper accepts 2 input identifiers: `startUrls` and `search`. Either one satisfies the run on its own, and one run accepts both at once.

- **`startUrls`** takes an array of Rightmove URLs, such as `https://www.rightmove.co.uk/properties/133723646/` or `https://www.rightmove.co.uk/property-to-rent/find.html?locationIdentifier=REGION%5E87490`. Each URL resolves to a property detail lookup or a search request depending on its path.
- **`search`** takes a location string, such as `London`, a town, a city, a postcode or a region. The Rightmove Scraper resolves it to a Rightmove location key, logs the region it matched, and runs the search on the selected `channel`.

The `channel` field narrows a `search` term to one of 4 values, `rent`, `sale`, `new` or `student`, and defaults to `rent`. A start URL carries its own channel in its path and ignores this field.

### Who Uses the Rightmove Scraper?

Listed below are the 6 roles that run the Rightmove Scraper against UK property data.

- **Property portals and aggregators** keep a current view of listings across `channel` values and locations, reading `addedOn`, `price` and `primaryPrice` on every run.
- **Estate agencies and letting agents** track competitor stock in their postcodes, reading `branch.brandName`, `branch.companyName` and `addedOn`.
- **PropTech and valuation teams** assemble comparable-sales and comparable-rent datasets filtered by `minPrice`, `maxPrice`, `minBeds`, `maxBeds` and `type`, with `maxItems` capping the sample size.
- **Investors and build-to-rent operators** compare rents and sale prices by running `channel: rent` and `channel: sale` on the same `search` location.
- **Mortgage, insurance and lending analysts** collect `tenure.tenureType`, `tenure.yearsRemainingOnLease`, `livingCosts.councilTaxBand`, `livingCosts.annualServiceCharge` and `livingCosts.annualGroundRent`, the fields that bear on affordability and risk.
- **Relocation and search agents** run a `search` with `minBeds`, `maxPrice` and `furnished` matched to a client brief and read `lettings.letAvailableDate`, `lettings.deposit` and `nearestStations`.

Each role pays per search and per property, priced below.

### What Does the Rightmove Scraper Cost?

The Rightmove Scraper charges 3 event types. **List queries cost $0.005 per search, detail queries cost $0.0001 per property, and dataset items cost $0.0003 per item stored.**

| Event Type | Price | What Triggers It |
|---|---|---|
| `list-query` | $0.005 per search | One search, from a `search` term or a search start URL, including all of its pages. Charged only when the search returns results |
| `detail-query` | $0.0001 per property | Each property detail lookup, whether enriching a search result or serving a `/properties/{id}` start URL |
| `dataset-item` | $0.0003 per item stored | Each item saved to the dataset. On paid plans, items from the first page of each search (24 results) are free |

The Rightmove Scraper charges direct-URL detail queries at the start of the run, charges a list query when its search's first page returns results, and charges enrichment detail queries as each lookup is sent.

#### Rightmove Scraper Cost Examples

The table below prices 7 scenarios against the rate card above, all on a paid plan unless stated.

| Scenario | Charge Events | Calculation | Total Cost |
|---|---|---|---|
| 1 search with full details, 24 properties | 1 list query + 24 detail queries | $0.005 + ($0.0001 x 24) | $0.0074 |
| 1 search with full details, 100 properties | 1 list query + 100 detail queries + 76 dataset items | $0.005 + $0.01 + $0.0228 | $0.0378 |
| 1 search with full details, 1,000 properties | 1 list query + 1,000 detail queries + 976 dataset items | $0.005 + $0.10 + $0.2928 | $0.3978 |
| 1 search, summaries only, 100 properties | 1 list query + 76 dataset items | $0.005 + $0.0228 | $0.0278 |
| 1 search, summaries only, 24 properties | 1 list query | $0.005 x 1 | $0.0050 |
| 1 direct property URL | 1 detail query + 1 dataset item | $0.0001 + $0.0003 | $0.0004 |
| Free plan, 1 search with full details, 10 properties | 1 list query + 10 detail queries + 10 dataset items | $0.005 + $0.001 + $0.003 | $0.0090 |

#### Rightmove Scraper Unit Economics

The 5 figures below are derived from the rate card above. The first 3 cover only the detail query and dataset item pair, not the per-search list query or the free first page.

| Metric | Value |
|---|---|
| Cost per property, including its dataset item | $0.0004 |
| Properties per $1 | 2,500 |
| Cost per 1,000 properties | $0.40 |
| Dataset-item value of one free first page | $0.0072 (24 x $0.0003) |
| Ratio between cheapest and most expensive charge event | A list query costs 50 times a detail query |

Three principles control cost on a Rightmove Scraper run:

- **Turn off details when summaries are enough.** `includeDetails: false` drops a 100-property search from $0.0378 to $0.0278.
- **Split one deep search into narrower ones.** Each extra search costs $0.005 when it returns results, and returns a free first page worth $0.0072 in dataset items.
- **Filter at the source.** `minPrice`, `minBeds` and `type` exclude listings before a detail query is paid for them.

Free-plan users run the Rightmove Scraper without a subscription, capped at 5 runs per month and 10 items per run. This cap overrides any `maxItems` value, the first-page dataset-item discount does not apply, and the API is not available on the Free plan.

### How Is the Rightmove Scraper Configured?

The Rightmove Scraper exposes 21 input fields covering targeting, channel selection, detail depth, volume limits, search filters, output customization and delivery to other services.

| Field | Type | Description | Default |
|---|---|---|---|
| `startUrls` | array | Rightmove URLs to scrape: search pages or property detail pages. Filters in the URL are honoured. | not set |
| `search` | string | Location to search for: town, city, postcode or region. | not set |
| `channel` | string | Which listings to search: `rent`, `sale`, `new` or `student`. | `rent` |
| `includeDetails` | boolean | Look up the full detail of every search result. Set to `false` for cheaper listing summaries. | `true` |
| `maxItems` | integer | Maximum number of listing items to output. On paid plans the account's per-run limit also applies; on the Free plan every run stops at 10 items. | all items |
| `endPage` | integer | Last search page to fetch, applied to each search and each start URL individually. | no end page |
| `sort` | string | Sort order: `newest`, `oldest`, `highest` or `lowest`. | not set |
| `minPrice` | integer | Lowest price to include. Monthly for rentals. Minimum `0`. | not set |
| `maxPrice` | integer | Highest price to include. Monthly for rentals. Minimum `0`. | not set |
| `minBeds` | integer | Lowest number of bedrooms, `0` to `10`. `0` selects studios. | not set |
| `maxBeds` | integer | Highest number of bedrooms, `0` to `10`. | not set |
| `maxDaysSinceAdded` | string | Only listings added in the last `"1"`, `"3"`, `"7"` or `"14"` days. | not set |
| `type` | string | Property type: `all`, `detached`, `semi_detached`, `terraced`, `flat`, `bungalow`, `land`, `park_home` or `student_halls`. Valid values differ per `channel`. | not set |
| `furnished` | string | `all`, `furnished`, `part_furnished` or `unfurnished`. Applies to `rent` and `student` only. | not set |
| `includeLetAgreed` | boolean | Include properties already let agreed. Applies to `rent` and `student` only. | not set |
| `includeSSTC` | boolean | Include properties sold subject to contract. Applies to `sale` and `new` only. | not set |
| `customMapFunction` | string | A single synchronous function that takes each output item and returns the object to keep. It runs in a sandbox with plain JavaScript only (no network requests, `require` or `console`) and about 1 second per item. | not set |
| `outputConnector` | string | MCP connector to deliver the results to — pick one (see [How Do You Send Rightmove Scraper Results to Notion, Todoist and More?](#how-do-you-send-rightmove-scraper-results-to-notion-todoist-and-more)). | not set |
| `deliverTarget` | string | Where the connector writes — paste the URL or ID (Notion example: `https://www.notion.so/My-Posts-24f8a1b2c3d44e5f8a9b0c1d2e3f4a5b`); some services need none. | not set |
| `deliverMode` | string | `perPost` (one record per item) or `summary` (one roll-up per run). | `perPost` |
| `deliverMaxItems` | integer | Optional cap on how many records `perPost` delivers (ignored in `summary`). | not set |

A filter set in the input acts as a default. The same filter written into a start URL wins, being the more specific instruction.

### Which Input Rules Does the Rightmove Scraper Enforce?

The Rightmove Scraper enforces 15 usage constraints covering required fields, channel validity, filter scope, URL handling, output functions and volume caps.

| Rule | Applies To | Behavior |
|---|---|---|
| At least one identifier is required | `startUrls`, `search` | The run fails immediately when both are empty |
| `channel` must be a known value | `channel` | The run fails immediately when set outside `rent`, `sale`, `new`, `student` |
| A property type is valid only for its channel | `type` | `student` accepts only `all`, `flat`, `terraced` and `student_halls`; `student_halls` is not valid for `sale` or `new`. An invalid value is dropped with a warning |
| `furnished` and `includeLetAgreed` apply to lettings channels only | `furnished`, `includeLetAgreed` | Ignored with a warning for `sale` and `new` |
| `includeSSTC` applies to sale channels only | `includeSSTC` | Ignored with a warning for `rent` and `student` |
| `sort` must be a known value | `sort` | An unknown value is dropped with a warning |
| Rightmove serves at most 42 pages per search | `endPage`, `startUrls` | Pagination stops at page 42 whatever `endPage` says; a start URL whose `index` offset points past page 42 is rejected with `C012` |
| A start URL must be an http or https Rightmove URL with a supported path | `startUrls` | Any other URL is skipped with a warning |
| `maxDaysSinceAdded` must be a window Rightmove offers | `maxDaysSinceAdded`, `startUrls` | Only `1`, `3`, `7` and `14` are accepted; any other value is dropped with a warning |
| A filter written into a start URL wins over the same input field | `minPrice`, `maxPrice`, `minBeds`, `maxBeds`, `maxDaysSinceAdded`, `type`, `furnished`, `sort`, `includeSSTC`, `includeLetAgreed` | The URL's own value is used; the input field is the fallback |
| `radius` in a start URL is not applied | `startUrls` | Ignored with a warning; the search covers the location itself |
| `customMapFunction` must be a plain synchronous function | `customMapFunction` | A function that fails to parse, is not a function, is async or a generator, uses `new Date`, `Date.now` or `1970` (use `maxDaysSinceAdded` instead), throws, returns a non-object or a Promise, or runs longer than about 1 second on one item is rejected with a warning, and the original items are saved |
| Unknown input keys are reported, not rejected | any field outside the 21 listed above | Logged as a warning; the legacy `start_urls` key is read as `startUrls` |
| The Free plan caps volume regardless of `maxItems` | `maxItems` | Capped at 10 items per run and 5 runs per month; the API is not available on this plan |
| The maximum cost per run must cover the start-of-run query charges | all identifiers | The run exits before any query when the direct-URL detail queries charged at start exceed the limit |

### What Changed When the Rightmove Scraper Replaced Its Legacy Scraping Method?

The Rightmove Scraper now calls the API directly instead of scraping rendered pages. `startUrls`, `maxItems`, `endPage` and `customMapFunction` are unchanged, and the 2 retired fields only log a warning.

| Before | Now | What to Do |
|---|---|---|
| `proxy` | ignored | Delete it. The Rightmove Scraper does not scrape pages |
| `extendOutputFunction` | `customMapFunction` | Rewrite the body. It receives the finished item, not a Cheerio `$` handle |
| Numeric fields returned unrelated values | now correct | See below |
| `url` was the URL you pasted | canonical `https://www.rightmove.co.uk/properties/{id}` | The pasted URL is now in `inputSource` |

The previous version resolved numeric fields a second time, so `beds`, `baths`, `livingCosts.annualServiceCharge`, `lettings.deposit` and every other numeric detail field came back as unrelated values. Remove any workaround built around the old behavior.

The output is a superset of the previous one. The 15 newly available fields are `channel`, `transactionType`, `incode`, `outcode`, `countryCode`, `displayPriceQualifier`, `sharedOwnership`, `ownershipPercentage`, `commercialUseClasses`, `sizes`, `tenure.yearsRemainingOnLease`, `lettings.minimumTermInMonths`, `branch.logo`, `branch.brandName` and `inputSource` on every item.

### How Do You Search Rightmove by Location With the Rightmove Scraper?

The Rightmove Scraper runs a location search in 5 steps: set `search`, pick `channel`, apply filters, set `maxItems`, and start the run. The example below searches Manchester rentals with 2 or more bedrooms at up to 2,000 GBP per month.

```json
{
  "search": "Manchester",
  "channel": "rent",
  "minBeds": 2,
  "maxPrice": 2000,
  "maxItems": 50
}
```

### How Do You Scrape a Rightmove Search URL With the Rightmove Scraper?

The Rightmove Scraper reads the filters encoded in a pasted search URL, such as `locationIdentifier`, `minBedrooms`, `propertyTypes`, `maxDaysSinceAdded` and `index`, so no separate input fields are needed.

```json
{
  "startUrls": [
    "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490&minBedrooms=2&propertyTypes=flat"
  ],
  "maxItems": 100
}
```

### How Do You Scrape Individual Rightmove Properties With the Rightmove Scraper?

The Rightmove Scraper turns a list of `/properties/{id}` URLs into full property records, one detail query per URL, with no list query charged. Each record costs $0.0004 including its dataset item.

```json
{
  "startUrls": [
    "https://www.rightmove.co.uk/properties/133723646/",
    "https://www.rightmove.co.uk/properties/87624684/"
  ]
}
```

### How Do You Get Cheaper Rightmove Listing Summaries With the Rightmove Scraper?

The Rightmove Scraper returns the lighter listing-summary shape when `includeDetails` is set to `false`, with no detail query charged per property. The example below fetches up to 5 pages of Leeds sale listings.

```json
{
  "search": "Leeds",
  "channel": "sale",
  "includeDetails": false,
  "endPage": 5,
  "maxItems": 120
}
```

### How Do You Send Rightmove Scraper Results to Notion, Todoist and More?

Skip the manual exports — the Rightmove Scraper can deliver its results directly into the tools you already work in, through [Apify MCP Connectors](https://apify.com/store/collections/mcp-connectors):

1. Authorize a connector (Notion, Todoist, or any service whose MCP server offers non-destructive write tools) once in [Console → Settings → API & Integrations → MCP connectors](https://console.apify.com/settings/integrations).
2. Pick it from the **Send results to Notion, Todoist, …** dropdown.
3. Fill in where and how to write:
   - **Destination target** — paste the URL or ID (Notion example: `https://www.notion.so/My-Posts-24f8a1b2c3d44e5f8a9b0c1d2e3f4a5b`); share it with your connector first via Notion's **•••  → Connections** menu. For structured columns use a **page** URL (the Actor builds the database for you) or a database that **already has columns** — an empty database only receives titles. (Some services need no target.)
   - **Write mode** — `perPost` writes one record per property; `summary` writes a single roll-up for the run.
   - **Max records to deliver** *(optional)* — cap on how many records `perPost` delivers.

**Notion, structured like a spreadsheet:** for a table of typed columns, point the target at a Notion **page** — the Actor auto-creates a database from the data, one matching, correctly-typed column per field (URL, number, date, text). Pointing at an **existing database** fills the columns it already has (matched by name); an **empty database** receives only the title, and the rest of each record goes to the row body — the connector can't add columns to an existing database without destructive access it never requests. Nested fields are flattened into columns too — a `tenure` object becomes `tenure.tenureType`, `tenure.yearsRemainingOnLease`, … and a list like `features` becomes a comma-joined column — so everything is sortable and filterable in the grid. Fields that don't fit a column go to the row's page body, so nothing is lost.

Your credentials stay yours: the Actor talks to your services exclusively through your own authorized connector and only ever uses non-destructive write tools — it cannot delete or overwrite anything you already have. Delivery is best-effort and runs after the scrape: if a connector is misconfigured or a delivery fails, your run still finishes normally with all results intact — the failure is reported in the run log, never by failing the run. If the run is about to hit its timeout, delivery stops early so the run still succeeds, and the log tells you how many records were delivered.

### Which Fields Does the Rightmove Scraper Output?

The Rightmove Scraper outputs 51 top-level fields per property in the full detail record and 24 top-level fields per property in the listing summary, covering identification, location, pricing, tenure, living costs, lettings terms, media and branch data.

Four of the 51 detail fields are grouped objects with nested fields of their own: `tenure` (3 fields), `livingCosts` (8 fields), `lettings` (5 fields) and `branch` (11 fields), for 27 nested fields. Four further detail fields, `summary`, `displaySize`, `numberOfImages` and `numberOfFloorplans`, are carried over from the search result and are absent when the record comes from a `/properties/{id}` start URL. The listing summary carries a lighter `tenure` (1 field) and `branch` (6 fields).

Every item carries `inputSource`, the URL or search term it came from. The dataset's Overview tab shows 25 of the 51 detail fields as a table.

**Full property detail** (`includeDetails: true`)

```json
{
  "inputSource": "https://www.rightmove.co.uk/properties/133723646/",
  "id": "133723646",
  "url": "https://www.rightmove.co.uk/properties/133723646",
  "transactionType": "RENT",
  "channel": "RES_LET",
  "title": "2 bedroom flat for rent in Milton Road, W7",
  "description": "A beautifully presented two bedroom, two bathroom apartment...",
  "latitude": 51.510261,
  "longitude": -0.324018,
  "address": "Milton Road, W7",
  "incode": "1LQ",
  "outcode": "W7",
  "country": "England",
  "countryCode": "GB",
  "propertyType": "flat",
  "propertySubType": "Flat",
  "isBusinessForSale": false,
  "isCommercial": false,
  "isRetirement": false,
  "hasOnlineViewing": false,
  "price": 1850,
  "primaryPrice": "£1,850 pcm",
  "secondaryPrice": "£427 pw",
  "beds": 2,
  "baths": 2,
  "sizes": [],
  "tags": [],
  "features": ["Two double bedrooms", "Two bathrooms", "Private balcony"],
  "tenure": { "tenureType": null, "yearsRemainingOnLease": null, "message": null },
  "livingCosts": {
    "councilTaxExempt": false,
    "councilTaxIncluded": false,
    "councilTaxBand": "C",
    "annualServiceCharge": null,
    "domesticRates": null
  },
  "lettings": {
    "letAvailableDate": "Ask agent",
    "deposit": 2134,
    "minimumTermInMonths": null,
    "letType": "Long term",
    "furnishType": "Unfurnished"
  },
  "furnishedType": "Unfurnished",
  "addedOn": "17/04/2023",
  "images": ["https://media.rightmove.co.uk/..."],
  "floorplans": ["https://media.rightmove.co.uk/..."],
  "brochures": [],
  "nearestStations": [{ "name": "Hanwell", "unit": "miles", "distance": 0.4 }],
  "nearestAirports": [],
  "branch": {
    "branchId": 12997,
    "branchName": "Northfields Avenue",
    "displayName": "Gibbs Gillespie, Northfields Avenue",
    "brandName": "Gibbs Gillespie",
    "companyName": "Leaders and Romans Group",
    "companyType": "corporate",
    "logo": "https://media.rightmove.co.uk/...",
    "phone": "020 3889 6402"
  }
}
```

**Listing summary** (`includeDetails: false`)

```json
{
  "inputSource": "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490",
  "id": "92770581",
  "url": "https://www.rightmove.co.uk/properties/92770581",
  "image": "https://media.rightmove.co.uk/...",
  "address": "25 Cuba, Canary Wharf, London, E14",
  "summary": "A stunning two bedroom apartment with river views...",
  "latitude": 51.505,
  "longitude": -0.0195,
  "beds": 2,
  "baths": 2,
  "propertySubType": "Apartment",
  "price": 885000,
  "primaryPrice": "£885,000",
  "numberOfImages": 12,
  "numberOfFloorplans": 1,
  "tenure": { "tenureType": "LEASEHOLD" },
  "branch": {
    "branchId": 245781,
    "branchName": "Canary Wharf",
    "brandName": "JOHNS&CO"
  }
}
```

### Which Errors Does the Rightmove Scraper Report?

The Rightmove Scraper reports 15 error codes. **12 of the 15 codes are non-terminal**, logging the failure and letting the run continue on other sources. 3 codes terminate the run: `C098`, `C099` and `C100`.

The 12 non-terminal codes split into 5 recovery behaviors:

- **3 codes** (`C001`, `C002`, `C008`) skip only the current property.
- **5 codes** (`C003`, `C004`, `C005`, `C006`, `C012`) stop only the current search or start URL.
- **2 codes** (`C013`, `C014`) drop only the failed dataset write or the failed search page or property.
- **1 code** (`C007`) is informational: the source returned zero results.
- **1 code** (`C019`) writes an error item to the dataset and retries the request after a 1 second delay.

| Code | Trigger | Behavior |
|---|---|---|
| `C001` | The detail request for a property id fails | Skips that property; the run continues |
| `C002` | The detail request answers but carries no property | Skips that property; saves the search summary instead when one exists |
| `C003` | The search request for a start URL or `search` term fails | Stops that source's pagination |
| `C004` | The search response has no `results` array | Stops that source's pagination |
| `C005` | The location lookup for a `search` term fails | Stops that search |
| `C006` | No Rightmove location matches the `search` term | Stops that search |
| `C007` | A search's first page returns zero results | Logged; no items for that source |
| `C008` | No property exists for a given id | Skips that property; the detail query is still charged |
| `C012` | A requested page exceeds Rightmove's 42-page limit | Stops that source's pagination; earlier pages are kept |
| `C013` | Writing items to the dataset fails, or times out again after 2 retries (only timeouts are retried) | The write is not confirmed, so those items may be missing from the dataset; the run continues |
| `C014` | An unexpected error escapes while processing a search page or property | Skips that page or property; the run continues |
| `C019` | The account's rate limit is exceeded | Writes an error item with `code: "C019"` to the dataset, waits 1 second, then retries |
| `C098` | An unhandled promise rejection occurs anywhere in the run | Terminates the run |
| `C099` | An uncaught exception occurs anywhere in the run | Terminates the run |
| `C100` | The run fails to initialize | Terminates the run before any query executes |

### Which Rightmove Scraper Questions Come Up Most Often?

#### Can the Rightmove Scraper run a location search and direct URLs in one job?

Yes. `search` and `startUrls` are accepted together in a single Rightmove Scraper run, and at least one of the two is required.

#### Why does the Rightmove Scraper return fewer results than Rightmove reports?

Rightmove serves at most 42 pages of 24 results, 1,008 listings, per search regardless of how many matches it reports. Covering a larger area takes 2 or more narrower searches, each capped at 1,008 listings.

#### Is there a free way to test the Rightmove Scraper?

Yes. The Free plan runs the Rightmove Scraper without a subscription, limited to 5 runs per month and 10 items per run, with no API access.

#### What happens when the Rightmove Scraper looks up a property that no longer exists?

The Rightmove Scraper logs `C008` and writes no item, and the detail query is still charged. An archived listing still has a full record on Rightmove, so the Rightmove Scraper returns it complete.

#### Does the Rightmove Scraper support commercial property?

No. The Rightmove Scraper skips `/commercial-property-to-let/` URLs with a warning and charges nothing for them.

#### Does a Rightmove Scraper sale search ever return something other than a full property?

Yes. Rightmove mixes commercial listings into some residential sale results, and the Rightmove Scraper saves those from the search data in the listing-summary shape, with no detail query charged.

#### When does the Rightmove Scraper charge for queries?

The Rightmove Scraper charges direct-URL detail queries at the start of the run, a list query when its search's first page returns results, and enrichment detail queries as each lookup is sent.

### Where Do You Get Rightmove Scraper Support?

Rightmove Scraper support runs through epctex.com: the site lists the full product range, its chat box handles custom integrations, and the team is reachable at business@epctex.com.

# Actor input Schema

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

URLs to start with. They can be property detail pages or search pages for rent, sale, new homes and student accommodation. Filters in the URL are honoured. Commercial property is not supported.

## `search` (type: `string`):

A location to search for, such as a town, city, postcode or region. Resolved to a Rightmove location internally. Used together with the channel below.

## `channel` (type: `string`):

Which listings to search. Start URLs carry their own channel and ignore this field.

## `maxItems` (type: `integer`):

Maximum number of listing items that you want as output. Default is all

## `endPage` (type: `integer`):

The page number that you want to end with. By default there is no end page. This applies to all search requests and startUrls individually. Rightmove serves at most 42 pages of 24 results per search.

## `includeDetails` (type: `boolean`):

Look up the full detail of every search result. Turn this off to get the lighter listing summary instead - much cheaper, but each item carries only a handful of fields.

## `sort` (type: `string`):

Sort order for search results.

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

Lowest price to include. Monthly for rentals.

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

Highest price to include. Monthly for rentals.

## `minBeds` (type: `integer`):

Lowest number of bedrooms. Use 0 for studios.

## `maxBeds` (type: `integer`):

Highest number of bedrooms.

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

Limit results to this property type. Student accommodation only accepts flat, terraced and student halls; land and park homes are sale and rent only.

## `furnished` (type: `string`):

Only return lettings with this furnishing. Ignored for sale and new home searches.

## `maxDaysSinceAdded` (type: `string`):

Only return listings added to Rightmove within this window. Leave empty for listings added at any time.

## `includeLetAgreed` (type: `boolean`):

Include properties that are already let agreed. Ignored for sale and new home searches.

## `includeSSTC` (type: `boolean`):

Include properties that are sold subject to contract. Ignored for rent and student searches.

## `customMapFunction` (type: `string`):

Function that takes each of the resulting objects as an argument and returns the object you want to keep. Must be a single synchronous function, e.g. (object) => { return {...object} }. It runs in a sandbox with plain JavaScript only (no network or require) and about 1 second per item. Date operations are rejected - use the maxDaysSinceAdded filter instead. Leave empty if you do not need to transform the output - an unusable function is ignored and the original items are saved instead.

## `outputConnector` (type: `string`):

Pick an MCP connector you authorized in Console → Settings → API & Integrations → MCP connectors (e.g. Notion, Todoist — any service whose MCP server offers non-destructive write tools works best-effort). The scraped results are written through your own connector — the Actor never sees your third-party credentials. Only non-destructive write tools are used; it can never delete or overwrite your existing data.

## `deliverTarget` (type: `string`):

Where to write into the connector — paste the URL or ID. Notion example: https://www.notion.so/My-Posts-24f8a1b2c3d44e5f8a9b0c1d2e3f4a5b. Leave empty for services that need no target (e.g. Todoist Inbox, Slack). For Notion, share the page or database with your connector first (Notion's ••• → Connections menu), and point at a PAGE for structured columns (the Actor builds the database for you) — an empty database receives only the title (the rest of each record goes to the row's body).

## `deliverMode` (type: `string`):

perPost writes one record per scraped item; summary writes a single roll-up for the run.

## `deliverMaxItems` (type: `integer`):

Cap on how many records perPost mode writes to the connector; ignored in summary mode. Leave empty to deliver everything scraped.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.rightmove.co.uk/properties/133723646/",
    "https://www.rightmove.co.uk/property-to-rent/find.html?locationIdentifier=REGION%5E87490",
    "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490"
  ],
  "search": "London",
  "channel": "rent",
  "maxItems": 20,
  "endPage": 1,
  "includeDetails": true,
  "customMapFunction": "(object) => { return {...object} }",
  "deliverMode": "perPost"
}
```

# Actor output Schema

## `overview` (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 = {
    "startUrls": [
        "https://www.rightmove.co.uk/properties/133723646/",
        "https://www.rightmove.co.uk/property-to-rent/find.html?locationIdentifier=REGION%5E87490",
        "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490"
    ],
    "search": "London",
    "maxItems": 20,
    "endPage": 1,
    "customMapFunction": (object) => { return {...object} }
};

// Run the Actor and wait for it to finish
const run = await client.actor("epctex/rightmove-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": [
        "https://www.rightmove.co.uk/properties/133723646/",
        "https://www.rightmove.co.uk/property-to-rent/find.html?locationIdentifier=REGION%5E87490",
        "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490",
    ],
    "search": "London",
    "maxItems": 20,
    "endPage": 1,
    "customMapFunction": "(object) => { return {...object} }",
}

# Run the Actor and wait for it to finish
run = client.actor("epctex/rightmove-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": [
    "https://www.rightmove.co.uk/properties/133723646/",
    "https://www.rightmove.co.uk/property-to-rent/find.html?locationIdentifier=REGION%5E87490",
    "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490"
  ],
  "search": "London",
  "maxItems": 20,
  "endPage": 1,
  "customMapFunction": "(object) => { return {...object} }"
}' |
apify call epctex/rightmove-scraper --silent --output-dataset

```

## MCP server setup

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