Website Change Monitor — Learns What to Ignore avatar

Website Change Monitor — Learns What to Ignore

Pricing

from $120.00 / 1,000 real change detecteds

Go to Apify Store
Website Change Monitor — Learns What to Ignore

Website Change Monitor — Learns What to Ignore

Website change monitor that learns which parts of a page are noise — clocks, counters, A/B tests — and never alerts or bills you for them.

Pricing

from $120.00 / 1,000 real change detecteds

Rating

0.0

(0)

Developer

Kevin Baldassari

Kevin Baldassari

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a month ago

Last modified

Share

Every website change monitor can tell you a page changed. The hard part is telling you when it matters. Pages carry clocks, view counters, "posted 3 hours ago", rotating testimonials and A/B variants — and a monitor that diffs raw content fires on all of them. You get an alert channel nobody reads, and under pay-per-event pricing, a bill for every false alarm. The usual fix makes it your problem: declare the noisy parts up front with ignore patterns or CSS selectors, which requires knowing on day one exactly which parts will turn out to be noisy.

This Actor learns it instead. It watches how each region of your page behaves across runs, works out which ones change on their own, and stops reporting them — automatically, per page, with no configuration. You are never billed for a change it suppressed, and the learning period itself is free.

What it does

  • Monitor any website for content changes — give it a URL, put it on a schedule, get told when something real happens.
  • Automatically ignores timestamps, counters and rotating content — no ignore rules to write, no CSS selectors to hunt down.
  • Detects word-level changes, so a price moving from $29 to $39 is reported as those two words, not as an entire paragraph replaced.
  • Tracks changes to pricing pages, terms of service, competitor sites and documentation with a signed webhook per confirmed change.
  • Filters A/B tests and rotating content by optionally requiring a change to survive several consecutive checks.
  • Never charges for noise, baselines, unchanged pages or failed fetches.

Who it's for

  • Competitive intelligence and product teams — know the hour a rival changes their pricing page, not the week.
  • Legal, compliance and procurement — get told when a supplier quietly edits their terms of service or SLA.
  • SEO and content teams — catch silent edits to title tags, canonical URLs and on-page copy across a site.
  • Developers and integrators — watch an API changelog or docs page and fire a webhook into your own automation.

How it works

  1. Add your URLs. A plain list is enough. Everything else has a working default.
  2. Put it on a schedule. Save your input as a Task, then Task → Schedules → Create schedule. Daily suits most pages; hourly for fast-moving ones. The Actor does not schedule itself.
  3. Get told only when something real changes. Confirmed changes land in the dataset and fire your webhook. Noise does not.

The first few runs

The first run on a URL records a baseline — there is nothing to compare against yet, so nothing is reported and nothing is charged.

The next few comparisons are the learning window. During it the Actor reports everything it sees, including noise, because it cannot yet tell the two apart. Those runs are free. By default it has made up its mind after three comparisons, and from then on the noisy regions go quiet.

You can watch this happen in the output: volatileSlots counts the noisy regions it has identified, and learningComplete flips to true when its map is trusted.

Input

{
"urls": [
{ "url": "https://example.com/pricing", "label": "Competitor pricing" },
{ "url": "https://example.com/terms", "label": "Terms of service" }
],
"mode": "text",
"webhookUrl": "https://hooks.example.com/website-changed"
}
FieldTypeDefaultWhat it does
urlsarrayPages to watch. Plain strings, or objects with url, label and an optional per-page selector.
modestringtexttext compares visible text. selector compares one CSS selector. html compares raw markup.
selectorstringRequired when mode is selector, e.g. .pricing-table.
ignoreSelectorsarray[]Elements removed before comparing. Optional — skips the learning period for regions you already know are noisy.
ignorePatternsarray[]Regexes blanked before comparing, e.g. Last updated: .*.
learningRunsinteger3Comparisons observed before a region can be judged as noise. These are free.
volatilityThresholdnumber0.6How often a region must change to count as noise.
minChangedWordsinteger1Changes smaller than this are treated as noise.
confirmRunsinteger1Raise to require a change to survive N consecutive checks. Filters A/B tests.
webhookUrlstringPOST fired per confirmed change.
webhookSecretstringSigns each POST so your endpoint can verify it.
stateStoreNamestringwebsite-change-stateWhere snapshots live. Schedules sharing memory must share this name.
includeUnchangedbooleanfalseAlso write a row for quiet checks, for a full audit trail.

Output

One dataset row per check. A confirmed change looks like this:

{
"url": "https://example.com/pricing",
"label": "Competitor pricing",
"changeType": "changed",
"changed": true,
"charged": true,
"similarity": 0.9231,
"changedPercent": 7.69,
"addedText": ["The Pro plan costs $39 per month."],
"removedText": ["The Pro plan costs $29 per month."],
"wordsAdded": 1,
"wordsRemoved": 1,
"noiseLinesMasked": 2,
"suppressedSegments": 1,
"volatileSlots": 2,
"learningComplete": true,
"httpStatus": 200,
"responseTimeMs": 412,
"timesChanged": 3,
"checkedAt": "2026-08-07T09:00:04.881Z"
}

changeType is one of baseline, unchanged, changed, noise-only, pending or error. charged tells you plainly whether that row cost you anything. noiseLinesMasked and suppressedSegments are the regions that were ignored — the alerts you did not get and did not pay for.

Use cases

Monitor a competitor's pricing page for changes

Point it at every rival's pricing page on a daily schedule. Those pages are full of noise — live chat widgets, "X people are viewing this", rotating customer logos — which is exactly what gets suppressed. When a plan price genuinely moves, you get the words that changed.

Track terms of service and SLA updates

Suppliers change terms quietly, and the "last updated" date is often the only visible sign — and is itself noise on many pages. Watch the terms URL with confirmRuns: 2 so a staging deploy does not alert you, and route the webhook where legal or procurement will actually see it.

Watch API documentation and changelogs for breaking changes

Docs pages are usually server-rendered and stable, which makes them ideal targets. Use mode: "selector" on the main content to skip navigation and version pickers, and get a word-level diff of the endpoint you depend on.

Detect silent SEO and on-page content edits

Run in html mode against key landing pages to catch changes to meta tags, canonical URLs and structured data that visible-text monitoring would miss.

Pricing

Pay-per-event. Checking is nearly free; you pay when the Actor hands you something worth knowing.

EventPriceFires
actor-start$0.005Once per run
page-checked$0.0005Per page successfully checked
change-detected$0.25Per confirmed real change, after learning

Worked example — 10 pages, checked daily for a month: 30 runs × $0.005 = $0.15, plus 300 checks × $0.0005 = $0.15, plus, say, 12 genuine changes × $0.25 = $3.00. About $3.30 for the month.

50 pages, daily: roughly $11 a month. 100 pages, hourly: roughly $120 a month.

Volume discounts apply automatically on higher Apify plans.

You are not charged for: the first-run baseline · any change reported during the learning window · anything suppressed as noise · unchanged pages · failed fetches, timeouts and 404s · changes withheld because you hit your own spending limit.

That last one matters: if your cap is reached mid-run, the undelivered changes are held back from the stored baseline too, so the next run reports them again instead of losing them.

Limitations

Stated plainly, because finding out later is worse:

  • No JavaScript rendering. Raw HTML only. If a page builds itself in the browser the Actor says so in jsWarning rather than silently monitoring an empty shell — monitor a server-rendered page or an API endpoint instead.
  • No authentication. Public pages only.
  • No visual monitoring. It compares content, not screenshots or layout.
  • Learning needs runs, not time. A page checked weekly takes three weeks to settle.
  • A wholesale redesign re-baselines the page and learning restarts.

FAQ

Why not just diff the page myself?

The diffing is the easy part. What costs weeks is everything around it: recognising that "23 people viewing" is noise but the price line is not, keeping snapshots alive between scheduled runs, not re-reporting a whole page when a site briefly returns a partial response, and not alerting on an A/B test that flips back tomorrow.

How is this different from other change monitors on the store?

Others detect changes and ask you to declare the noise up front. This one learns it per page and never bills you for it. It also diffs at word level rather than line level.

Will it wake me up for a timestamp?

Only during the free learning window, and only until it has seen the timestamp move a few times. After that it goes quiet on it permanently — unless the region genuinely settles down, in which case it starts listening again.

What if a site is temporarily down?

The check is reported as an error and the stored baseline is left completely untouched. When the site comes back, the next run compares against the last good content — not against nothing — so you do not get a false "the whole page changed" alert.

How do I verify the webhook is really from this Actor?

Set webhookSecret. Each POST carries x-wcm-timestamp and x-wcm-signature, where the signature is sha256= followed by an HMAC-SHA256 over <timestamp>.<body> using your secret. Compare with a constant-time equality check, and reject timestamps older than a few minutes.

Can I monitor different sets of pages independently?

Yes. Give each watchlist its own stateStoreName. Snapshots and learned noise are kept per store, so the lists never interfere.

Support

Open an issue on the Issues tab. Response within one working day.