Skip to content

Website Change Monitor

Try for free

Watch any web page, or just one part of it, for changes. Every run compares each page with the previous check and returns what changed: added and removed lines, a diff, change share, before and after content and optional screenshots, with webhook alerts for Slack, Teams or Discord.

🔔 Website Change Monitor

Watch any web page, or just one part of it, and find out exactly what changed since the last check. Each run compares every page with the version it saw before and returns the added and removed lines, a ready-to-read diff, the share of the content that changed and both versions of the text, with optional screenshots and a webhook alert for Slack, Teams or Discord. No login, no code, and checks cost $1.80 per 1,000 pages on the Free plan, platform usage included.

✨ Why use Website Change Monitor?

  • 🎯 Watch only what matters — point it at a price, a job list or a changelog with a CSS selector, and leave out ads, clocks and counters so they never raise a false alarm.
  • 🧾 See the change, not just a flag — every changed page comes with the added and removed lines, a unified diff and a change percentage.
  • 📚 Many pages in one run — monitor a whole list of pages at once; each keeps its own history, even several areas of the same page.
  • ⚡ Fast and light — pages load over plain HTTP by default, so a check takes a few seconds; switch on the built-in browser only for pages that build their content with JavaScript.
  • 📸 Before and after screenshots — optional PNGs of the monitored area, with the version from before the last change kept next to the current one.
  • 🔔 Alerts where you work — one webhook POST per change, with a ready-made message that Slack, Microsoft Teams and Discord incoming webhooks show as is.

🎯 Use cases

  • 💲 Price monitoring — get told when a competitor's price, plan or discount changes.
  • 📦 Stock and availability — catch "back in stock" or "sold out" the moment it appears on a product page.
  • 🧑‍💼 Job and tender boards — see new postings on a careers page or a procurement list without reading it every day.
  • 📜 Policies and legal pages — track edits to terms, privacy policies or regulations, line by line.
  • 🛠️ Release notes and docs — follow a vendor's changelog, status page or API docs.
  • 🔍 SEO and content QA — notice when titles, headings or copy on your own or a competitor's pages change.

🚀 How to use

  1. Paste the pages to watch into Pages to monitor.
  2. Optionally enter a Monitored area CSS selector (e.g. main, #price, .job-list li) and the parts to ignore.
  3. Optionally add a Webhook URL to get an alert for every change.
  4. Run it once: the first run saves each page as the starting version (first-check).
  5. Schedule the same input (or a saved task) to run hourly or daily. Each later run reports changed or unchanged for every page.
  6. Download the rows as JSON, CSV or Excel, or read them through the API.

📥 Input

FieldWhat it does
startUrlsPages to monitor (url and urls are accepted too)
contentSelectorCSS selector of the part to watch; empty = whole page
compareOntext (visible text, default) or html (markup of the area)
ignoreSelectorsPage parts left out before comparing (ads, clocks, banners)
ignorePatternsRegular expressions for text left out before comparing (times, counters)
monitorNameName of the history the run continues; different names keep separate histories
webhookUrlReceives a JSON POST for every changed page
notifyOnErrorsAlso notify when a page cannot be checked
renderJavaScriptLoad pages in a browser so JavaScript-built content is included
saveScreenshotsSave a PNG of the monitored area on every check (uses the browser)
waitSecsExtra wait after the page loaded (browser only)
requestTimeoutSecsTime allowed per page
proxyConfigurationProxy for loading the pages (datacenter by default)
{
  "startUrls": [
    { "url": "https://scrape.ly/pricing" },
    { "url": "https://news.ycombinator.com/newest" }
  ],
  "contentSelector": "main",
  "ignorePatterns": ["\\d+ minutes? ago"],
  "monitorName": "competitors",
  "webhookUrl": "https://hooks.slack.com/services/T000/B000/XXXX"
}

contentSelector can also be set per page: add "selector": "..." to an item of startUrls when you call the actor through the API.

📤 Output

One row per page and run. This row is from a real run: the second check of the Scrape.ly Store list, after three new actors were published.

FieldDescription
url, finalUrl, title, httpStatusThe page that was checked
statusfirst-check, unchanged, changed or error
changedtrue when the content differs from the previous check
changeSummaryThe change in words, e.g. "2 lines added, 1 line removed (12.5% of the content)"
addedLines, removedLinesThe lines that are new and the lines that are gone
addedCount, removedCount, changePercentSize of the change
diffUnified diff from the previous to the current version
currentContent, previousContentBoth versions of the monitored content
contentHash, previousHash, contentLengthSHA-256 fingerprints and size of the content
checkedAt, previousCheckedAt, firstCheckedAt, lastChangedAtWhen the page was checked and last changed (UTC)
checkCount, changeCountChecks and changes in this page's history
screenshotUrl, previousScreenshotUrlScreenshot now and from before the last change
renderedWith, monitorName, noteHow the page was loaded, which history it belongs to, extra information
error, errorCodeWhy a page could not be checked
{
  "url": "https://scrape.ly/store/search",
  "finalUrl": "https://scrape.ly/store/search",
  "title": "All actors | Scrape.ly Store",
  "status": "changed",
  "changed": true,
  "changeSummary": "1 line added, 1 line removed (0.76% of the content)",
  "httpStatus": 200,
  "contentSelector": "main",
  "compareOn": "text",
  "addedLines": [
    "12 of 648 actors"
  ],
  "removedLines": [
    "12 of 645 actors"
  ],
  "addedCount": 1,
  "removedCount": 1,
  "changePercent": 0.76,
  "diff": "--- previous\n+++ current\n@@ -87,3 +87,3 @@\n Try for free\n-12 of 645 actors\n+12 of 648 actors\n //From the blog\\\\",
  "currentContent": "Back to store\nAll available actors\n…",
  "previousContent": "Back to store\nAll available actors\n…",
  "contentHash": "c3044f7906d7eb8212abace16b545ffd5c111745dfeac7bd50f641f888ba0597",
  "previousHash": "6eff12f2b1044dbd6c7ab196e138003aa09c330dae367d40cbb0753b92c376ba",
  "contentLength": 4713,
  "checkedAt": "2026-11-13T05:04:47.190Z",
  "previousCheckedAt": "2026-11-13T04:46:47.241Z",
  "firstCheckedAt": "2026-11-13T04:46:47.241Z",
  "lastChangedAt": "2026-11-13T05:04:47.190Z",
  "checkCount": 2,
  "changeCount": 1,
  "renderedWith": "http",
  "monitorName": "store-watch"
}

The run also saves a summary in the OUTPUT record: how many pages changed, stayed the same or failed, and the list of changed URLs.

💰 Pricing

  • $1.80 per 1,000 page checks on the Free plan, and less on paid plans ($1.50 on Scale, $1.20 on Business).
  • One check = one page compared in one run, whether it changed or not. Platform usage is included, also when pages load in the browser (Render JavaScript) or get screenshots: the price per check stays the same.
  • Pages that cannot be checked (not found, blocked, selector missing, invalid address) are free.
  • Example: 20 pages checked every hour for a month = 14,400 checks ≈ $25.92 on the Free plan.

❓ FAQ

Is it legal to monitor websites? The actor only reads public pages, the same way a visitor's browser does. Check the terms of the sites you monitor and the rules that apply to the data you collect.

Do I need a login or my own proxy? No. Pages load through a Scrape.ly datacenter proxy by default, and a page that blocks it is retried once over a residential proxy. The browser always loads pages through a proxy (the datacenter one when you turn the proxy off). Pages behind a login are not supported.

How does the first run work? The first run of a page saves its current version and reports first-check. From the second run on, every row says changed or unchanged and carries the difference.

Why does a page report a change on every run? Something on it changes on every visit: a clock, a counter, a rotating banner or a random token. Narrow the Monitored area, add the moving parts to Ignore page parts, or remove the text with Ignore text matching.

The monitored area is empty or not found. What now? The page probably builds that part with JavaScript. Turn on Render JavaScript, and if the content appears late, add a few seconds of Extra wait.

Can I schedule it or use the API? Yes. Save the input as a task and add a schedule (for example every hour); each run continues the same history. You can also start runs and read the rows through the Scrape.ly API, CLI, MCP server and integrations.

⚠️ Limits

  • Pages behind a login, a paywall or a captcha are not supported.
  • Each page's text is compared up to the first 2 million characters, and pages larger than 10 MB are not loaded. In a row, each version of the content shows up to 500,000 characters, and the line lists and diff of a very large change show its beginning.
  • Two runs of the same monitor at the same time can both compare against the same earlier version; give monitors that overlap in time different names.
  • Changing the selector, the compare mode or the ignore settings starts a new history for that page (its next check is a first-check).
  • Screenshot links stay valid for 31 days after the check.
  • Plain loading checks hundreds of pages a minute. In the browser each page takes about 5 to 25 seconds at the default memory (long pages with screenshots take the longest); for long lists give the run more memory, so more pages load at the same time, or a longer timeout.
//From the blog\\

Latest articles

All articles

The internet is full of data.
Start owning yours.

Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes.

No credit card. No setup calls.