OnTheMarket Scraper - Listings, Prices & New-Ad Alerts avatar

OnTheMarket Scraper - Listings, Prices & New-Ad Alerts

Pricing

$1.00 / 1,000 properties

Go to Apify Store
OnTheMarket Scraper - Listings, Prices & New-Ad Alerts

OnTheMarket Scraper - Listings, Prices & New-Ad Alerts

Scrape OnTheMarket UK for-sale search results: price, bedrooms, bathrooms, location, property type, public agent business name, listing age text and floor area when published. Seen-listing alerts can go to Discord, Telegram, Slack or any webhook.

Pricing

$1.00 / 1,000 properties

Rating

0.0

(0)

Developer

Luke Hunter

Luke Hunter

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Share

For property researchers, buyers, analysts, and scheduled alert workflows, this Actor scrapes public OnTheMarket sale search pages into flat listing rows with stable IDs, URLs, titles, prices, locations, dates, and source-specific property fields. It can also watch the same search for newly appearing listing IDs.

Pricing: $0.001 per delivered property listing. Rows skipped by robots rules, seen-listing state, parser filters, or run limits are not charged.

Quick start

{
"startUrls": [
"https://www.onthemarket.com/for-sale/property/london/"
],
"maxPagesPerSearch": 2,
"maxItems": 20,
"onlyNewSinceLastRun": false,
"stateStoreName": "onthemarket-scraper-seen-properties"
}

The prefill is intentionally capped at 20 rows, so a first run returns at least 10 captured-style listings when the public search page still has the expected shape.

Example output

{
"id": "20334833",
"url": "https://www.onthemarket.com/details/20334833/",
"title": "1 bedroom apartment for sale",
"price": 115625,
"currency": "GBP",
"areaM2": null,
"rooms": 1,
"bedrooms": 1,
"bathrooms": 1,
"location": "Plot 315 -SO - September 26, at Prime Point, Shared Ownership West Parkside, North Greenwich SE10",
"propertyType": "Apartment",
"transaction": "sale",
"agencyName": "L&Q - Prime Point, Shared Ownership",
"agentName": "L&Q - Prime Point, Shared Ownership",
"date": "Added > 14 days"
}

Missing source values are null; the Actor never guesses them.

Search-intent use cases

  1. Watch London sale searches for newly listed properties.
  2. Compare asking prices and bedroom counts across public search results.
  3. Export public agent-business inventory for market coverage analysis.

Pricing

The pay-per-event price is $0.001 per delivered listing using event property. Charging happens only after a row is pushed to the dataset; skipped or already-seen rows are not billed.

Notifications to Discord, Telegram, Slack, Teams, Google Chat, ntfy, Pushover and webhooks are free: you pay only for delivered listings, never for messages sent.

Limitations

  • Two promotional new-home ad cards per captured page have no property listing URL/title/address, so they are skipped instead of filling fields by guesswork.
  • Only the captured public for-sale/property search shape is implemented.
  • Floor area is null unless the result card explicitly publishes a sq ft floor area feature; the conversion to m² is arithmetic only. OnTheMarket's date field remains its relative Added/Reduced text because no absolute date is exposed in the captured card data.
  • Every request path is checked against the committed robots.txt capture before fetching, using one honest User-Agent and roughly one request every three seconds.
  • If page 2+ is blocked, rate-limited, malformed, or otherwise fails, rows already delivered from earlier pages are kept and the run reports partial results honestly.

New-listing alert mode

Set onlyNewSinceLastRun to true and keep the same stateStoreName across scheduled runs. Each search URL has independent seen-ID state. The first successful run establishes the baseline; later runs deliver and charge only listing IDs not previously delivered for that search.

Get OnTheMarket alerts in Discord, Telegram, Slack, Teams, Google Chat, your phone (ntfy/Pushover) or any app (webhook)

Want a OnTheMarket Discord alert, a OnTheMarket Telegram bot, or new listings pushed to Slack, Teams, Google Chat or your phone instead of checking a dataset? Add one or more destinations in the Actor's Notifications (optional) section and each run sends the listings it delivered. It is a monitor that notifies you: it only reads public OnTheMarket search pages and never contacts agents or sellers, buys anything or logs in anywhere, and the messages go only to the places you set up.

ChannelFill inWhat you get
DiscorddiscordWebhookUrlOne card per listing, 10 per message
TelegramtelegramBotToken + telegramChatIdUp to 10 listings per message, one line each
SlackslackWebhookUrlBlock Kit message, up to 10 listings per message
Mattermost, Rocket.ChatslackCompatibleWebhookUrlSlack-style incoming webhook: a Markdown list (these apps do not render Slack Block Kit)
Microsoft TeamsteamsWebhookUrlAdaptive Card from a Teams Workflows webhook, up to 10 listings per card
Google ChatgoogleChatWebhookUrlCard in a space, up to 10 listings per message
ntfy (phone push, no account)ntfyTopic (optional ntfyServer, ntfyToken)A push per listing, up to 10, then one "...and N more"
Pushover (phone push)pushoverUserKey + pushoverAppTokenA push per listing, up to 10, then one "...and N more"
Any app: Zapier, Make, n8n, Pipedream, IFTTT, Home AssistantwebhookUrlOne JSON POST per run with the delivered rows

Fill in as many as you like; each channel works on its own and a failing one never stops the others.

Setup, channel by channel

  • Discord (1 minute): Server Settings → Integrations → Webhooks → New Webhook → pick the channel → Copy Webhook URL.
  • Telegram (2 minutes): chat with @BotFather, send /newbot, paste the token into telegramBotToken. Add the bot to the chat or channel (administrator for a channel; for a chat with yourself press Start on the bot). telegramChatId is a numeric id (123456789, or -1001234567890 for a group or channel) or a public @channelusername.
  • Slack: at api.slack.com/apps create an app (From scratch) → Incoming Webhooks → switch it on → Add New Webhook to Workspace → pick the channel → copy the https://hooks.slack.com/services/... URL.
  • Mattermost or Rocket.Chat: create an incoming webhook in the app and paste its public https:// URL into slackCompatibleWebhookUrl. Localhost, private IP addresses and .local / .internal names are rejected.
  • Microsoft Teams: in the channel open ... → Workflows → Post to a channel when a webhook request is received → finish the wizard and copy the URL (a host ending in .logic.azure.com or .powerplatform.com). The old "Office 365 connector" webhooks are retired and not supported.
  • Google Chat: in the space open Apps & integrations → Webhooks → Add webhook, name it and copy the https://chat.googleapis.com/v1/spaces/... URL (needs a Google Workspace account that allows webhooks).
  • ntfy (free, no account): install the ntfy app (or open ntfy.sh), subscribe to a topic with a long random name, and put the same name in ntfyTopic. Anyone who knows the topic can read it, so make it unguessable. Own server or a protected topic: set ntfyServer (public https:// address) and ntfyToken.
  • Pushover: copy your user key from pushover.net into pushoverUserKey, create an application at pushover.net/apps/build and put its API token in pushoverAppToken. Pushover itself is a separate paid app after its trial: check their pricing.
  • Any app (webhook): paste the catch-hook URL from Zapier, Make, n8n, Pipedream, IFTTT or Home Assistant into webhookUrl. It must be a public https:// address.

The recipe: a OnTheMarket new-listing alert in five steps

  1. Set your search on onthemarket.com and paste its URL into startUrls.
  2. Turn on onlyNewSinceLastRun, so only listings not delivered before are sent.
  3. Add your destination(s) from the table above.
  4. Run it once. The first run is the baseline and sends what is currently listed (up to maxNotifications).
  5. Create a Schedule (for example every few hours). From then on you only hear about listings it has not delivered before for that search.
{
"startUrls": [
"https://www.onthemarket.com/for-sale/property/london/"
],
"onlyNewSinceLastRun": true,
"maxItems": 100,
"ntfyTopic": "your-long-random-topic-name",
"maxNotifications": 25
}

The generic webhook (webhookUrl)

Each run sends one POST per 100 delivered rows (so usually one) with this body, followed by whatever your tool does with it:

{
"source": "apify",
"actor": "onthemarket-scraper",
"runId": "HG7ML7M8z78YcAPEB",
"count": 2,
"total": 2,
"part": 1,
"parts": 1,
"items": [ { "...": "the full dataset rows" } ]
}

count is the number of rows in this POST, total the number in the run, and part / parts number the POSTs when a run delivers more than 100 rows. maxNotifications does not cap the webhook. Your endpoint should answer with a 2xx status; redirects are not followed and a failure is reported in the run status, never retried in a loop.

What to expect

  • What a message contains: title, address, price, bedrooms, bathrooms, floor area, property type, the agent and OnTheMarket's own "Added" or "Reduced" wording, plus the link.
  • Only delivered listings are sent. A run that finds nothing new sends nothing, so there is no "no new listings" spam. Rows the run could not deliver (for example because your spending limit was reached) are not sent.
  • maxNotifications (default 25, max 100) caps how many listings go to chat and phone channels per run (the webhook is not capped). The rest are still in the dataset and the status message says so. ntfy and Pushover send at most 10 individual pushes, then one "...and N more" summary.
  • Cost: notifications are free. You pay only for delivered listings at the usual price, exactly as without alerts. There is no extra charge for any channel.
  • Failures never fail the run. A deleted webhook or an unreachable service leaves the run successful and the dataset complete, and the status message says what happened, for example Notified: Discord 12, Slack 12, ntfy 10 (+summary). Teams failed (HTTP 404) - check the webhook URL. The logs show the channel name and HTTP status only, never a URL or token.
  • Your URLs, tokens and ntfy topic are stored as secret inputs. Anyone holding a webhook URL can post to that channel, so treat it like a password.
  • The dataset is unchanged. The output rows are identical whether or not you set a destination; the run's status message just gains a short note such as Notified: Discord 12, ntfy 10 (+summary).
  • It is a monitor that notifies you. It never contacts agents or sellers, buys anything or logs in to OnTheMarket, and the messages go only to the destinations you set up.

Use it from your code, Make, Zapier or n8n

Built for automated pipelines: small runs, stable field names, one row per item, and you pay only for rows actually delivered.

One API call that runs the Actor and returns the data (replace $APIFY_TOKEN with your token from Apify Console → Settings → Integrations):

curl -s -X POST "https://api.apify.com/v2/acts/lukehunter~onthemarket-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"startUrls": ["https://www.onthemarket.com/for-sale/property/london/"], "maxPagesPerSearch": 2, "maxItems": 20}'

JavaScript (npm i apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('lukehunter~onthemarket-scraper').call({
"startUrls": [
"https://www.onthemarket.com/for-sale/property/london/"
],
"maxPagesPerSearch": 2,
"maxItems": 20
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python (pip install apify-client):

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('lukehunter~onthemarket-scraper').call(run_input={"startUrls": ["https://www.onthemarket.com/for-sale/property/london/"], "maxPagesPerSearch": 2, "maxItems": 20})
items = client.dataset(run['defaultDatasetId']).list_items().items

Schedules, webhooks and no-code tools: save your input as a Task, add a Schedule (e.g. hourly or daily), and attach a webhook or one of the Integrations tab's connectors (Make, Zapier, n8n, Google Sheets, Slack) to push each run's results into your own system.

Only new items each run: set "onlyNewSinceLastRun": true on a scheduled Task and every run after the first delivers, and charges for, only items it hasn't delivered before for that same input. That makes it a ready-made change feed.

Reliability: an automated test runs this Actor's parser against the live site every day, and failures are fixed fast.

Feedback: an honest rating on the Store page, good or bad, helps others decide if this Actor fits their needs. Missing a field or found a problem? Open an issue on the Actor page.

FAQ

Does this Actor bypass blocks or CAPTCHAs? No. A challenge/block is reported honestly and the Actor stops that affected search.

Does it crawl listing detail pages? No. It parses only the public search pages represented by the committed fixtures.

Does it return seller personal data? No. It omits seller profiles, phone numbers, and other personal contact fields; only public real-estate business names shown on the ad/search card are returned where available.

Can I get OnTheMarket alerts by email? Not natively. There are two routes. (1) Set webhookUrl to a Zapier, Make or n8n catch hook and add an email or Gmail step: the webhook delivers the listings as JSON, so the email can list them. (2) Apify's own run integrations and run notifications can email you when a run finishes, but they only send a link to the run or dataset, not the listings themselves. For instant alerts without building anything, Telegram, ntfy or Pushover reach your phone directly.

Can I get OnTheMarket alerts in WhatsApp? Not natively, and we do not use unofficial WhatsApp APIs, which risk getting your number banned. The official route is the WhatsApp Business Platform (Cloud API) with its own business account, message templates and pricing: point webhookUrl at a Zapier, Make or n8n flow that calls it. For free phone alerts use Telegram or ntfy instead.

More from this publisher