Website Change Monitor – Page Diff, Price & Keyword Alerts
Under maintenancePricing
from $0.50 / 1,000 page checkeds
Website Change Monitor – Page Diff, Price & Keyword Alerts
Under maintenanceMonitor web pages for changes on a schedule: line-by-line diff, change %, CSS-selector targeting, price-drop and keyword alerts, webhook to Slack/Discord/n8n. HTTP only, robots.txt respected. Unchanged checks cost $0.0005.
Pricing
from $0.50 / 1,000 page checkeds
Rating
0.0
(0)
Developer
Cemal Atakli
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Monitor any web page for changes and get only what changed. Give the Actor a list of URLs (optionally a CSS selector per page), schedule it, and every run compares the page with the previous snapshot. You get a line-by-line diff (added / removed lines), the change percentage, the old and new price, watched keywords that appeared or disappeared, and an optional webhook to Slack, Discord, n8n, Make or Zapier. A cheap, API-first Visualping / Distill alternative for competitor pricing, terms & policy pages, tender and job boards, government registers and product stock pages.
- Watch only the part that matters: a CSS selector (
#pricing,main,.product-info,table.results) plus "ignore these elements" (.related-posts,#footer). - Real diffs, not just "something changed":
addedLines,removedLines, a unifieddiffandchangeRatio. - Price-drop alerts: price read from product meta tags / JSON-LD, a price selector, or the first amount with a currency. Output:
price,previousPrice,priceChange,priceChangePercent. - Keyword alerts:
watchFor: ["sold out", "deadline", "Series A"]→ counts per keyword, pluskeywordsAppeared/keywordsDisappeared. - No false alarms from clocks and nonces: times of day, "5 minutes ago", session tokens, ads and cookie banners are masked; dates optionally too; your own regex ignore patterns.
- Noise threshold:
minChangePercentand "only alert on keywords or price" mode. - State that survives runs: snapshots live in your named key-value store
website-change-monitor-<stateKey>; one Actor task = one monitor. - Polite and cheap: HTTP only (no browser), robots.txt respected (incl. Crawl-delay), one request per site at a time, conditional requests (ETag / Last-Modified), honest User-Agent.
What can I use it for?
- Competitor price and plan monitoring: pricing pages, product pages, feature lists.
- Compliance and legal: terms of service, privacy policies, cookie policies, supplier codes of conduct.
- Procurement and grants: tender notice pages, "open calls" pages, funding programme pages.
- Government and regulators: registers, guidance pages, "last updated" pages (the prefill watches the UK register of licensed sponsors, which updates every working day).
- Stock and availability: "sold out" → "in stock" alerts with
watchFor. - Jobs, events, changelogs: be told when a careers page, an event page or a changelog gets a new entry.
- AI agents: a "has this page changed and how?" tool (see below).
How it works
- First run: each page is fetched, its text is saved as the baseline → row with
status: "new". - Every next run (schedule it hourly / daily in Apify): the page is fetched again and compared.
- Every checked page gets a row:
status: "changed"with the diff, or"unchanged". Changes are also sent to your webhook. TurnincludeUnchangedoff to get a pure change feed (only new, changed and error rows).
Input
| Field | Description |
|---|---|
pages | URLs or objects {"url", "selector", "label", "ignoreSelectors", "watchFor", "priceSelector", "trackPrice"}; per-page settings override the global ones |
urls | Simple alternative: a plain list of URLs |
selector | Global CSS selector to watch (empty = whole page) |
ignoreSelectors | Elements removed before comparing |
watchFor | Keywords / phrases (case-insensitive) |
trackPrice, priceSelector | Price tracking |
notifyOn | anyChange (default) or keywordsOrPrice |
minChangePercent | Ignore edits touching fewer lines than this % |
ignoreDynamicContent, ignoreDates, ignorePatterns | Noise filters |
webhookUrl, webhookOnEveryRun | POST a JSON summary when something changed |
stateKey | Monitor name; snapshots go to the named store website-change-monitor-<stateKey> |
includeUnchanged | Default on; off = only new / changed / error rows |
includeSnapshotText | Add the full normalised text to each row |
maxItems, maxConcurrency, requestTimeoutSecs, proxyConfiguration | Advanced |
{"pages": [{"url": "https://www.gov.uk/government/publications/register-of-licensed-sponsors-workers", "selector": "main", "label": "UK sponsor register"},{"url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", "selector": ".product_main", "trackPrice": true}],"watchFor": ["sold out", "Worker"],"minChangePercent": 0,"webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ","stateKey": "my-monitor"}
Output
One row per checked page (and one free row per error). The Changes and Price & keyword alerts tables are in the Output tab. Real result (shortened):
{"url": "https://www.gov.uk/government/publications/register-of-licensed-sponsors-workers","label": "UK sponsors","selector": "main","title": "Register of licensed sponsors: workers - GOV.UK","status": "changed","changed": true,"checkedAt": "2026-10-27T10:38:39Z","previousCheckAt": "2026-10-27T10:38:00Z","changeRatio": 0.0002,"addedCount": 2,"removedCount": 0,"addedLines": ["27 October 2026", "Show all updates"],"removedLines": [],"diff": "@@ -9,2 +9,4 @@\n Last updated:\n+27 October 2026\n+Show all updates\n 27 October 2026","price": null,"previousPrice": null,"keywordsFound": {"Worker": 25},"keywordsAppeared": [],"keywordsDisappeared": [],"charged": true,"error": null}
A price change looks like "price": 51.77, "previousPrice": 55.0, "priceChange": -3.23, "priceChangePercent": -5.87, "currency": "GBP".
status values: new (first check, baseline saved), changed, minor-change (changed, but below your threshold), unchanged, error. With includeUnchanged off, only new, changed and error rows are written. The run summary (counts, changed URLs, webhook status) is in the OUTPUT record of the default key-value store.
Webhook payload
{"event": "website-change-monitor.run-finished", "text": "Website Change Monitor: 1 of 4 pages changed\n- https://...: 0.02% changed, price 55.0 -> 51.77","content": "...same text (Discord)...", "runId": "...", "datasetUrl": "https://api.apify.com/v2/datasets/.../items?clean=true","pagesChecked": 4, "changedCount": 1, "changes": [{"url": "...", "changeRatio": 0.0002, "price": 51.77, "previousPrice": 55.0, "addedLines": ["..."], "removedLines": []}]}
text makes Slack incoming webhooks work as-is, content does the same for Discord.
Pricing (pay per event)
| Event | Price |
|---|---|
| Page checked (fetched and compared, changed or not) | $0.0005 |
| Change detected (extra, only when a page changed) | $0.002 |
| Errors, blocked pages, robots.txt-disallowed pages, invalid input | free |
Watching 20 pages once a day for a month = 600 checks = $0.30, plus $0.002 per real change.
| Actor (Oct 2026, public Store prices) | Price |
|---|---|
| This Actor | $0.0005 per check + $0.002 per change |
| ryanclinton/website-change-monitor | $0.10 per site (free tier) down to $0.018 |
| kondasviktor (page monitor) | $0.0025 per page |
| mrlarryjohnson (change monitor) | $0.002 per URL |
| muhammad-bilal/web-drift-detector | $0.0006 + $0.0002 per page |
Use with AI agents / Apify MCP
Add the Actor as a tool through the Apify MCP server (gazidev/website-change-monitor). An agent can call it with {"pages": [{"url": "...", "selector": "..."}], "stateKey": "agent-watch"} and read status, addedLines, removedLines and priceChange to answer "what changed on this page since last time?". The API works the same: POST https://api.apify.com/v2/acts/gazidev~website-change-monitor/run-sync-get-dataset-items.
FAQ
How do I run it every hour / day? Create a task with your pages, then add a Schedule in Apify Console. Each run compares with the previous one through the stateKey store.
How do I reset a monitor? Use a new stateKey, or delete the named key-value store website-change-monitor-<stateKey> in Storage.
Does it work on JavaScript-only pages? No, it uses plain HTTP (that keeps it cheap). If the text you want is rendered in the browser, the row says the selector matched nothing or the page has no readable text, and you are not charged.
Which sites are not supported? Social networks and marketplaces whose terms forbid automated access (LinkedIn, Facebook, Instagram, TikTok, X, Amazon, eBay, Google...) are refused. Pages disallowed by robots.txt are skipped. You are responsible for having the right to monitor the pages you add.
Why was a page reported as changed when nothing visible changed? Some sites print counters or rotating content. Add the element to ignoreSelectors, add a regex to ignorePatterns, or set minChangePercent.
Is the change percentage the share of text changed? It is (added + removed lines) / (old + new lines).