Website Change Monitor — Page Diff, CSS Selector & Webhook avatar

Website Change Monitor — Page Diff, CSS Selector & Webhook

Pricing

from $2.00 / 1,000 page checkeds

Go to Apify Store
Website Change Monitor — Page Diff, CSS Selector & Webhook

Website Change Monitor — Page Diff, CSS Selector & Webhook

Monitor web pages for changes on a schedule: compares each page with the previous run (readable text, HTML or CSS-selector elements), ignores timestamps and noise, returns a unified diff and posts changes to Slack, Discord, Zapier, Make or n8n. A Visualping alternative at $2 per 1,000 checks.

Pricing

from $2.00 / 1,000 page checkeds

Rating

0.0

(0)

Developer

ActorForge

ActorForge

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

19 hours ago

Last modified

Security

Limited permissions

Share

Monitor web pages for changes on a schedule: compares each page with the previous run (readable text, HTML or CSS-selector elements), ignores timestamps and noise, returns a unified diff and posts changes to Slack, Discord, Zapier, Make or n8n. A Visualping alternative at $2 per 1,000 checks.

Get told when a web page changes, without checking it yourself. This website change monitor fetches each of your URLs, compares it with what it saw on the previous run, and returns one row per page: baseline (first check), unchanged, changed (with a unified diff, added/removed line counts and percent changed) or error. Use it for page change detection on competitor pricing pages, product and stock pages, terms of service and privacy policies, job boards, government notices, documentation and changelogs. It is a Visualping alternative (and ChangeTower / Distill alternative) that you own: results land in an Apify dataset and API, and changes can be posted to Slack, Discord, Zapier, Make, n8n or your own webhook.

Three ways to compare. text (default) compares the readable page as Markdown, without menus, header, footer, cookie banners or scripts, so redesigns and ad rotations don't trigger alerts. html compares the markup itself (scripts and styles excluded) to catch changed links, images and attributes. selector watches only the elements you name with CSS selectors, e.g. .price or #pricing-table: the cheapest way to monitor competitor prices or one section of a busy page.

No false alarms from noise. Dates, clocks and "5 minutes ago" are ignored by default. Add your own ignore patterns (regular expressions such as Visitors: \d+) and ignore selectors (.ad, #related), and set a minimum change size so a one-character edit doesn't page anyone (small edits add up until they cross the threshold). Whitespace and re-indentation are ignored.

Built for schedules. Snapshots live in a named key-value store, change-monitor-<monitorName>, that persists between runs, so every scheduled run compares against the last one. Use one monitor name per watch list. Fetch failures and robots.txt blocks are reported as free error rows and never overwrite the saved snapshot, so one bad response can't hide a change.

How to schedule it (daily, hourly or weekly checks)

  1. Run the actor once with your URLs and a monitorName (e.g. competitor-prices). That run saves the baselines.
  2. In Apify Console, open the actor and click Save as a new task so the input is stored, or keep using the actor's input.
  3. Go to Schedules → Create new schedule, choose how often (e.g. every day at 08:00 with the cron 0 8 * * *, or hourly 0 * * * *), and under Add pick the task (or this actor with the same input).
  4. Add a webhookUrl (a Slack or Discord incoming webhook, or a Zapier / Make / n8n catch hook) to get a message only when something changed. You can also attach an Apify integration or webhook to the task's Run succeeded event and read the run's dataset.

Each scheduled run returns rows for every URL (or only the changes, with outputOnlyChanges) plus an OUTPUT summary record listing the changed URLs. Via the API, start the task and read .../runs/last/dataset/items?status=SUCCEEDED.

Webhook payload

Slack and Discord get a readable message with the changed lines. Any other URL gets JSON: {"event": "changes-detected", "monitorName", "runId", "datasetUrl", "checkedAt", "counts": {"checked", "baseline", "unchanged", "changed", "errors"}, "changes": [{"url", "title", "addedLines", "removedLines", "percentChanged", "diff"}], "errors": [{"url", "error"}]}. One POST per run; by default only when at least one page changed.

What data does it return?

Every run outputs clean, schema-validated rows like these:

urlstatusstatusCodechangeSummarydiffpreviousCheckedAtcheckedAt
https://competitor.example/pricingchanged200{"addedLines":1,"removedLines":1,"changedChars":36,"percentChanged":1.12}@@ -12,5 +12,5 @@ ... -Pro: $49 per month +Pro: $59 per month2026-10-18T08:00:04Z2026-10-19T08:00:03Z
https://www.iana.org/help/example-domainsunchanged200{"addedLines":0,"removedLines":0,"changedChars":0,"percentChanged":0}2026-10-18T08:00:04Z2026-10-19T08:00:03Z
https://shop.example/new-productbaseline2002026-10-19T08:00:05Z
https://down.example/termserror5032026-10-18T08:00:06Z2026-10-19T08:00:09Z

How much does it cost?

Transparent pay-per-event pricing — you only pay for what you get, and the actor always respects your run budget: set a maximum total charge and it stops cleanly at the cap instead of overrunning.

EventPriceChargedWorked example
page-checked$0.002per URL fetched and compared (baseline, unchanged or changed)50 pages checked daily for a month = 1,500 checks = $3.00
change-detected$0.005extra, per URL whose content changed since the previous run20 changes in that month = $0.10
apify-actor-start$0.00005per run per GB of memory (platform start fee)One run at up to 1 GB = $0.00005 (charged as one event)

Input options

FieldTypeRequiredDefaultDescription
urlsarrayyes—Pages to watch, one per line (up to 5,000; duplicates removed). Each run compares every page with what it saw on the previous run of the same monitor. Bare domains like example.com/pricing work too.
monitorNamestringno"default"Snapshots are saved in a named key-value store called change-monitor-<name>, which persists between runs. Use one name per schedule (e.g. competitor-prices, legal-pages) so separate watch lists keep separate baselines. Letters, numbers and dashes.
modestringno"text"Text catches what a reader would notice and ignores layout changes. HTML also catches changes to links, images and markup (scripts and styles are excluded). Selector watches only the parts you name in CSS selectors, e.g. a price or a table.
cssSelectorarrayno—For mode "selector": CSS selectors of the parts to watch, e.g. .price, #pricing-table, main h2. The text of every matching element is compared. A page where no selector matches is reported as an error (free) and its snapshot is kept.
ignoreSelectorsarrayno—CSS selectors for parts of the page to remove before comparing, like ads, a related-posts box, a live chat widget or a visitor counter. Example: .ad, #related, .view-count.
ignorePatternsarrayno—Regular expressions for text to strip before comparing (case-insensitive; ^ and $ match line starts/ends). Example: Visitors: \d+ or ^Ad #\d+.*$. Use /pattern/flags to choose flags yourself.
ignoreDatesAndTimesbooleannotrueStrip clocks, dates and relative times (2026-10-19, 10:42 am, Oct 19 2026, 19/10/2026, 5 minutes ago) before comparing, so a page whose only change is its timestamp is not reported as changed. Prices and counts are not touched.
ignoreWhitespacebooleannotrueCollapse spaces and tabs and drop blank lines before comparing, so re-indented or re-flowed pages are not reported as changed.
minChangeCharsintegerno0Report a page as changed only when at least this many characters were added plus removed. Smaller changes are reported as unchanged and the old baseline is kept, so small edits add up until they cross the threshold. 0 = any change counts.
includeDiffbooleannotrueAdd a unified diff (lines starting with - were removed, + were added, with 2 lines of context) to each changed row, capped at about 20 KB. Added/removed line counts are always included.
outputOnlyChangesbooleannofalseLeave unchanged pages out of the dataset (they are still checked and their snapshot is refreshed). Baselines, changes and errors are always output.
webhookUrlstringno—Optional. At the end of the run, POST a summary of the changes here. Slack and Discord incoming-webhook URLs get a readable message with the changed lines; any other URL (Zapier, Make, n8n, your server) gets JSON with counts, each change (URL, title, line counts, diff) and errors. Private and internal addresses are blocked.
webhookOnlyOnChangesbooleannotrueOn by default: no message on runs where nothing changed. Turn off to get a summary after every run (useful as a heartbeat).
respectRobotsTxtbooleannotrueSkip pages that the site's robots.txt disallows for crawlers (reported as a free error row). Turn off only for sites you own or are allowed to monitor.
maxUrlsintegerno500Safety cap on how many URLs one run checks; extra URLs are skipped.
requestTimeoutSecsintegerno30How long to wait for each page before reporting it as an error (free). Transient failures (timeouts, 429, 5xx) are retried twice.
maxConcurrencyintegerno10How many pages to check at once. At most 2 pages per site are fetched at the same time.
proxyConfigurationobjectno{"useApifyProxy":false}Off by default (direct requests from Apify's datacenter). Use Apify Proxy (datacenter groups) for sites that rate-limit or block a single IP, or your own proxy URLs. Residential and SERP proxy groups are not supported: pages are fetched with plain HTTP, and bot-protected sites usually need a browser anyway.

Limits & honest notes

  • You pay only for pages that were fetched and compared. Errors are free: timeouts, HTTP 4xx/5xx, robots.txt blocks, unsupported file types (images, PDFs, binaries), a selector that matches nothing, blocked internal addresses. Error rows never overwrite the saved snapshot.
  • The first run of a monitor (or the first time a URL is seen) is a baseline: only page-checked is charged and there is nothing to diff yet. Changing the mode, selectors or ignore rules also starts a new baseline instead of reporting a false change.
  • Pages are fetched with plain HTTP (no browser), which keeps checks cheap and fast. Content that only appears after JavaScript runs is not seen; such pages are reported as an error (no text content) or compare only their static HTML. Sites with CAPTCHAs or strong bot protection are out of scope.
  • Up to 5,000 URLs per run (maxUrls, default 500), 10 in parallel by default (up to 50), at most 2 at a time per site. Pages larger than 10 MB are skipped; compared content is capped at 1 million characters and the diff at about 20 KB per page (counts stay exact).
  • Snapshots are kept per monitor name in your own Apify account (named key-value store change-monitor-
  • robots.txt is respected by default. If a site's robots.txt can't be fetched (HTTP 5xx or a network error, after one retry), that site's URLs get a free error row for the run (RFC 9309) and their saved snapshots are kept. Requests to localhost, private networks and cloud-metadata addresses are blocked for pages and webhooks, including after redirects; webhooks do not follow redirects.
  • Proxy: off by default; Apify datacenter proxy and your own proxy URLs are supported, residential and SERP groups are not.
  • Respects your run budget: set a maximum total charge and the run stops cleanly at the cap. Pages not checked keep their snapshot, so the next run still reports their changes.

Changelog

  • 2026-10-19 — Initial release: text, HTML and CSS-selector comparison, unified diffs, ignore patterns/selectors, date and time masking, minimum change size, named per-monitor snapshots for schedules, Slack/Discord/JSON webhook, robots.txt and SSRF protection, optional proxy.

Built and maintained by ActorForge. Reliability first: every actor in the portfolio is monitored by an automated nightly self-test, and breakages are typically fixed the same day.