Web Page Change Monitor
Pricing
from $3.00 / 1,000 page checkeds
Web Page Change Monitor
Monitor pages for content changes with visual diff output. Compare against stored snapshots. CSS selectors for specific sections. Track prices, competitors, compliance. Multi-URL with configurable schedules.
Pricing
from $3.00 / 1,000 page checkeds
Rating
0.0
(0)
Developer

junipr
Actor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 hours ago
Last modified
Categories
Share
Introduction
Web Page Change Monitor detects content changes on any web page and tells you exactly what changed, when, and by how much. On each run, the actor fetches your target pages, extracts the content you care about (full page or a specific CSS selector), compares it against the last stored snapshot, and produces a structured diff showing precisely what was added, removed, or modified.
Primary use cases include e-commerce price monitoring, competitor content tracking, legal and compliance teams auditing terms of service, SEO professionals watching SERP features, government and regulatory page monitoring, and DevOps teams watching status pages or documentation. Unlike visual screenshot-based tools, this actor gives you machine-readable, line-by-line diffs you can pipe into any downstream workflow.
Key differentiators: CSS selector targeting lets you focus on exactly the content that matters (not noisy ads and nav bars), three structured diff formats (unified, side-by-side, and JSON) serve both human review and programmatic consumption, webhook notifications push changes to Slack, Discord, or any endpoint the moment they are detected, and persistent snapshots in a named Key-Value Store survive across Apify runs so your comparison baseline is never lost.
Why Use This Actor
Most existing web change monitors fall short in predictable ways. Visualping and ChangeTower offer visual pixel-diffs but no structured output — you can see something changed but can't process it programmatically. The built-in Apify Web Page Monitor returns only a boolean "changed: true" with no detail. Both Visualping and ChangeTower charge $10–$150/month subscriptions regardless of how many pages you actually check.
| Feature | This Actor | Visualping | ChangeTower | Apify Built-in |
|---|---|---|---|---|
| CSS selector targeting | Yes | Yes | Yes | Partial |
| Structured diff output | Full line-by-line | Visual only | Visual only | Boolean only |
| JS rendering | Yes (Playwright) | Yes | Yes | No |
| Webhook notifications | Yes | Paid plans | Paid plans | No |
| Batch monitoring | Yes (100s per run) | 1 per monitor | 1 per monitor | Yes |
| Persistent snapshots | Named KV Store | 6–12 months | 30 days | None |
| Diff formats | unified, JSON, side-by-side | None | None | None |
| Change threshold filter | Yes | Sensitivity slider | Sensitivity slider | No |
| Pricing | $2/1,000 checks | $10–$150/mo | $10+/mo | Compute-time |
At $2 per 1,000 checks, monitoring 50 pages daily for a month costs $3.00. The equivalent Visualping plan starts at $10/month before you even consider batch checking.
How to Use
Zero-config: Click Try for free — the actor runs immediately on Hacker News as a demo. No configuration required. The first run stores a baseline snapshot; the second run detects any changes since.
Basic setup:
- Open the actor and go to Input
- Set
pagesto your target URLs (JSON array of objects withurland optionallabel) - Optionally set a
selectorto monitor only a specific section (e.g.,".pricing-table") - Set
snapshotStoreto a consistent name (e.g.,"my-monitor") so snapshots persist across runs - Add a
webhookUrlto receive instant notifications on change - Go to Schedules → Create schedule and set your desired frequency (hourly, daily, etc.)
Minimal example input:
{"pages": [{ "url": "https://example.com/pricing", "label": "Pricing Page", "selector": ".pricing-table" }],"snapshotStore": "my-monitor","webhookUrl": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"}
Input Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
pages | array | Hacker News demo | URLs to monitor with optional label, selector, removeSelectors |
maxPagesPerRun | integer | 100 | Cap on pages checked per run |
renderJs | boolean | false | Use Playwright for JavaScript-rendered pages |
waitForNetworkIdle | boolean | false | Wait for network quiet before extracting (Playwright only) |
changeThreshold | number | 0.01 | Minimum fraction changed to trigger detection (0 = any change) |
ignoreWhitespace | boolean | true | Ignore whitespace-only differences |
ignoreCaseChanges | boolean | false | Ignore capitalization differences |
ignoreNumbers | boolean | false | Ignore changes to numeric values (filters counters, timestamps) |
ignorePatterns | string[] | [] | Regex patterns for text to ignore (e.g., ISO dates) |
contentType | string | text | What to compare: text, html, or attributes |
diffFormat | string | unified | Output format: unified, sideBySide, or json |
diffContextLines | integer | 3 | Unchanged context lines shown around each change |
includeFullSnapshot | boolean | false | Include full page text in output |
webhookUrl | string | — | URL to POST change notifications to |
webhookHeaders | object | {} | Custom headers for webhook (auth tokens, etc.) |
notifyOnNoChange | boolean | false | Send heartbeat notification when nothing changed |
notifyOnError | boolean | true | Notify when a page fails to load |
snapshotStore | string | change-monitor-snapshots | Named KV store for persistent snapshots |
maxSnapshotHistory | integer | 10 | Snapshot versions to retain per URL |
maxRetries | integer | 3 | Retry attempts on page load failure |
requestTimeout | integer | 30000 | Per-page timeout in milliseconds |
maxConcurrency | integer | 10 | Simultaneous page requests |
Common configurations:
Monitor competitor pricing with selector and timestamp suppression:
{"pages": [{ "url": "https://competitor.com/pricing", "selector": ".price", "removeSelectors": [".ad", ".cookie-banner"] }],"ignorePatterns": ["\\d{4}-\\d{2}-\\d{2}"],"changeThreshold": 0.001}
JavaScript-rendered SPA with Playwright:
{"pages": [{ "url": "https://app.example.com/dashboard", "waitForSelector": ".data-loaded" }],"renderJs": true,"waitForNetworkIdle": true}
Slack webhook integration:
{"webhookUrl": "https://hooks.slack.com/services/T00/B00/XXXX","webhookHeaders": {},"notifyOnNoChange": false}
Output Format
Each dataset item contains one page result. Key fields:
status: changed | unchanged | new (first run) | error
Unified diff example (diffFormat: "unified"):
--- Previous (2026-03-10T12:00:00Z)+++ Current (2026-03-11T12:00:00Z)@@ -15,7 +15,7 @@Regular price: $29.99-Sale price: $19.99+Sale price: $24.99Free shipping on orders over $50
JSON diff example (diffFormat: "json"):
{"changes": [{"type": "modified","lineNumber": 16,"oldValue": "Sale price: $19.99","newValue": "Sale price: $24.99","context": { "before": ["Regular price: $29.99"], "after": ["Free shipping"] }}]}
Webhook payload (sent to your webhookUrl on change):
{"actorId": "...","runId": "...","timestamp": "2026-03-11T12:00:00Z","changedPages": [{ "url": "...", "label": "...", "changePercentage": 0.03, "diffPreview": "..." }],"summary": { "totalChecked": 5, "totalChanged": 1, "totalUnchanged": 4, "totalErrors": 0 }}
Tips and Advanced Usage
Reducing false positives: Use removeSelectors to strip dynamic sections like .ad-banner, #live-chat, #cookie-notice. Add ignorePatterns for date strings ("\\d{1,2}/\\d{1,2}/\\d{4}"), view counts, or session tokens. Set changeThreshold: 0.05 to ignore changes smaller than 5% of the page.
Monitoring JavaScript-rendered pages: Set renderJs: true. For pages that lazy-load content, add "waitForSelector": ".content-loaded" to the page config, or set waitForNetworkIdle: true. Note that JS rendering uses more memory — allocate at least 2048 MB.
Slack/Discord/Teams notifications: Slack incoming webhooks accept the same JSON POST format this actor uses. For Discord, set the URL to https://discord.com/api/webhooks/ID/TOKEN. For Teams, use a Power Automate HTTP trigger URL. Add auth tokens in webhookHeaders.
Long-term monitoring: Give your snapshotStore a stable, descriptive name (e.g., "pricing-monitor-prod"). The KV store persists indefinitely in your Apify account. Use maxSnapshotHistory: 30 to keep a 30-version history per URL for audit trails.
Batch monitoring: Put all your URLs in the pages array. The actor checks all of them concurrently (up to maxConcurrency at once). 100 static pages typically complete in under 60 seconds.
Pricing
This actor uses Pay-Per-Event pricing at $2.00 per 1,000 page checks. You are only charged for successfully checked pages — errors, CAPTCHA blocks, and empty selector matches are free.
| Scenario | Checks/Month | Estimated Cost |
|---|---|---|
| One-time check (10 pages) | 10 | $0.02 |
| Daily monitoring (50 pages) | 1,500 | $3.00 |
| Hourly monitoring (20 pages) | 14,400 | $28.80 |
| Enterprise (500 pages, daily) | 15,000 | $30.00 |
| High-frequency (5 pages, every 5 min) | 43,200 | $86.40 |
Compare: Visualping charges $10–$150/month for 1–5,000 monitors. ChangeTower starts at $10/month. This actor scales linearly — pay only for what you check.
FAQ
How does it detect changes on JavaScript-rendered pages?
Set renderJs: true in the input. The actor then uses a Playwright browser (Chromium) to fully render the page — executing JavaScript, waiting for DOM updates, and optionally waiting for a specific selector or network idle. The extracted content after rendering is compared to the previous snapshot exactly as with static pages.
Can I monitor only a specific section of a page?
Yes. Add a selector field to each page config: { "url": "https://example.com", "selector": ".pricing-table" }. Only the text (or HTML) within that selector is compared. Changes outside the selector are completely ignored. You can also add removeSelectors to strip sub-sections within your target area.
How do I reduce false positives from ads and dynamic content?
Three approaches work together: (1) Use removeSelectors to strip known dynamic elements like .ad-banner, #cookie-notice, .live-chat. (2) Use ignorePatterns with a regex for content that changes frequently but isn't meaningful, such as timestamps or view counters. (3) Increase changeThreshold so only substantial changes (e.g., 5%+ of content) trigger detection.
How long are snapshots stored?
Snapshots are stored in an Apify Key-Value Store in your account. KV stores persist until you delete them — there is no automatic expiry. The maxSnapshotHistory setting controls how many historical versions are kept per URL (default: 10). The most recent version is always the comparison baseline for the next run.
Can I set up Slack notifications?
Yes. Create a Slack Incoming Webhook at https://api.slack.com/apps and paste the webhook URL into the webhookUrl field. The actor will POST a JSON payload to Slack whenever a change is detected. For a formatted Slack message, you can use a middleware like Make (Integromat) or Zapier to transform the raw JSON into Slack Block Kit format.
What happens if the page is temporarily down?
The actor retries up to maxRetries times (default: 3) before marking the page as status: "error". Critically, it does not update the snapshot when a page fails — the last good snapshot is preserved as the comparison baseline. This means a temporary outage will not corrupt your monitoring history or trigger a false positive on the next successful check.
How often can I schedule checks?
Apify Scheduler supports any cron expression, so checks can run as frequently as every minute. Practical minimums depend on the number of pages and whether JavaScript rendering is used. For static pages with renderJs: false, checking every 5 minutes for 10 pages is well within normal resource use. For Playwright-rendered pages, every 15–30 minutes is more typical.
How is a "page check" defined for pricing?
A billable event is emitted when: (1) the page loads successfully (HTTP 2xx), (2) content is extracted from the page, and (3) a comparison is completed (or a first-run baseline is stored). Pages that fail to load, return CAPTCHA blocks, or match no elements with the provided CSS selector are not billed. Webhook delivery and snapshot storage are included in the page check charge at no extra cost.