Website Change Monitor & Page Diff Tracker avatar

Website Change Monitor & Page Diff Tracker

Pricing

Pay per usage

Go to Apify Store
Website Change Monitor & Page Diff Tracker

Website Change Monitor & Page Diff Tracker

Monitor website, SEO, pricing, landing page, documentation, and AI/RAG content changes. Track persistent snapshots, detect significant changes, and export structured page diffs for Apify Schedules, APIs, webhooks, and automations.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

João Victor

João Victor

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

0

Monthly active users

a day ago

Last modified

Share

Monitor website, SEO, pricing, landing page, documentation, changelog, and AI/RAG source changes — then export clean structured diffs for automations.

Apify Actor Website monitoring SEO API ready

This Actor turns any public URL list into a scheduled website change monitoring API with persistent snapshots, noise filtering, and machine-readable diffs. It is built for teams that need automation-ready data — not just visual screenshots.

⚡ At a glance

MonitorDetectAutomate
Pricing pagesText, HTML, metadata, headings, linksApify Schedules
SEO pagesSignificant changes and diff textWebhooks
Landing pagesAdded/removed contentMake, n8n, Zapier
DocumentationAI/RAG source driftSlack, email, dashboards

🎯 Best for

AudienceWhy they use it
SEO agenciesMonitor titles, descriptions, headings, landing pages, client sites, and competitor pages.
SaaS founders & growth teamsTrack competitor pricing, homepage positioning, feature pages, docs, and changelogs.
AI/RAG teamsKnow when source docs, help centers, FAQs, or knowledge-base pages changed.
Marketing teamsWatch CTAs, offers, testimonials, campaign pages, and product messaging.
Automation buildersFeed clean JSON diffs into alerts, dashboards, BI pipelines, and AI agents.

What this Actor does

  1. Takes a list of public URLs.
  2. Fetches each page with fast HTTP mode by default.
  3. Optionally renders JavaScript-heavy pages with Playwright browser mode.
  4. Extracts visible text, HTML, or metadata.
  5. Removes noisy page parts such as scripts, navbars, footers, cookie banners, dates, or custom regex patterns.
  6. Stores a persistent baseline snapshot in a named key-value store.
  7. Compares future runs against the previous snapshot.
  8. Outputs structured dataset rows with FIRST_SEEN, UNCHANGED, CHANGED, or ERROR status.
  9. Reports diff text, severity, change ratio, headings, link count, hashes, timestamps, and snapshot keys.
  10. Works with Apify Schedules, Tasks, API, webhooks, and integrations.

🧭 Typical workflow

StepActionOutput
1Run with your URL listFIRST_SEEN baseline snapshots
2Schedule the same inputrecurring checks
3Detect changed pagesCHANGED, severity, changeRatio
4Send results to your workflowwebhook, Slack, Make, n8n, Zapier, API

Why this Actor is different

Generic website monitors often create noisy alerts from cookie banners, timestamps, layout shifts, nav menus, ads, analytics widgets, and formatting changes. This Actor is designed for commercial automation workflows:

  • Persistent snapshots across scheduled runs.
  • Structured JSON output for API users, BI, automations, and AI agents.
  • CSS selector targeting to monitor only main, article, .pricing, #content, or any page region.
  • Noise filtering with excluded selectors, date/number handling, whitespace normalization, and regex ignores.
  • SEO-friendly modes for visible text, stricter HTML comparison, or metadata-only monitoring.
  • Cost-aware defaults: HTTP mode, proxy disabled, browser disabled, bounded concurrency, response-size caps.
  • Marketplace-safe security: private/internal URLs are blocked by default to reduce SSRF risk.

Use cases

Use caseWhat to monitorRecommended settings
Competitor pricing monitorPricing pages, plan tables, discount textcontentSelector: "main", ignoreNumbers: false, emitMode: "CHANGES_ONLY"
SEO content monitorLanding pages, service pages, blog pagesextractionMode: "VISIBLE_TEXT", ignoreDates: true
SEO metadata trackerTitles, descriptions, headings, linksextractionMode: "METADATA"
Landing page CTA monitorHeadlines, buttons, offers, hero textcontentSelector: "main", low threshold such as 0.03
Documentation monitorDocs, developer portals, changelogscontentSelector: "main", emitMode: "SIGNIFICANT_ONLY"
AI/RAG freshness monitorKnowledge-base pages, FAQs, help centersscheduled task + webhook when pages change
Agency alert workflowClient/competitor URL setsseparate snapshotStoreName per client
Compliance/evidence workflowPublic policy pages, terms, docsenable saveHtmlSnapshot if raw HTML evidence is needed

Quick start

  1. Open the Actor on Apify.
  2. Add one or more URLs in Pages to monitor.
  3. Keep snapshotStoreName stable across runs.
  4. Run once to create the baseline. Results will be FIRST_SEEN.
  5. Run again later, or create a Schedule. Results will be UNCHANGED or CHANGED.
  6. Use emitMode = CHANGES_ONLY or SIGNIFICANT_ONLY for alerts.

Minimal input:

{
"startUrls": [{ "url": "https://example.com" }],
"snapshotStoreName": "my-website-monitor",
"emitMode": "ALL"
}

Tutorial: create a daily competitor pricing monitor

Step 1 — Add competitor URLs

{
"startUrls": [
{ "url": "https://competitor-one.com/pricing" },
{ "url": "https://competitor-two.com/pricing" },
{ "url": "https://competitor-three.com/pricing" }
],
"snapshotStoreName": "competitor-pricing-daily-monitor",
"contentSelector": "main",
"extractionMode": "VISIBLE_TEXT",
"ignoreDates": true,
"ignoreNumbers": false,
"significantChangeThreshold": 0.03,
"emitMode": "CHANGES_ONLY",
"maxConcurrency": 3,
"useBrowser": false,
"proxy": { "useApifyProxy": false }
}

Step 2 — Run once to create the baseline

The first run returns FIRST_SEEN because no previous snapshot exists yet.

Step 3 — Save as an Apify Task

Create a Task after verifying the input. Use a different snapshotStoreName for each client, competitor group, or project.

Step 4 — Schedule the Task

Create an Apify Schedule, for example once per day. For high-priority pricing pages, daily monitoring is usually enough. For docs and SEO content, daily or weekly monitoring usually works well.

Step 5 — Add notifications or workflow automation

Connect the Actor or Task to:

  • Apify webhooks;
  • Slack or Discord alerts;
  • Make, Zapier, or n8n workflows;
  • Google Sheets or Airtable dashboards;
  • internal BI pipelines;
  • AI agents that summarize changes.

Example inputs

Example 1 — SEO metadata monitor

{
"startUrls": [
{ "url": "https://example.com" },
{ "url": "https://example.com/pricing" },
{ "url": "https://example.com/blog" }
],
"snapshotStoreName": "seo-metadata-monitor",
"extractionMode": "METADATA",
"emitMode": "ALL",
"significantChangeThreshold": 0.01
}

Example 2 — Documentation and changelog monitor

{
"startUrls": [
{ "url": "https://docs.example.com/introduction" },
{ "url": "https://docs.example.com/api-reference" },
{ "url": "https://example.com/changelog" }
],
"snapshotStoreName": "docs-rag-source-monitor",
"contentSelector": "main",
"excludeSelectors": ["nav", "footer", ".pagination", ".last-updated"],
"extractionMode": "VISIBLE_TEXT",
"ignoreDates": true,
"significantChangeThreshold": 0.05,
"emitMode": "SIGNIFICANT_ONLY"
}

Example 3 — Landing page CTA monitor

{
"startUrls": [
{ "url": "https://competitor.com" },
{ "url": "https://competitor.com/product" }
],
"snapshotStoreName": "landing-page-cta-monitor",
"contentSelector": "main",
"excludeSelectors": ["script", "style", "nav", "footer", ".cookie", ".announcement-bar"],
"ignoreDates": true,
"ignoreNumbers": false,
"significantChangeThreshold": 0.03,
"emitMode": "CHANGES_ONLY"
}

Example 4 — Dry run without updating the stored baseline

{
"startUrls": [{ "url": "https://example.com/pricing" }],
"snapshotStoreName": "production-pricing-monitor",
"updateSnapshots": false,
"emitMode": "ALL"
}

Input reference

FieldTypeDefaultDescription
startUrlsarrayhttps://example.comPages to monitor.
snapshotStoreNamestringwebsite-change-monitor-snapshotsNamed key-value store for previous snapshots. Use a different store per project/client.
maxItemsinteger10Maximum pages processed in one run.
maxConcurrencyinteger3Maximum URLs processed in parallel. Keep low for browser mode to control memory/cost.
extractionModeenumVISIBLE_TEXTWhat to compare: VISIBLE_TEXT, HTML, or METADATA.
contentSelectorstringemptyOptional CSS selector for the exact page area to monitor, e.g. main, .pricing, article.
excludeSelectorsstring[]common noise selectorsElements removed before comparison.
ignoreRegexesstring[][]Regex patterns removed from content before comparison.
ignoreWhitespacebooleantrueNormalize whitespace.
ignoreCasebooleanfalseNormalize casing.
ignoreNumbersbooleanfalseNormalize numbers. Keep disabled for pricing pages.
ignoreDatesbooleantrueNormalize common date formats.
significantChangeThresholdnumber0.05Minimum changed-content ratio to mark a change significant.
emitModeenumALLALL, CHANGES_ONLY, or SIGNIFICANT_ONLY.
saveHtmlSnapshotbooleanfalseStore raw HTML evidence in the snapshot store. Increases storage usage.
updateSnapshotsbooleantrueDisable for dry-run comparisons.
maxDiffCharactersinteger2000Maximum length of addedText / removedText.
useBrowserbooleanfalseUse Playwright for JavaScript-rendered pages. Costs more than HTTP mode.
maxRetriesinteger2Retry attempts for transient fetch errors. Applies to HTTP and browser mode.
requestTimeoutSecsinteger20Fetch/browser timeout per page.
maxContentBytesinteger2000000Maximum bytes read per page before stopping to protect memory/storage cost.
allowPrivateUrlsbooleanfalseAllow localhost/private/internal IPs. Keep disabled for public runs.
proxyobjectdisabledOptional Apify Proxy configuration. Most public pages do not need proxy.

Output

The Actor writes results to the default dataset. Each row represents one monitored URL.

Dataset item example — first run

{
"url": "https://example.com",
"finalUrl": "https://example.com",
"title": "Example Domain",
"statusCode": 200,
"changeType": "FIRST_SEEN",
"severity": "HIGH",
"isSignificant": true,
"changeRatio": 1,
"previousHash": null,
"currentHash": "4a415f5252c741fbf3b4e11711552f78d0a5c3c0abaeefacedae0fc0807b63db",
"previousFetchedAt": null,
"currentFetchedAt": "2026-07-05T18:44:29.407Z",
"addedText": "Example Domain This domain is for use in documentation examples...",
"removedText": null,
"headings": ["Example Domain"],
"linksCount": 1,
"contentLength": 125,
"snapshotKey": "SNAPSHOT_...",
"htmlSnapshotKey": null,
"source": "http",
"error": null
}

Dataset item example — changed page

{
"url": "https://competitor.com/pricing",
"finalUrl": "https://competitor.com/pricing",
"title": "Pricing | Competitor",
"statusCode": 200,
"changeType": "CHANGED",
"severity": "HIGH",
"isSignificant": true,
"changeRatio": 0.31,
"previousHash": "old-hash",
"currentHash": "new-hash",
"previousFetchedAt": "2026-07-04T08:00:00.000Z",
"currentFetchedAt": "2026-07-05T08:00:00.000Z",
"addedText": "Pro plan $39 per month AI add-on included",
"removedText": "Pro plan $29 per month",
"headings": ["Pricing", "Pro"],
"linksCount": 12,
"contentLength": 4210,
"snapshotKey": "SNAPSHOT_...",
"htmlSnapshotKey": "HTML_...",
"source": "http",
"error": null
}

Run summary

A summary is stored in the default key-value store under OUTPUT:

{
"processed": 10,
"emitted": 3,
"changed": 2,
"significant": 1,
"unchanged": 7,
"firstSeen": 1,
"failed": 0,
"snapshotStoreName": "competitor-pricing-monitor",
"startedAt": "2026-07-05T08:00:00.000Z",
"finishedAt": "2026-07-05T08:00:12.000Z"
}

Understanding results

FieldMeaning
FIRST_SEENNo previous snapshot existed. The current page is stored as the baseline.
UNCHANGEDCurrent normalized content hash equals the previous hash.
CHANGEDContent changed. Check changeRatio, severity, addedText, and removedText.
ERRORThe page failed after retries. Error details are in error.
SeverityApproximate ratioMeaning
NONE0No content change.
LOW< 5%Small change. Often harmless.
MEDIUM5–25%Meaningful content change.
HIGH> 25%Large change or first snapshot.

API usage

Run asynchronously:

curl -X POST \
"https://api.apify.com/v2/actors/joaosbp~website-change-monitor-seo-ai/runs" \
-H "Authorization: Bearer YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startUrls": [{ "url": "https://example.com" }],
"snapshotStoreName": "example-monitor",
"emitMode": "ALL"
}'

Run synchronously and get dataset items:

curl -X POST \
"https://api.apify.com/v2/actors/joaosbp~website-change-monitor-seo-ai/run-sync-get-dataset-items?format=json" \
-H "Authorization: Bearer YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startUrls": [{ "url": "https://example.com" }],
"snapshotStoreName": "example-monitor"
}'

FAQ

Is this a visual screenshot monitor?

No. It is a structured content and metadata change monitor. It focuses on text, HTML, metadata, hashes, and diffs that are useful for APIs, alerts, automation, SEO, and AI workflows.

Does it crawl an entire website automatically?

No. You provide the URLs to monitor. This keeps runs predictable, cheaper, and easier to schedule. If you need whole-site discovery, combine it with a sitemap extractor or a future sitemap-monitor Actor.

Why is the first run marked FIRST_SEEN?

The first run creates the baseline snapshot. Run the same task again later with the same snapshotStoreName to detect UNCHANGED or CHANGED.

How do I reduce noisy alerts?

Use contentSelector to focus on the important part of the page and excludeSelectors to remove navbars, footers, cookie banners, widgets, ads, or timestamps. Keep ignoreDates = true for pages with last-updated dates.

Can I monitor pricing pages?

Yes. Keep ignoreNumbers = false, use contentSelector = "main", and set emitMode = "CHANGES_ONLY". This is one of the primary use cases.

Can I monitor SEO titles and descriptions?

Yes. Use extractionMode = "METADATA" to focus on title, description, headings, and links.

Can I monitor JavaScript-heavy pages?

Yes, enable useBrowser = true. Browser mode costs more than HTTP mode, so use it only when the page content is not available in the initial HTML.

Do I need proxies?

Usually no. Proxy is disabled by default to keep costs low. Enable Apify Proxy only for pages that block normal HTTP requests or require proxy routing.

Are private/internal URLs allowed?

No, they are blocked by default for safety. Advanced users can set allowPrivateUrls = true only for trusted private monitoring jobs.

Does the Actor store raw HTML?

Only if saveHtmlSnapshot = true. By default it stores normalized snapshots and compact diffs to control storage costs.

Can I send alerts to Slack, email, Make, Zapier, or n8n?

Yes. Use Apify webhooks or run the Actor as a scheduled Task, then send dataset items or the OUTPUT summary to your automation tool.

What happens on errors?

One bad URL does not fail the entire run. The Actor emits an ERROR dataset item for that URL and continues with the rest.

Pricing and cost guidance

Recommended Apify monetization model: Pay Per Event after enough production usage data is collected.

A real remote test on 8 public pricing/docs pages with HTTP mode and proxy disabled succeeded at roughly $0.000996 total platform cost after tuning, or about $0.000125 per successful page in that sample.

Suggested future paid events:

EventSuggested priceWhen to charge
page-checked$0.003–$0.006successful non-error page check
change-detected$0.03–$0.10page changed above hash baseline
significant-change-detected$0.05–$0.20change ratio passes threshold

Do not charge for per-URL errors. Keep browser/proxy modes as advanced options because they increase platform cost.

Limitations

  • The Actor monitors the URLs you provide; it does not discover all pages on a website by default.
  • JavaScript-heavy websites may require useBrowser = true, which costs more.
  • Some websites block bots or require login; this Actor is designed for public pages.
  • Text diff is optimized for concise monitoring signals, not full Git-style line-by-line review.
  • Private/internal URLs are blocked by default for safety.
  • First run always produces FIRST_SEEN because there is no baseline yet.

Best practices

  • Use contentSelector for noisy layouts.
  • Use separate snapshotStoreName values per client, project, competitor set, or environment.
  • Keep ignoreNumbers = false for pricing and metrics pages.
  • Use ignoreDates = true for blogs, docs, and changelogs with timestamps.
  • Use emitMode = CHANGES_ONLY or SIGNIFICANT_ONLY for alerting workflows.
  • Use updateSnapshots = false when testing thresholds against an existing baseline.
  • Start with HTTP mode. Enable browser/proxy only when needed.

Changelog

See CHANGELOG.md for release history.

Search terms

Website change monitor, website monitoring, page change detector, page diff tracker, SEO monitor, SEO change tracker, competitor monitoring, competitor pricing monitor, pricing page monitor, landing page monitor, content change detection, documentation monitor, changelog monitor, help center monitor, AI RAG monitor, website alerts, web page monitoring API, Apify website monitor, scheduled web monitoring, structured diff API.

Support

If a page produces noisy changes, configure contentSelector, excludeSelectors, and ignoreRegexes before increasing the threshold. For pricing pages, keep numbers enabled. For documentation pages, usually monitor the main element and exclude navigation, footer, pagination, and last-updated widgets.