DEV Community

Cover image for How to Scrape Rightmove London Property Listings Without a Paid API
Tim Zinin
Tim Zinin

Posted on Originally published at apify.com

How to Scrape Rightmove London Property Listings Without a Paid API

The problem

Rightmove is the UK's biggest property portal, and for anyone researching the London market — a sourcing analyst, a buy-to-let researcher, a relocation advisor, a proptech builder — its search-result cards are the primary source. There is no public API. The manual route is browsing search pages, opening each card, and transcribing price, bedrooms, area and address into a spreadsheet, then trying to keep units straight: Rightmove quotes many rentals per week, sale prices in pounds, floor areas in square feet, and posting dates as exact timestamps that other portals reduce to "3 days ago."

A home-grown scraper has its own traps. Rightmove's location identifiers are opaque TYPE^NUMBER tokens with no public name-to-code table, so "London" is REGION^87490 and nobody documents the mapping. Some listings carry no public price at all ("POA" — price on application, common at the high end), and roughly a third of London listings in spot checks publish no floor area. A scraper that silently fills those gaps with guesses produces a dataset that looks complete and is quietly fiction.

What the actor does

The Rightmove UK Property Listings Scraper collects bounded for-sale or to-rent listings from Rightmove search-result pages for a location code you supply (the default is London). No login, no API key, no browser on your side. For every listing card it extracts:

  • title, price and currency — with rental headline prices normalized to a single per-calendar-month figure even when Rightmove's internal record is weekly, so every rental row in the dataset is on the same comparable unit;
  • property_type, rooms (bedrooms), and area_sqm — floor area converted from square feet to square meters when the listing publishes a size;
  • location (the display address), lat/lng coordinates, a short description, card images, the direct listing url, and the full ISO posted_date — Rightmove publishes an exact date, and the actor preserves it;
  • completeness and provenance: found, partial/partial_reason, source_portal and scraped_at.

Nulls are honest. price: null means the listing has no public asking price (POA) and the actor never invents a number; area_sqm: null means the source simply doesn't publish a size. partial: true with a plain-English partial_reason tells you the run stopped at its own max_pages/max_items bounds before Rightmove confirmed there was nothing more — so a bounded sample is never presented as the whole market.

Beyond the raw card facts, rows carry a decision layer: a stable entityId derived from the listing URL, a derived pricePerSqm calculated only when both a positive price and positive area are present, a freshness classification, evidence confidenceScore/confidenceBand, and a recommendedAction such as REVIEW_LISTING or REVIEW_PARTIAL_LISTING.

Input is deliberately small: location_identifier (Rightmove's opaque TYPE^NUMBER code — to find another area's code, search it on rightmove.co.uk and copy the locationIdentifier parameter from the results page URL), deal_type (sale or rent), max_items (1–2,000) and max_pages (1–50, 24 listings per page). Rows where the source returned nothing — an unrecognized location, zero matches, a failed request — come back with found: false and an explanatory note, and are never charged.

Example: input and output

{
    "location_identifier": "REGION^87490",
    "deal_type": "sale",
    "max_items": 5,
    "max_pages": 1
}
Enter fullscreen mode Exit fullscreen mode

A real row from a live platform run (2026-08-01):

{
    "location_identifier": "REGION^87490",
    "deal_type": "sale",
    "found": true,
    "url": "https://www.rightmove.co.uk/properties/166896110#/?channel=RES_BUY",
    "title": "1 bedroom apartment for sale — Cashmere House, Leman Street, E1",
    "price": 800000,
    "currency": "GBP",
    "property_type": "Apartment",
    "rooms": 1,
    "area_sqm": null,
    "location": "Cashmere House, Leman Street, E1",
    "lat": 51.51373,
    "lng": -0.070178,
    "posted_date": "2025-09-11T17:32:28Z",
    "description": "Regent are proud to present this spectacular one-bedroom apartment with amazing view over the City in the heart of Cashmere House, part of the Goodman's Field development, E1...",
    "images": [
        "https://media.rightmove.co.uk:443/dir/crop/10:9-16:9/property-photo/36f551317/166896110/36f551317fd23d7243757894728a14a4_max_476x317.jpeg"
    ],
    "source_portal": "rightmove-london",
    "scraped_at": "2026-08-01T05:10:56.822Z",
    "partial": true,
    "partial_reason": "stopped after 1 page(s), 5 item(s) collected — reached this run's own max_pages/max_items limit before the source confirmed (via confirmedEnd) that there is nothing more; there may be additional matching listings beyond what was collected"
}
Enter fullscreen mode Exit fullscreen mode

(The actual row carries five card images; one shown here.)

Pricing and the free limit

Pay per event: $0.005 per run start plus $0.003 per result row. A run that collects 100 listings costs about $0.305. Not-found and failed-request rows are returned for transparency but never charged.

Apify's free plan gives $5 of usage credits per month. At this tariff, $5 covers up to 1,665 listings in a single run (0.005 + 0.003 × 1,665 = $5.00) — or about 16 full 100-listing runs at $0.305 each.

Try it

The London location code is already filled in — pick a deal type and press Start: Rightmove UK Property Listings Scraper

For AI agents and MCP

The actor takes JSON in and returns structured JSON dataset rows via the Apify API, and the README's machine-use section names the input and the dataset row as the machine-facing contract: price and area_sqm are null exactly when Rightmove doesn't publish a value, and an agent treating a run's results as the full market should check partial first. The README documents a dedicated MCP section with a ready-made call-actor payload for Apify MCP clients, plus an MCP server setup block alongside cURL, JavaScript and Python examples.

Top comments (0)