Website Change Monitor: Page Change Detection & Diffs avatar

Website Change Monitor: Page Change Detection & Diffs

Pricing

from $2.10 / 1,000 changed pages

Go to Apify Store
Website Change Monitor: Page Change Detection & Diffs

Website Change Monitor: Page Change Detection & Diffs

Watch web pages for changes, a website change tracker: give it page URLs (or a dataset of them) and each scheduled run returns only the pages that changed, with a line-by-line diff, the sections affected, and added and removed text. Unchanged pages cost less. Selector, ignore and keyword filters.

Pricing

from $2.10 / 1,000 changed pages

Rating

0.0

(0)

Developer

Michael Costa

Michael Costa

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

15 hours ago

Last modified

Share

What does Website Change Monitor do?

Website Change Monitor watches web pages for changes. Give it the pages you care about; each run compares every page with what it saw last time and returns only the pages that changed, with a line-by-line diff, the sections the change is under, and the text that was added and removed. In short: change detection and a website change tracker for the pages you choose.

Run it on a schedule and send the changes to Slack, email or a webhook: a competitor's pricing page, a supplier's terms, a product's documentation, a tender or job page, a policy you have to track. It reads pages like a normal visitor, without a browser, and it is not a screenshot or visual-diff tool: it compares the text.

Input fields · API · Use it from Claude, ChatGPT or Cursor (MCP)

Jump to: Alerts · Fields · Price · How to use · Input · Output · AI agents (MCP) · Limits · FAQ

Try it in one click: the input comes pre-filled with Wikipedia's Main Page, which changes every day. The first run records it (1 page, $0.003, plus $0.00005 for the run start); run it again tomorrow to see what changed. Then replace it with the pages you actually want to watch.

Get page changes in Slack, email or a webhook

  1. Put your pages in Pages to watch and click Start. This first run returns every page as new: it's the baseline the next runs compare with.
  2. Click Save as a new task (top right of the actor page). A task keeps its own memory, so it always compares with its own last run.
  3. In Apify Console, open Schedules, click Create new, set how often (for example every day at 07:00, or every hour), then Add your task.
  4. On the task, open the Integrations tab and pick where the changes go:
    • Slack: click Configure, sign in, pick the channel and the "run succeeded" event. A useful message: {{resource.statusMessage}} and a link to the changes, <https://console.apify.com/storage/datasets/{{resource.defaultDatasetId}}|page changes>. Each row's summary reads like "1 line added, 1 removed in “Plans”".
    • Gmail: click Connect with Google, set the subject and body, and attach the dataset (for example as CSV).
    • HTTP webhook: event ACTOR.RUN.SUCCEEDED, your URL. Apify POSTs {"eventType": ..., "resource": {...}}; GET https://api.apify.com/v2/datasets/<resource.defaultDatasetId>/items?format=json (with your API token) returns the changed pages.

Apify's integrations fire after every successful run, including quiet ones: a quiet run's dataset is empty, and its status message says how many pages were unchanged.

A page that fails is never reported as a change. When a page is down, blocked by robots.txt or a bot check, or needs JavaScript, it isn't compared: it's listed as failed in the log and RUN_STATS, isn't charged, and the next run compares with the last text it really had. A page that answers 404 or 410 after being seen before is reported once as removed, and as changed if it comes back.

What data does Website Change Monitor return?

One row per page that is new, changed or removed since the last run:

FieldExampleNotes
urlhttps://example.com/pricingThe page as you listed it
statuschangednew (first check), changed, or removed (404/410)
summary1 line added, 1 removed in “Plans”One line for an alert
changedSections["Plans"]The headings the changes are under
added / removed["Starter costs $12 a month."]The changed lines (first 100)
linesAdded / linesRemoved1 / 1Complete counts; null for a new page
diff-Starter costs $10…Unified diff, 2 lines of context; null for a new page
matchedKeywords["price"]With Only report changes that mention; null without
text## Plans\nStarter costs…The watched text now (first 20,000 characters)
title, finalUrlThe page's title, and its address after redirects
checkedAt, previousCheckedAt, previousChangeAt2026-10-02T04:44:00ZWhen it was checked, last checked, and last changed

The full list is under Output.

How much does it cost to monitor a website for changes?

You pay per page checked, and a page that didn't change costs half as much as one that did:

  • $3.00 per 1,000 changed pages: a row in your results, for a page that is new (its first check), changed or removed;
  • $1.50 per 1,000 unchanged pages: a page checked, found unchanged and not returned;
  • plus $0.00005 each time a run starts.

The changed-page price is lower on paid Apify plans: $2.70 (Starter), $2.40 (Scale), $2.10 (Business) per 1,000.

Pages that fail (down, blocked, not found on the first check, JavaScript-only, a selector that matches nothing) are never charged.

  • The pre-filled example: the first run is 1 new page, $0.003; a later run is 1 changed page, $0.003.
  • A month, for example: 50 competitor pages checked daily, 3 of them changing on a typical day: 30 × (47 × $0.0015 + 3 × $0.003) + the start fees ≈ $2.39. The same 50 pages every hour, with the same 3 changes a day: ≈ $54.17.
  • Caps: Max pages per run in the input, and Maximum cost per run in the run options. The run stops cleanly at whichever comes first; pages not checked are checked by the next run.

How to monitor a web page for changes

  1. Open Website Change Monitor and click Try for free (or Start if you're signed in).
  2. Put the pages in Pages to watch, one per line.
  3. Optional: pick the Part of the page to watch, a CSS selector, text to ignore, or words to watch for.
  4. Click Start. The first run records every page; open the Output tab to see them.
  5. Save it as a task and schedule it (Alerts); each later run returns only what changed.

Example: a busy page, and how to quiet it

Two pages, checked twice, 2 minutes apart (real output from local runs on 2026-10-02):

{"urls": ["https://en.wikipedia.org/wiki/Main_Page", "https://news.ycombinator.com/"],
"monitorName": "readme-example"}

The first run returned both pages as new (2 × $0.003 = $0.006). The second said "2 of 2 pages checked (compared with the run of 2026-10-02 04:54 UTC): 1 changed, 0 new, 0 removed, 1 unchanged" and returned one row, for $0.0045 ($0.003 for the changed page, $0.0015 for the unchanged one). Shortened (usernames replaced by …, 2 of 8 lines shown):

{
"id": "0f63a2a5a5620b745938e6a2",
"url": "https://news.ycombinator.com/",
"title": "Hacker News",
"status": "changed",
"summary": "8 lines added, 8 removed in “Hacker News”",
"changedSections": ["Hacker News"],
"linesAdded": 8,
"linesRemoved": 8,
"added": ["| | 42 points by … 1 hour ago \\| hide \\| 14 comments | |",
"| | 44 points by … 2 hours ago \\| hide \\| 14 comments | |", "..."],
"removed": ["| | 41 points by … 1 hour ago \\| hide \\| 14 comments | |",
"| | 43 points by … 2 hours ago \\| hide \\| 13 comments | |", "..."],
"diff": "--- before\n+++ after\n@@ -4,9 +4,9 @@\n ...\n-| | 41 points by … 1 hour ago ...\n+| | 42 points by … 1 hour ago ...",
"wordCount": 891,
"checkedAt": "2026-10-02T04:55:53Z",
"previousCheckedAt": "2026-10-02T04:54:08Z",
"previousChangeAt": null
}

Every changed line was a vote or comment count, which is noise for most people watching a page like this. Adding Ignore text matching \d+ points?, \d+ comments? and \d+ (minute|hour|day)s? ago turns those into …; the next run compares afresh (not reported), and after that only stories that appear, disappear or move are changes. Wikipedia's Main Page didn't change in those 2 minutes; it changes daily.

Input

FieldWhat it does
Pages to watch (urls)The pages, one per line; https:// is added when missing. Up to 2,000 per run.
Or: page URLs from a dataset (datasetId)Another actor's results, e.g. every page Sitemap URL Extractor found on a site. urls is then ignored.
Part of the page (contentScope)main (default): the main content, without menus, headers, footers and sidebars. page: all visible text.
Only this part of the page (cssSelector)A CSS selector such as #pricing or .product-price; only matching elements are compared.
Ignore text matching (ignorePatterns)Regular expressions for text that changes without meaning anything (view counts, "updated 5 minutes ago"); each match becomes … before comparing.
Only report changes that mention (watchFor)Words or phrases; a change is returned only when an added or removed line contains one.
Count changed link addresses as changes (includeLinks)Off by default: link text is compared, not its address (tracking parameters change on every visit).
Monitor name (monitorName)Which memory to compare with. Tasks get their own automatically; set it when you run several monitors without tasks.
Max pages per run (maxResults)Caps the pages checked in one run.
{
"urls": ["https://example.com/pricing", "https://example.com/terms"],
"contentScope": "main",
"ignorePatterns": ["\\d+ (views|comments)"],
"watchFor": ["price", "$"]
}

Output

Every row has the same fields; a field that doesn't apply is null (for example diff on a new page, text on a removed one).

FieldTypeMeaning
idstringStable id of the page (from its URL), the same on every run
urlstringThe page as you listed it
finalUrlstring or nullIts address after redirects
titlestring or nullThe page's title
statusstringnew, changed or removed
summarystringWhat changed and where, in one line
changedSectionsarrayThe headings the changes are under; (top of page) before the first heading
linesAdded, linesRemovedinteger or nullComplete counts of changed lines
added, removedarrayThe changed lines: the first 100, each up to 1,000 characters
diffstring or nullUnified diff with 2 lines of context, up to 30,000 characters
diffTruncatedbooleanThe diff was cut (the counts stay complete)
matchedKeywordsarray or nullThe watched words found in the changed lines
textstring or nullThe watched text now, as Markdown lines, up to 20,000 characters
textTruncatedbooleantext was cut at 20,000 characters
textCutAtLimitbooleanThe page has over 200,000 characters of text; only the first 200,000 are compared
wordCountinteger or nullWords in the watched text
contentHash, previousContentHashstring or nullHashes of the watched text now and last time
checkedAtstringWhen this run checked the page (ISO 8601, UTC)
previousCheckedAt, previousChangeAtstring or nullWhen this monitor last checked it, and last saw it change
sourceTitle, sourcePlaceId, sourceIndexWith a dataset: the source item's title, placeId and position

The run's RUN_STATS record lists every page with its status (new, changed, removed, unchanged) or the reason it failed, and the totals (pagesChanged, pagesUnchanged, ...).

Run it on a schedule, or from your own code

  1. Save your input as a task and add it to a schedule; the steps are under Alerts.
  2. Collect results: download the dataset as JSON, CSV or Excel; fetch the latest run's changes from the API (GET https://api.apify.com/v2/actor-tasks/<task id>/runs/last/dataset/items?status=SUCCEEDED&format=json, with your API token); let a webhook tell your system when a run succeeds; or connect it to Make, Zapier or n8n through Apify's integrations.

Can I use Website Change Monitor from an AI agent (MCP)?

Yes, through Apify's MCP server, from Claude, ChatGPT, Cursor or any other MCP client. Add this to your client's MCP configuration; your client signs you in to Apify:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=humble-echidna/website-change-monitor"
}
}
}

To use an Apify API token instead of signing in, add "headers": {"Authorization": "Bearer <APIFY_TOKEN>"} next to url.

The agent passes the pages and a monitor name of its own, e.g. {"urls": ["https://example.com/pricing"], "monitorName": "agent-pricing"}, and reads summary and added / removed for each changed page. An empty result means nothing changed since its last call with that name.

Who it's for

Product, marketing and sales teams watching competitors' pricing, plans and feature pages; procurement and legal teams tracking suppliers' terms, policies and price lists; anyone waiting for a page to change (a tender, a job, a "coming soon" or out-of-stock page). The recurring job: the same list of pages, checked every day or every hour, with an alert only when something actually changed.

Why this one?

  • Unchanged pages cost half. A page that didn't change is charged $1.50 per 1,000, a changed one $3.00, so checking often costs less than a flat per-check price. No compute, proxy or storage charges on top, apart from the $0.00005 run-start fee.
  • Changes you can act on. Each change says which section it's in and which lines were added and removed, plus a unified diff, not just "the page changed".
  • Less noise. Main content only by default (a new menu item or footer line isn't a change), link addresses ignored by default, your own ignore patterns, and an optional keyword filter.
  • Failures aren't changes. A page that's down, blocked or replaced by a bot check isn't compared or charged; the next run compares with its last real text.
  • Polite and safe. It identifies itself honestly (User-Agent HumbleEchidnaApify), follows each site's robots.txt and Crawl-delay, makes at most 2 requests per site at once, and only requests public web addresses on the standard ports (80 and 443).
  • Reliable. One failing page never affects the others. The log and RUN_STATS say which page had a problem and why.

Limits

  • No browser: pages that build their text with JavaScript are reported as failed (not charged). Most public pages (pricing, docs, terms, news, listings) are served as HTML and work.
  • Text only: a changed image, color or layout isn't a change unless its text (or, with includeLinks, a link address) changes.
  • Up to 2,000 pages per run and 200,000 characters of text per page; split bigger sites into several tasks.
  • No logins, no proxies: pages behind a login, and sites that refuse automated visitors or answer with a bot check, are reported and not charged.

FAQ

How does Website Change Monitor know what changed since the last run?

It keeps each monitor's memory in a key-value store named website-change-monitor-memory in your own Apify account: per page, a hash of its watched text, and the text itself when it changed. Each run compares with that and moves the memory on only for the pages you got a result for, so a run stopped by your maximum cost reports the change next time.

Why is a page I didn't change reported as changed?

Usually a counter, date or rotating block in the page's main content. Add an Ignore text matching pattern for it (for example \d+ views or updated .* ago), watch only the part you care about with a CSS selector, or use Only report changes that mention. Changing these settings compares the affected pages afresh on the next run (not reported, charged as unchanged), so you don't get a burst of false changes.

Can I watch a whole website?

Yes: run Sitemap URL Extractor on the site and pick its dataset in Or: page URLs from a dataset, up to 2,000 pages per run. A page that newly appears in the list is reported as new.

Why did a page come back as "blocked by robots.txt" or "needs JavaScript"?

The site's robots.txt disallows automated visitors on that page, or the page has no text until a browser runs its scripts. Both are listed in the log and RUN_STATS, and neither is charged.

Does it run on Apify's schedule, or does it watch continuously?

It checks when it runs. Schedule it as often as you need (hourly is common); each run is quick for a few dozen pages.

It reads public pages anyone can open, without logging in, identifies itself honestly and follows each site's robots.txt. What you do with the text is up to you and the site's terms; don't use it to republish someone else's content.

ActorUse it when
Sitemap URL ExtractorYou want to watch every page of a site: it lists the URLs to feed in.
Website & Page to Markdown for RAG and LLMsYou want the full pages as clean Markdown, for example to refresh a knowledge base.
Product Price & Stock MonitorThe pages are product pages and you want price and stock as fields.

Feedback and support

Found a bug, or a page that's reported as changed when it isn't? Open an issue on the Issues tab with the input you used.

Versions

Current version: 0.1. See the Changelog tab for what changed in each version.