Website Change Monitor — Page Diff & Change Alerts avatar

Website Change Monitor — Page Diff & Change Alerts

Pricing

from $0.88 / 1,000 page checks

Go to Apify Store
Website Change Monitor — Page Diff & Change Alerts

Website Change Monitor — Page Diff & Change Alerts

Monitor any web page for content changes between runs. Each check hashes the page (or a CSS-selected part of it), compares it with the previous snapshot, and returns a line-level diff on change. Optional JavaScript rendering and webhook alerts.

Pricing

from $0.88 / 1,000 page checks

Rating

0.0

(0)

Developer

SIÁN OÜ

SIÁN OÜ

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Website Change Monitor — Track Page Content Changes 🔄

SIÁN Agency Store Store-Google SERP Scraper-1AE392 Store-Google News Scraper-1AE392 Store-Reddit Scraper-FF4500

🎉 Line-level diffs on every page change — $1 per 1,000 checks

For marketers, compliance teams and anyone who needs to know the day a page moved

🔎 What is the Website Change Monitor — and when should you use it?

The Website Change Monitor turns any public web page, watched for content changes between runs, with a line-level diff on every change into clean, structured rows you can filter, export and feed straight into a spreadsheet, database or AI agent. No account, no portal API key, no browser automation to maintain.

Use it when you need: one row per checked page: status (first check, unchanged, changed), the content hash pair, and on change a short line-level diff with before/after snippets. Scope any page to a CSS selector so layout noise stays out of the results. Turn on JavaScript rendering for pages that build themselves in the browser. Point the change-alert webhook at n8n, Zapier, Make, Slack or your own endpoint, and every change pings you the moment a run sees it.

Use something else when: the change you care about is somewhere other than one page's content. Use Google SERP Scraper for where a keyword RANKS over time, rather than what one page says. Use Google News Scraper for new coverage of a topic across the news, rather than edits to one known page. Use Reddit Scraper for new posts and comments across Reddit, rather than one page's content. This actor watches page CONTENT as text. Pages behind a login, private and internal addresses, and purely visual (pixel-level) changes are out of scope. Pages that need JavaScript are covered by turning rendering on.

🤖 Use with AI agents

Already connected to the Apify MCP server? Just ask for this Actor by name: sian.agency/website-change-monitor

Your agent can pay for its own runs. This Actor is eligible for agentic payments, so an agent can discover it, run it and settle the bill over x402 (USDC on Base) or Skyfire — without an Apify account or API token of its own. Billing is the same either way: per successful row, never for errors.

Otherwise copy this prompt into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

I want to know when a web page changed and what exactly moved using the Apify Actor `sian.agency/website-change-monitor`.
Use it when I need: one row per checked page: status (first check, unchanged, changed), the content hash pair, and on change a short line-level diff with before/after snippets. Scope any page to a CSS selector so layout noise stays out of the results. Turn on JavaScript rendering for pages that build themselves in the browser. Point the change-alert webhook at n8n, Zapier, Make, Slack or your own endpoint, and every change pings you the moment a run sees it.
Don't use it when: the change you care about is somewhere other than one page's content — use google-serp-scraper or google-news-scraper or reddit-scraper instead.
How to call it: give `url` one page, or `bulkUrls` many, or `requestsFromUrl` a link to a text file of pages. Narrow any page to one part with `selector` (a CSS selector like .price or #availability). Set `renderJs` true for pages that load their content in the browser. Put an https endpoint in `notifyWebhookUrl` and every changed page posts a JSON event to it. The first run of a page stores its baseline and reports first_check; every later run reports unchanged or changed.
Start with this input:
{
"url": "https://example.com/pricing",
"selector": ".price",
"renderJs": false
}
Ask me which pages to watch (one URL, a list, or a text-file link), whether any of them need JavaScript rendering, and where to send change alerts, then run the Actor and summarise the results as a table.

Things you can ask your agent for:

  • Watch these five competitor pricing pages and show me a diff of anything that changed since yesterday.
  • Check our terms-of-service page every morning and tell me exactly which lines were edited.
  • Monitor this product page with rendering on and alert my webhook the moment the availability text changes.

Machine-readable API, MCP config and OpenAPI definition for this Actor are published at apify.com/sian.agency/website-change-monitor.md.

📋 Overview

Website Change Monitor watches any public web page and tells you exactly what changed since the last look. Every run fetches each page on your list, strips the volatile chrome nobody cares about, and hashes the visible text. That hash is compared with the snapshot from the previous run. One row per page, every run.

Why teams pick it:

  • A diff, not a boolean: every changed page ships a line-level excerpt — minus lines removed, plus lines added — with before/after snippets in the row. You can act without re-opening the page.
  • 🎯 Watch only what matters: scope any page to a CSS selector (a price block, a spec table, one heading). A nav redesign never buries the change you actually care about.
  • 🆕 An honest first run: the first check stores the baseline and reports first_check. Nothing is ever "changed" before you have something to compare against.
  • ⚙️ JavaScript pages, solved: pages that build themselves in the browser get a real rendering pass before hashing, so skeleton HTML stops producing empty checks.
  • 🔔 Alerts that reach you: every changed page can POST a JSON event to your webhook — n8n, Zapier, Make, Slack or your own endpoint — on any schedule you set.
  • 💰 Priced for watchlists: $1 per 1,000 checks. The most popular paid alternative on the Store charges $47 for the same thousand.

✨ Features

  • 🔄 One row per page, every run — first_check, unchanged or changed, so a first run is never a wasted run
  • 🧾 Line-level diff excerpts — up to 20 changed lines per page, plus counts of lines added and removed
  • 📝 Before/after snippets — both text states ride in the row, ready to paste into a ticket or an audit trail
  • 🎯 CSS selector scoping — check .price, #availability or table.specs instead of the whole page
  • 🧹 Noise-proof normalization — scripts, styles, navigation, headers, footers and comments are ignored before hashing, so layout tweaks and asset churn do not fire false alarms
  • 📄 Watchlists at any size — one URL, a bulk list, or a link to a text file of pages; duplicates removed automatically
  • ⚙️ JavaScript rendering — for pages whose content only exists after scripts run
  • 🔔 Change-alert webhook — one JSON event per changed page, best-effort by design: a down endpoint never fails your run
  • 🗓️ Schedule-ready — snapshots persist between runs, so an hourly or daily schedule just works from run two
  • 📤 Every export you need — JSON, CSV, Excel and the API, straight from the Apify dataset

🚀 Quick Start

Open the actor, paste a page URL, click Start. You get one row: first_check, with the page's baseline stored. Run it again and the same page reads unchanged — change something on it (or point at a page that moves, like a leaderboard) and the row flips to changed with its diff.

curl -X POST https://api.apify.com/v2/acts/sian.agency~website-change-monitor/runs?token=YOUR_TOKEN \
-d '{"url": "https://example.com/pricing"}'

🛠️ Getting Started (3 Simple Steps)

Step 1: Add your pages

Paste one URL into the single-page field, or drop a list into bulk URLs, or link a text file with one URL per line.

Step 2: Scope the check (optional)

Add a CSS selector to watch one part of the page. Turn on JavaScript rendering only for pages that load their content in the browser.

Step 3: Schedule it

Set a schedule (hourly, daily, weekly) and, if you want push alerts, paste a webhook URL. Every changed page posts to it automatically.

That's it! From the second run on, you'll have:

  • A row per page telling you first_check, unchanged or changed
  • A line-level diff and before/after snippets for every change
  • An optional webhook event the moment a change is detected

📥 Input Configuration

FieldTypeRequiredDescription
urlstringNoOne page to watch — used when the bulk list and list file are empty (any public http(s) address)
bulkUrlsarrayNoMany pages in one run — paste a list or upload a text file
requestsFromUrlstringNoLink to a plain-text file with one page URL per line
selectorstringNoCSS selector to watch one part of each page (empty = whole page)
renderJsbooleanNoLoad pages in a browser session before checking (for JS-built pages)
notifyWebhookUrlstringNoWebhook that receives a JSON event for every changed page

Single page:

{
"url": "https://example.com/pricing",
"selector": ".price"
}

Bulk watchlist:

{
"bulkUrls": [
"https://competitor-a.com/pricing",
"https://competitor-b.com/pricing",
"https://example.com/terms"
],
"notifyWebhookUrl": "https://hook.eu2.make.com/your-flow"
}

📤 Output

One dataset row per checked page, 14 fields including:

FieldTypeDescription
urlstringThe page that was checked
statusstringfirst_check · unchanged · changed · error
diffExcerptarrayLine-level diff lines (changed pages only)
currentSnippetstringThe watched text as of this run
previousSnippetstringThe watched text before the change
selectorstringThe CSS selector in force, if any
changedAtstringWhen the change was detected
checkedAtstringWhen this check ran
currentHashstringSHA-256 of the current normalized text
previousHashstringSHA-256 of the previous run's text
checkCountintegerHow many times this page has been checked
httpStatusintegerHTTP status the page returned
renderJsbooleanWhether this check rendered JavaScript
errorMessagestringPlain-language reason and fix, error rows only

Example (changed page):

{
"url": "https://example.com/pricing",
"selector": ".price",
"status": "changed",
"currentHash": "162b81548a8db0ab…",
"previousHash": "866c59903724e0dc…",
"changedAt": "2026-08-31T02:43:44.953Z",
"diffExcerpt": ["- $129.00", "+ $119.00"],
"addedLines": 1,
"removedLines": 1,
"previousSnippet": "$129.00",
"currentSnippet": "$119.00",
"checkedAt": "2026-08-31T02:43:44.953Z",
"checkCount": 6,
"httpStatus": 200,
"renderJs": false
}

💼 Use Cases & Examples

1. Competitor Price Monitoring

A pricing analyst watches rivals' pricing pages without visiting them.

Input: The competitor pricing URLs in bulkUrls, selector scoped to the price block. Output: A row per page per run, with the diff the moment a price moves. Use: Catch undercutting and flash-sale changes the day they happen, not at the next quarterly review. "Competitor price monitoring" is one of the highest-value searches in this category — advertisers pay over $30 a click for it.

2. Compliance & Policy Watch

A privacy officer tracks terms of service and policy pages for edits.

Input: The policy URLs, run on a daily schedule. Output: Line-level diffs with before/after snippets — audit-ready evidence of what moved and when it was caught. Use: Prove when a clause changed, without screenshotting pages by hand every morning.

3. Publishing & Content QA

A web team verifies its own pages after each release.

Input: The page list from a text file (requestsFromUrl), selector scoped to the content area. Output: Changed rows for anything the deploy touched. Use: A release checklist that runs itself — stray debug text or a broken localization shows up as a diff, not as a customer email.

4. Inventory & Availability Alerts

A reseller watches product pages that never got a feed.

Input: Product URLs with renderJs on for pages built in the browser. Output: Status rows per page, plus a webhook event when the availability text changes. Use: Restock and sell-out signals routed straight into n8n, Zapier, Make or Slack.

5. Changelog & Release Tracking

A developer relations team watches vendors' changelog pages.

Input: The changelog URLs, scheduled hourly. Output: The added lines (new entries) delivered as a diff. Use: Blog-worthy releases surface the hour they publish — no vendor newsletter required.

6. Defacement & Unauthorized Edit Spot-Checks

A site owner keeps an eye on the public pages of a small site.

Input: The site's key public pages, scoped to their main content selectors. Output: A changed row the moment text appears that nobody approved. Use: A lightweight early warning alongside — never instead of — proper security tooling.

🔗 Integration Examples

JavaScript/Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('sian.agency/website-change-monitor').call({
url: 'https://example.com/pricing',
selector: '.price'
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('sian.agency/website-change-monitor').call(
run_input={'url': 'https://example.com/pricing', 'selector': '.price'}
)
for item in client.dataset(run['defaultDatasetId']).iterate_items():
print(item)

cURL

curl -X POST 'https://api.apify.com/v2/acts/sian.agency~website-change-monitor/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com/pricing"}'

Automation Workflows (n8n / Zapier / Make)

  1. Trigger: Apify schedule (daily, hourly) fires the run
  2. Fetch: Each run checks every page on your list
  3. Alert: A changed page POSTs a JSON event to your notifyWebhookUrl
  4. Action: Your workflow routes it — Slack message, email digest, ticket, sheet row

The webhook payload carries the url, selector, diff excerpt, both hashes and the checked time — everything a downstream step needs to decide and act.

📊 Performance & Pricing

FREE Tier (Try It Now)

  • 5 pages per run — every feature included, diffs and rendering alike
  • No credit card required
  • Perfect for a first baseline and a weekly check of a handful of pages
  • Unlimited pages per run — watchlists of any size
  • Pay per page actually checked: a page that errors costs you nothing
  • JavaScript-rendered checks cost $3 per 1,000 (the $1 check plus a $2 rendering surcharge) because they take real browser time

💰 $1 per 1,000 checks — the most popular paid alternative in this category charges $47 for the same thousand.

🔗 View current pricing

❓ Frequently Asked Questions

Q: How many pages can I check? A: FREE tier: 5 pages per run. PAID tier: unlimited, and only successful checks are billed.

Q: What does the first run report? A: first_check. The first run stores each page's baseline snapshot, so nothing shows as changed before there is something to compare with. From run two you get unchanged or changed.

Q: Does it work with pages behind a login? A: No. Only publicly accessible pages are supported, and private or internal addresses are rejected up front.

Q: A page shows almost no text on first check. Why? A: It probably builds its content with JavaScript. Turn on "Run JavaScript before checking" and run it again.

Q: Why did a page report changed when the content looks the same? A: Rotating text — timestamps, session banners, token strings — can shift between runs. Scope the check to a CSS selector covering the part you care about; that removes most false alarms.

Q: What output formats are available? A: JSON, CSV, Excel — export directly from the Apify dataset, or pull via the API.

Q: Is this legal? A: The actor reads publicly available pages only. See our legal section below.

Q: How long does a check take? A: A plain check is typically under two seconds per page. Rendered checks take longer because a browser session loads the page first.

🐞 Troubleshooting

A page returns "403 — it may block automated access"

  • Retry later; some sites throttle bursts of requests
  • Space your checks further apart, or check fewer pages per run
  • Try JavaScript rendering — some pages only open after scripts run

"The CSS selector matched nothing on this page"

  • Right-click the element in your browser, choose Inspect, and copy a class or id that exists in the HTML
  • The selector must match on the page you are checking — selectors are per-page, not global

Everything reports first_check again

  • The snapshots live with the actor run history; if you deleted the actor's storage or switched accounts, baselines start over
  • Run twice in a row — the second run should read unchanged

"The page did not answer in time"

  • Run again with fewer pages; the site is slowing the run down
  • If it repeats, the site may be blocking automated visitors — try rendering on

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the legality of web scraping.

🤝 Support

Telegram Support

Join our active support community


Built by SIÁN Agency | More Tools