# Rightmove BMV Deal Finder (`lowlanddata/rightmove-bmv-deal-finder`) Actor

One run samples an area, builds the market median per bedrooms and property type, and delivers the listings priced well below their group - below-market-value leads with the discount percent computed. Asking prices, honestly labeled. No agent contact data.

- **URL**: https://apify.com/lowlanddata/rightmove-bmv-deal-finder.md
- **Developed by:** [Lowland Data](https://apify.com/lowlanddata) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.59 / 1,000 results

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/actors/running/actors-in-store.md#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

## Rightmove BMV Deal Finder — below-market-value property leads

Find **below-market-value (BMV) properties on Rightmove** in one run. The actor samples an area's live listings, builds a market median for every group of comparable properties (same bedrooms, same property type), and delivers only the listings priced at least N% below their group's median — sorted steepest discount first, each with the market context that justifies it.

This is the answer UK property sourcers pay from £14/month for, delivered as a pay-per-result scan: point it at a town, get back the mispriced listings with the numbers already done.

**No personal data, ever.** Built on the same privacy-first extractor as the [Rightmove Scraper](https://apify.com/lowlanddata/rightmove-scraper): no agent phone numbers, no contact routes, no coordinates — agencies appear as business names only.

### Quick start (30 seconds)

1. Put a place name into **location** — a town (`Manchester`), area (`Camden, London`) or outcode (`EN2`), just like the Rightmove search box.
2. Click **Start**. The defaults do the rest: 12 pages sampled, deals at 15% or more below their group median.
3. When the run finishes, open the dataset's **Overview** tab — asking price, group median and discount side by side — or **Export** it as CSV/Excel/JSON.

A run at default depth finishes in under a minute. The run's status message tells you what happened at a glance: how many listings were sampled, how many comparison groups formed, how many deals cleared the bar.

### Who this is for

- **BMV property sourcers.** The daily grind — pull an area, compare every listing to its comps, shortlist the underpriced ones — becomes one run per area. The output is the shortlist.
- **Buy-to-let investors screening areas.** Run several towns and compare where discounts cluster. Run the `rent` channel to spot below-market rents — the other half of a yield calculation.
- **Flippers hunting mispriced listings.** Sort is steepest-first; the top of the dataset is where the margin lives. The `auction` flag tells you which leads need cash.
- **Deal packagers.** Each row carries the evidence — group, sample size, median, discount — so a lead sheet is an export, not a spreadsheet session.

A real run, for scale: Manchester at defaults with a 20% threshold sampled 149 listings, formed 7 comparison groups, and delivered 18 deals — the steepest 65% below its group's median (an auction lot, which is exactly the kind of thing the flags are for).

### What you get

Each deal is one dataset item: the full listing plus four scoring fields.

```json
{
  "propertyId": "169700001",
  "url": "https://www.rightmove.co.uk/properties/169700001",
  "title": "2 bedroom flat for sale",
  "displayAddress": "Chase Side Avenue, Enfield, EN2",
  "priceGbp": 150000,
  "currency": "GBP",
  "priceFrequency": null,
  "priceQualifier": "Offers Over",
  "bedrooms": 2,
  "bathrooms": 1,
  "propertyType": "Flat",
  "channel": "buy",
  "tenureType": "LEASEHOLD",
  "displaySize": "678 sq. ft.",
  "summary": "A well presented two bedroom apartment...",
  "firstVisibleDate": "2026-06-12T10:14:02Z",
  "listingUpdateReason": "price_reduced",
  "listingUpdateDate": "2026-08-10T09:06:33Z",
  "addedOrReduced": "Reduced on 10/08/2026",
  "agencyName": "Ian Gibbs, Enfield",
  "featured": false,
  "auction": false,
  "imageUrls": ["https://media.rightmove.co.uk/property-photo/example.jpeg"],
  "bucket": "2-bed flat",
  "bucketSize": 34,
  "bucketMedianGbp": 200000,
  "discountPct": 25
}
```

Field notes, so you know exactly what you are buying:

- `bucket` is the comparison group the deal was scored in — bedrooms plus property type, so a 2-bed flat is only ever compared to other 2-bed flats.
- `bucketSize` is how many priced listings the median was computed from. Bigger is steadier; groups under 5 listings are skipped entirely rather than scored on noise.
- `bucketMedianGbp` is the group's median asking price in the sampled area, and `discountPct` is how far below it this listing sits.
- `auction` matters here more than anywhere: steep discounts are often auction lots. Check it before you get excited.
- `priceQualifier` (`Guide Price`, `Offers Over`) and `addedOrReduced` carry the listing's own pricing signals — a fresh reduction landing below median is a stronger lead than a stale one.
- `agencyName` is a trading name and branch only; `displayAddress` is the address exactly as the agent published it. No contact data, no coordinates — by design.

### How much does it cost to find BMV deals?

$1.99 per 1,000 deals delivered, pay-as-you-go — you pay for deals, not for the market sample behind them. A typical run delivers 10–50 rows, so **a full area scan costs roughly $0.02–$0.10**. No subscription, no charge for failed runs.

The price is all-inclusive — platform usage is covered, with no separate compute or proxy charges. Datacenter proxies are sufficient, and a default-depth run finishes in under a minute. Compare that to the £14+/month sourcing tools doing the same arithmetic.

Free-plan runs are limited to 25 items — more than a typical scan delivers anyway, so the free plan is a genuine trial here.

### Not technical? Let your AI assistant set it up

Copy this into ChatGPT, Claude or any AI assistant, fill in the one line, and follow the conversation:

```text
Help me set up the "Rightmove BMV Deal Finder" actor on Apify
(https://apify.com/lowlanddata/rightmove-bmv-deal-finder). Guide me one step at a time.

What I want to find: [E.G. "houses priced well below market in Sheffield, up to 250k"]

Guide me to:
1. Propose my input values: location (as I'd type it on rightmove.co.uk),
   channel buy or rent, an optional priceMinGbp/priceMaxGbp band,
   bedroomsMin/bedroomsMax, discountThresholdPct (15 is a sensible start),
   and samplePages (12 by default; more = steadier medians).
2. Create a free Apify account (apify.com), open the actor page, paste the
   values into the Input form, and start a run.
3. Read the results with me: what bucket, bucketMedianGbp and discountPct
   mean, and why I should check the auction flag on the steepest discounts.
4. Set up a daily Schedule in the Apify Console with the same input, plus an
   email or Slack integration so new deals reach me automatically.
5. Show me how to export results as CSV/Excel, or read them from the API if I code.
6. If the results are what I wanted, remind me at the end to leave a quick rating
   on the actor page, and to report anything broken or missing on its Issues tab.
```

### Input

| Field                  | Description                                                                                            |
| ---------------------- | ------------------------------------------------------------------------------------------------------ |
| `location`             | Place as you would type it on Rightmove. Required. First suggestion wins.                              |
| `channel`              | `buy` (default) or `rent`.                                                                             |
| `priceMinGbp`          | Only properties priced at least this many pounds (per month for rentals).                              |
| `priceMaxGbp`          | Only properties priced at most this many pounds (per month for rentals).                               |
| `bedroomsMin`          | At least this many bedrooms.                                                                           |
| `bedroomsMax`          | At most this many bedrooms.                                                                            |
| `radiusMiles`          | Widen the search this many miles around the location.                                                  |
| `discountThresholdPct` | A listing must be at least this far below its group median to count as a deal. 5–60, default 15.       |
| `samplePages`          | Result pages sampled to establish the market medians. 2–42, default 12. More pages = steadier medians. |
| `maxItems`             | Upper bound on deals delivered (default 100, free plan 25).                                            |
| `proxyConfiguration`   | Proxy settings; keep Apify proxy enabled.                                                              |

One sample serves both sides of the comparison: the same listings that build the medians are the candidates scored against them, so a run never charges you twice for the same area. If the sample is too thin to form even one comparison group, the run fails with a readable message — widen the area or raise `samplePages` — and costs you nothing.

### Use it from your code

Run the actor and get deals straight back with one HTTP call — well within the sync window, since runs finish in under a minute:

```bash
curl "https://api.apify.com/v2/acts/lowlanddata~rightmove-bmv-deal-finder/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -X POST -H "Content-Type: application/json" \
  -d '{"location": "Manchester", "discountThresholdPct": 20}'
```

Node.js:

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

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('lowlanddata/rightmove-bmv-deal-finder').call({
  location: 'Manchester',
  discountThresholdPct: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("lowlanddata/rightmove-bmv-deal-finder").call(
    run_input={"location": "Manchester", "discountThresholdPct": 20})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

Schedules, webhooks and the Make/Zapier/n8n integrations all work out of the box — this is a standard Apify actor.

### Use it with AI agents (MCP)

Claude, Cursor and other MCP-capable agents can run this finder as a tool through Apify's hosted MCP server: the agent picks the area, starts the scan and reads the deals — no glue code.

Claude Code:

```bash
claude mcp add apify --transport http "https://mcp.apify.com?actors=lowlanddata/rightmove-bmv-deal-finder"
```

Cursor or Claude Desktop (add a custom connector / MCP server with this URL):

```text
https://mcp.apify.com?actors=lowlanddata/rightmove-bmv-deal-finder
```

Sign in with your Apify account when prompted — runs are billed to it. Setup details per client: [Apify MCP docs](https://docs.apify.com/platform/integrations/mcp).

Prompts that work once connected:

- "Scan Leeds for properties at least 20% below market and tell me which ones aren't auctions."
- "Compare BMV deal counts in Hull, Bradford and Stoke and tell me where discounts cluster."
- "Find below-market 2-bed flats within 5 miles of Liverpool and summarize the top five."

### Is it legal to scrape Rightmove for BMV deals?

The finder works entirely on public listing data — asking prices, bedrooms, property types — which is public commercial information, and it inherits the Rightmove Scraper's structural guarantee: **no personal data enters your dataset in the first place.** Agent phone numbers, contact routes and exact coordinates are never read into the output; the agency appears as a business name only. UK GDPR sets strict rules on personal data, and the cleanest answer to those rules is a dataset that contains none.

The medians are computed by the actor from that same public sample — no third-party valuation data, nothing beyond what any Rightmove visitor sees. Requests are paced, load on the site is kept negligible, and no anti-bot protection is bypassed.

### Is there a Rightmove API for finding underpriced properties?

No — Rightmove publishes no public listings API, and no API anywhere hands you "listings below their local market median". This actor is the practical route: one HTTP call (`run-sync-get-dataset-items`) returns the deals with the market context attached, on demand, on a schedule, or as an MCP tool for AI agents.

### Does Rightmove block scrapers?

Rightmove serves its listings openly to ordinary requests — and this actor stays inside that welcome: paced requests, standard datacenter proxies, load kept negligible. No CAPTCHA fights, no bot-wall cat-and-mouse — which is also why a scan reliably finishes in under a minute and holds up on a daily schedule.

### How do I monitor an area for BMV deals?

Set your `location` and threshold, then add a daily Schedule in the Apify Console with an email or Slack integration on the runs — every morning the mispriced listings land in your inbox, steepest first, with the median maths already done. The run's status message doubles as the digest line: deals found, sample size, group count. New listings priced wrong tend to be corrected or snapped up fast, so a daily cadence is the difference between sourcing and archaeology. The AI-assistant prompt above walks a non-technical user through exactly this setup.

### FAQ

**How do I find below market value property?** Compare each listing's asking price to what comparable properties ask in the same area — same bedrooms, same type — and shortlist the ones sitting well below. That is precisely what one run of this actor does: sample the area, build the medians, deliver the listings 15% (or your threshold) below their group.

**What does BMV mean?** Below Market Value — a property priced under what comparable properties go for. Sourcers and investors hunt BMV deals for built-in margin: instant equity on purchase, or headroom on a flip.

**How does the market median work?** The run samples up to `samplePages` pages of the area's live listings, groups them by bedrooms + property type, and takes the nearest-rank median asking price of each group with at least 5 priced listings. Every deal row carries its group's median and sample size, so you can judge the evidence yourself.

**Why do auction properties show up as big discounts?** Auction guide prices are set low to attract bidding, so they often sit far below the local median — the steepest discount in a run is frequently an auction lot. Every row carries the `auction` flag, so filtering them out (or in — some sourcers want exactly those) is one column.

**Are the discounts against sold prices or asking prices?** Asking prices. The median is built from what sellers in the area are currently asking, not from Land Registry sold data. That makes it a live mispricing signal, not a valuation — a listing 25% below its peers is a lead to investigate, never a verdict.

**Is a big discount always a good deal?** No. Steep discounts usually have a reason: auction terms, shared ownership (where the price is for a share, not the whole property), cash-only sales, short leases, condition. The `auction` flag is in every row and the `summary` text usually says the rest. Treat the dataset as a shortlist for due diligence, not a buy list.

**What discount threshold should I use?** 15% (the default) is a sensible sourcing bar: enough margin to matter, loose enough to produce leads in most areas. Raise it to 20–25% in cheap, high-volume markets to cut noise; drop it toward 10% in expensive, tight markets where genuine mispricing is rarer and smaller.

**How many sample pages do I need?** The default 12 balances speed and stability. More pages mean more listings per group and steadier medians — worth it in large cities with many property types. In small towns, more pages may not exist; if a run reports few groups, widen `radiusMiles` instead.

**Why did my run find zero deals?** Usually a healthy market plus a strict threshold. Check the run's status message: if the sample and group counts look solid, lower `discountThresholdPct`; if groups are scarce, widen the area or raise `samplePages`. A zero-deal run still tells you something — nobody in that area is visibly mispricing.

**Can I find below-market rents too?** Yes — set `channel: "rent"` and the same maths runs on monthly rents. Useful from both sides: a below-market rent to negotiate as a tenant, or — for investors — evidence of what comparable properties actually ask, the other half of a yield calculation.

**Can I limit deals to my budget?** Yes — `priceMinGbp`/`priceMaxGbp` and `bedroomsMin`/`bedroomsMax` narrow the search before sampling, so both the medians and the deals reflect exactly the slice of the market you can buy in.

**What does the `bucket` field mean?** The comparison group the deal was scored in, e.g. `2-bed flat` — bedrooms plus property type. Listings missing either value can't be fairly compared and are left out of scoring entirely.

**Can I run it on a schedule?** Yes — any input works on an Apify Schedule. Daily is the sweet spot for sourcing: mispriced listings get corrected or taken quickly. Pair the schedule with an email or Slack integration and the deals come to you.

**Can I export to Excel or CSV?** Yes — every dataset exports as CSV, Excel, JSON or XML from the Apify Console or API. The Overview table (price, group, median, discount, link) is built for exactly that export.

**How is this different from the Rightmove Scraper?** The [Rightmove Scraper](https://apify.com/lowlanddata/rightmove-scraper) delivers listings; this actor delivers an answer. It runs the sampling, grouping, median maths and threshold filtering for you and charges only for the deals — the raw-data actor is the right tool when you want every listing.

**Does it include agent phone numbers or contact details?** No — by design, and it never will. Agencies appear as trading names only, and coordinates are never collected. The dataset is safe to store, share and pipe into a CRM without a privacy review.

**Does it work with Make, Zapier or n8n?** Yes — it is a standard Apify actor; all platform integrations, webhooks and schedules apply.

**Why did my run stop at 25 results?** That is the free-plan sample cap — though a typical scan delivers 10–50 deals, so on the free plan you are usually seeing the full result anyway. Any paid Apify plan removes the cap.

### Related scrapers

The same privacy-clean Rightmove data, cut different ways:

- [Rightmove Scraper](https://apify.com/lowlanddata/rightmove-scraper) — the parent: full listings as structured JSON, every filter, every field.
- [Rightmove Price Reductions](https://apify.com/lowlanddata/rightmove-price-reductions) — sellers already cutting: a reductions-only feed with the old-to-new price move parsed.
- [Rightmove New Listings Alert](https://apify.com/lowlanddata/rightmove-new-listings-alert) — only what's new since your last run, deduplicated, built for schedules.

### Troubleshooting

The actor fails fast with the reason in the run's status message:

- **"No (bedrooms, property type) group reached 5 priced listings - the area sample is too thin to define a market price. Widen the area or raise samplePages."** — the area sample was too thin to compute any median. Widen the area (`radiusMiles`), raise `samplePages`, or loosen the price/bedrooms filters. The run delivered nothing and costs nothing.
- **"Rightmove does not know the location ..."** — type the place as the Rightmove search box suggests it, e.g. `Camden, London` instead of an abbreviation.
- **"priceMinGbp must not be higher than priceMaxGbp."** — swap the two values.
- **"Rightmove blocked the run before any results could be fetched. This is usually temporary - retry in a few minutes."** — a temporary block on the first request; a retry usually lands on a clean proxy session.
- **Zero deals, healthy sample** — not an error. Check the status message's group count, then lower `discountThresholdPct` or accept that the area is priced tight today.

### Support

Found an issue or missing a field you need? Open an issue on the actor's **Issues tab** — reports get fixed, this actor is actively maintained.

Working well for you? A **rating on this page** takes ten seconds and helps other sourcers find this — it is also the clearest signal of what we should build next.

# Actor input Schema

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

Place to search, exactly as you would type it in the Rightmove search box: a town ("Manchester"), area ("Camden, London") or outcode ("EN2"). The first suggestion Rightmove offers for it is used.

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

Search properties for sale (buy) or to rent (rent).

## `priceMinGbp` (type: `integer`):

Only include properties priced at least this many pounds. For rentals this is pounds per month.

## `priceMaxGbp` (type: `integer`):

Only include properties priced at most this many pounds. For rentals this is pounds per month.

## `bedroomsMin` (type: `integer`):

Only include properties with at least this many bedrooms.

## `bedroomsMax` (type: `integer`):

Only include properties with at most this many bedrooms.

## `radiusMiles` (type: `integer`):

Widen the search this many miles around the location. 0 = the location only.

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

Upper bound on deals delivered. Free-plan runs are capped at 25 items.

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

Proxy settings. Keep Apify proxy enabled.

## `discountThresholdPct` (type: `integer`):

A listing must be at least this far below its group median (same bedrooms + property type) to count as a deal. 15 is a sensible sourcing bar.

## `samplePages` (type: `integer`):

Result pages sampled to establish the market medians (2-42). More pages = steadier medians, longer run.

## Actor input object example

```json
{
  "location": "Manchester",
  "channel": "buy",
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "discountThresholdPct": 15,
  "samplePages": 12
}
```

# Actor output Schema

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

Scraped Rightmove properties, one JSON object per listing.

# 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 = {
    "location": "Manchester",
    "channel": "buy",
    "maxItems": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    },
    "discountThresholdPct": 15,
    "samplePages": 12
};

// Run the Actor and wait for it to finish
const run = await client.actor("lowlanddata/rightmove-bmv-deal-finder").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 = {
    "location": "Manchester",
    "channel": "buy",
    "maxItems": 25,
    "proxyConfiguration": { "useApifyProxy": True },
    "discountThresholdPct": 15,
    "samplePages": 12,
}

# Run the Actor and wait for it to finish
run = client.actor("lowlanddata/rightmove-bmv-deal-finder").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 '{
  "location": "Manchester",
  "channel": "buy",
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "discountThresholdPct": 15,
  "samplePages": 12
}' |
apify call lowlanddata/rightmove-bmv-deal-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lowlanddata/rightmove-bmv-deal-finder"
        }
    }
}

```

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/6CA2mT6NeLf0t8edh/builds/BWtRKEbxSy3xFmipc/openapi.json
