Web Page Change Monitor avatar

Web Page Change Monitor

Pricing

from $3.00 / 1,000 page checkeds

Go to Apify Store
Web Page Change Monitor

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

junipr

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 hours ago

Last modified

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.

FeatureThis ActorVisualpingChangeTowerApify Built-in
CSS selector targetingYesYesYesPartial
Structured diff outputFull line-by-lineVisual onlyVisual onlyBoolean only
JS renderingYes (Playwright)YesYesNo
Webhook notificationsYesPaid plansPaid plansNo
Batch monitoringYes (100s per run)1 per monitor1 per monitorYes
Persistent snapshotsNamed KV Store6–12 months30 daysNone
Diff formatsunified, JSON, side-by-sideNoneNoneNone
Change threshold filterYesSensitivity sliderSensitivity sliderNo
Pricing$2/1,000 checks$10–$150/mo$10+/moCompute-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:

  1. Open the actor and go to Input
  2. Set pages to your target URLs (JSON array of objects with url and optional label)
  3. Optionally set a selector to monitor only a specific section (e.g., ".pricing-table")
  4. Set snapshotStore to a consistent name (e.g., "my-monitor") so snapshots persist across runs
  5. Add a webhookUrl to receive instant notifications on change
  6. Go to SchedulesCreate 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

ParameterTypeDefaultDescription
pagesarrayHacker News demoURLs to monitor with optional label, selector, removeSelectors
maxPagesPerRuninteger100Cap on pages checked per run
renderJsbooleanfalseUse Playwright for JavaScript-rendered pages
waitForNetworkIdlebooleanfalseWait for network quiet before extracting (Playwright only)
changeThresholdnumber0.01Minimum fraction changed to trigger detection (0 = any change)
ignoreWhitespacebooleantrueIgnore whitespace-only differences
ignoreCaseChangesbooleanfalseIgnore capitalization differences
ignoreNumbersbooleanfalseIgnore changes to numeric values (filters counters, timestamps)
ignorePatternsstring[][]Regex patterns for text to ignore (e.g., ISO dates)
contentTypestringtextWhat to compare: text, html, or attributes
diffFormatstringunifiedOutput format: unified, sideBySide, or json
diffContextLinesinteger3Unchanged context lines shown around each change
includeFullSnapshotbooleanfalseInclude full page text in output
webhookUrlstringURL to POST change notifications to
webhookHeadersobject{}Custom headers for webhook (auth tokens, etc.)
notifyOnNoChangebooleanfalseSend heartbeat notification when nothing changed
notifyOnErrorbooleantrueNotify when a page fails to load
snapshotStorestringchange-monitor-snapshotsNamed KV store for persistent snapshots
maxSnapshotHistoryinteger10Snapshot versions to retain per URL
maxRetriesinteger3Retry attempts on page load failure
requestTimeoutinteger30000Per-page timeout in milliseconds
maxConcurrencyinteger10Simultaneous 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.99
Free 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.

ScenarioChecks/MonthEstimated 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.