Website Change Monitor - Page Change Detection & Alerts avatar

Website Change Monitor - Page Change Detection & Alerts

Pricing

from $1.60 / 1,000 page checks

Go to Apify Store
Website Change Monitor - Page Change Detection & Alerts

Website Change Monitor - Page Change Detection & Alerts

Website change tracker and content monitor: text and price changes, CSS selector per URL, keyword triggers, noise filters, screenshots, email, Slack, Discord, webhook alerts, AI summary. $2/1k checks.

Pricing

from $1.60 / 1,000 page checks

Rating

0.0

(0)

Developer

Yukai Lin

Yukai Lin

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

What does Website Change Monitor do?

It watches web pages and tells you what changed since the last check: which text was added and which was removed. Run it on a schedule (hourly, daily, weekly) and get the changes in the dataset, by e-mail, in Slack or Discord, or pushed to a webhook (Zapier, Make, n8n, your own app). It accepts Content Checker inputs (url, contentSelector, sendNotificationTo and more) and the input fields of other change monitors (startUrls, kvStoreName, slackWebhookUrl...), takes before and after screenshots, and can watch thousands of pages in one run.

Quick start

  1. Paste the URLs you want to watch (one per line) and give the monitor a name.
  2. Run it once: this saves the baseline ("status": "first-check"), so the first run reports no changes yet.
  3. Add a daily schedule in Apify Console → Schedules (Create → pick this Actor and your input). Every scheduled run then reports what changed and sends your alerts.
  • 🔁 Remembers the previous version of every page between runs, so each run is a real comparison (or compare with a locked baseline you approved)
  • 🎯 Watch only what matters: a CSS selector for the whole run or per page (#pricing, .product-price, main), with an optional fallback to the whole page when the element disappears
  • 🔇 Less noise: ignore dates, times, "5 minutes ago" and view counters with one switch, add your own ignore patterns, and set a minimum size for a change to count
  • 🔑 Keyword triggers: alert only when a changed line mentions "price", "out of stock" or any words you choose
  • 🔢 Number changes: price and percentage changes are extracted ($19 → $29)
  • 🤖 Optional AI summary: one or two sentences on what changed, plus a significance score from 1 (trivial) to 5 (critical)
  • 📬 Alerts: e-mail (via Apify's send-mail Actor), Slack and Discord messages, or JSON webhooks with an optional HMAC-SHA256 signature
  • 📸 Before and after screenshots (optional): a screenshot of the page, or of just the watched element, on every alerted change, linked in results and alerts. Cookie and consent banners are always removed before the screenshot (verified on IKEA, The Guardian and apify.com), so the images show the page, not the banner
  • 🚨 Alerts when a page keeps failing: get told when a page could not be read (or its element vanished) several runs in a row, so a monitor never fails silently
  • 🗑️ Removed pages are reported: a watched page that starts answering 404 or 410 is reported as removed and alerted once (on by default, not charged), and as restored when it comes back
  • ⚙️ No false alerts after a settings change: changing the CSS selector, ignore rules or mode saves a new baseline (reason: "settings-changed") instead of reporting the whole page as changed
  • 🌐 Works on protected and JavaScript sites: pages are read over plain HTTP first, with automatic fallback to another network and a real browser
  • 💸 $2 per 1,000 page checks, no extra fee per detected change; failed checks are free

Content Checker alternative

If you use a Content Checker-style Actor today, your input works as it is: url, contentSelector, screenshotSelector, sendNotificationTo and informOnError are accepted.

Migrate in one minute

Paste your Content Checker input into this Actor's JSON input, keep your schedule, and that's it:

{
"url": "https://www.apify.com/change-log",
"contentSelector": "article",
"screenshotSelector": "article",
"sendNotificationTo": "you@your-apify-account-email.com",
"informOnError": "true"
}

screenshotSelector turns on change screenshots of that element ($0.003 each), and informOnError: "true" alerts you from the first failed check. To watch more pages in the same run, move them into urls (one entry per page, each with its own selector and name):

{
"urls": [
{ "url": "https://www.apify.com/change-log", "userData": { "selector": "article", "name": "Apify changelog" } },
{ "url": "https://example.com/pricing", "userData": { "selector": "#plans", "name": "Competitor pricing" } }
],
"monitorName": "my-watchlist",
"screenshotOnChange": true,
"alertOnError": true,
"notifyEmail": "you@your-apify-account-email.com"
}
Content Checker fieldThis ActorNotes
urlurl or urlsurls takes many pages in one run (up to 5,000)
contentSelectorcontentSelector or cssSelectorAlso per page: {"url": "...", "userData": {"selector": "#price", "name": "Pricing"}}
sendNotificationTosendNotificationTo or notifyEmailSent with apify/send-mail, which delivers to your Apify account's e-mail address
screenshotSelectorscreenshotSelector, or screenshotOnChange (uses the watched selector)Screenshot after the change plus the previous one ("before"), in results and alerts
informOnErrorinformOnError or alertOnError + errorThresholdAlert after N failed runs in a row (Content Checker's informOnError = after the first), plus a "works again" note
(none)webhookUrl, webhookSecretSlack, Discord or JSON, optionally signed
(none)watchKeywords, minChangedLines, minChangeRatio, ignoreCommonNoiseFewer false alarms
(none)aiSummaryWhat changed and how much it matters

What stays the same for you: a schedule in Apify Console runs the check, and each run compares with the last one. What you gain: many pages per run, per-page selectors, automatic browser fallback, noise filters, and failed checks are not charged.

Switching from another website change monitor

Using another change monitor from the Apify Store? Paste your existing JSON input as it is. The common field names of other monitors are accepted, and the run log lists each field that was mapped (and the few that are not used):

Their fieldRead asNotes
urls (list of URLs), startUrls ([{ "url": ... }]), wccInput.startUrlspages to watchExactly these pages are checked; linked pages are not crawled
urls with { "url", "label", "selectors": { "content", "ignore" } }per-page name and CSS selectorPer-page ignore selectors apply to all pages
kvStoreNamemonitorName
notifyOnlyChangesoutputOnlyChanges
slackWebhookUrl, alerts.webhookUrlwebhookUrlSlack gets a formatted message; with both set, both are called
ignoreNoiseignoreCommonNoise
mode: text, html or selectorautoThe visible text is compared; cssSelector watches one part of the page
baselineMode: latest / lockedrolling / locked
diff.ignorePatterns, diff.minChangePercentignorePatterns, minChangeRatio1.5 (%) becomes 0.015
maxRequestsPerCrawlmost pages checked per run
outputEmailnotifyEmailapify/send-mail delivers to your Apify account's e-mail address
cssSelector, webhookUrl, watchKeywords, ignorePatterns, ignoreSelectors, resetBaselinesame name

Not used: severity levels (minSeverity; use minChangedLines, minChangeRatio or watchKeywords), extra layers such as metadata or links (layers; the visible text is compared), sitemap discovery (list the pages), Notion and Slack connectors (use a Slack webhook URL). Paid extras are never switched on by a pasted field: set aiSummary or screenshotOnChange yourself if you want them. Your old monitor's history is not imported, so the first run saves a new baseline.

Paste your existing input

An input written for another monitor, unchanged:

{
"urls": ["https://example.com/pricing", "https://example.com/changelog"],
"mode": "text",
"cssSelector": "main",
"notifyOnlyChanges": true,
"kvStoreName": "competitors",
"slackWebhookUrl": "https://hooks.slack.com/services/...",
"watchKeywords": ["price", "plan"],
"ignoreNoise": true,
"baselineMode": "latest"
}

Here it watches the main part of both pages under the monitor name competitors, outputs only changed pages, posts changes that mention "price" or "plan" to Slack, ignores dates and counters, and compares each run with the previous one.

How the prices compare

Store prices on the Free plan, checked October 2, 2026 (see each Actor's Pricing tab for current prices):

This ActorWebsite Change Monitor & Diff TrackerCompetitor Marketing Change Monitor
Price per 1,000 page checks$2.00 ($1.60 to $1.80 on higher plans)$100 per 1,000 sites ($18 to $47 on higher plans)$3.00 ($0.002 per page + $0.001 per result)
Start fee per runnone$0.00005$0.25 per GB of memory
Failed pagesfreenot statednot stated
20 pages once a day (600 checks a month)$1.20$60at least $9.30
Screenshotsoptional, $0.003 each, before and afterno screenshot optionyes, on by default
Strong pointsmany pages per run, per-page selectors, browser fallback, removed-page alerts, signed webhookschange severity levels, SEO metadata, link and tech-stack layers, Notion and Slack connectors, sitemap discoverymarketing-page focus, screenshots

Use cases

  • Competitor monitoring: pricing pages, product catalogs, feature lists, job openings (use watchKeywords like "price" and read numericChanges)
  • Compliance & legal: terms of service, privacy policies, regulatory pages (use a locked baseline to compare with the approved version)
  • Release tracking: changelogs, download pages, documentation
  • Content watch: news pages, government notices, stock or availability pages

Product price and stock monitor (no selector)

Set watchProduct: true to compare structured product metadata instead of the page's visible text. It reads JSON-LD Product → Offer/AggregateOffer (using lowPrice for an aggregate), then product:price:amount, product:price:currency and product:availability meta tags. The dataset includes price, currency, availability (InStock or OutOfStock), and previousPrice. A first check saves the baseline; later price drops and stock flips can trigger your existing webhook or e-mail alert. For example:

{ "urlList": ["https://example.com/product"], "monitorName": "product-watch", "watchProduct": true, "priceDropPercent": 10, "webhookUrl": "https://example.com/my-webhook" }

With priceDropPercent: 10, a price drop of at least 10% from the previous check alerts; smaller drops, price increases, and layout changes do not. An InStock ↔ OutOfStock flip alerts regardless of the price threshold. The page must expose these fields in structured metadata; if it does not, the result says no-product-data (errorType: "no_product_data"), keeps the previous baseline, and is not charged. CSS selectors, JSON paths and text noise controls are ignored in this mode. Product pages disallowed by robots.txt return a free blocked row with errorType: "robots_disallowed". The product:price meta fallback uses the selected HTTP route: Actor network for direct, VM for vm, and Actor network when auto needs it. backend cannot expose raw meta tags, so use JSON-LD on that route or select another route. Each successful product check uses the existing one page-checked event; there is no product surcharge.

Price monitor for any website

Watch product prices on any online store, or a competitor's pricing page, and get an alert when a price moves or a product goes out of stock. Point a CSS selector at the product box, keep only price and stock words as keywords, and read the old and new price in numericChanges.

{
"urls": [
{ "url": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html", "userData": { "selector": ".product_main", "name": "A Light in the Attic" } },
{ "url": "https://books.toscrape.com/catalogue/tipping-the-velvet_999/index.html", "userData": { "selector": ".product_main", "name": "Tipping the Velvet" } }
],
"monitorName": "book-prices",
"watchKeywords": ["£", "out of stock"],
"ignorePatterns": ["\\(\\d+ available\\)"],
"outputOnlyChanges": true,
"webhookUrl": "https://hooks.slack.com/services/..."
}
  • selector: ".product_main" watches only the product box (title, price, stock), not the "recently viewed" or recommendations around it. On your own stores, use the element around the price, e.g. .price, #product-price or [itemprop=price] (right-click the price → Inspect to find it). One selector for all pages also works: set Only watch this part of the page (cssSelector).
  • watchKeywords makes a change significant (and alerted) only when a changed line contains a currency sign or "out of stock". Use $, € or the store's own wording ("sold out", "add to cart").
  • ignorePatterns drops the stock counter ("In stock (22 available)"), so a falling count is not an alert, while "Out of stock" still is.
  • When a price changes, the row carries numericChanges, e.g. [{ "before": "£51.77", "after": "£44.10", "context": "£44.10" }], and alerts show "£51.77 → £44.10".

Run it once to save the prices, then add a daily schedule. Each page check costs $0.002 (100 products checked daily ≈ $6 per month), whether the price changed or not.

Watch one field of a public JSON API

Many price, version and status pages are backed by a public JSON URL. Set JSON field to watch (jsonPath) to compare just that value, or set jsonPath per page in user data (it overrides the global one):

{
"urls": [
{ "url": "https://registry.npmjs.org/express/latest", "userData": { "jsonPath": "$.version", "name": "express version" } },
{ "url": "https://api.github.com/repos/nodejs/node/tags", "userData": { "jsonPath": "$[0].name", "name": "latest Node.js tag" } }
],
"monitorName": "api-fields"
}
  • Paths use object keys and array indexes only: $.price, $.items[0].price, $[0].name. Wildcards, filters and expressions are not supported.
  • Object key order does not count as a change; an object or array value is compared as a whole.
  • A successful read costs the usual $0.002 per page check. A missing field, a response that is not JSON, an invalid path, a page that robots.txt disallows or a response over 512 KiB is a free failed row, and the saved value is kept for the next run.
  • Changing the path saves a new baseline instead of reporting a change. JSON pages are read directly with an identified User-Agent; only public URLs that need no login work.

How much does it cost?

EventPrice
Page check$2.00 / 1,000 checks
AI change summary (optional)$0.005 per changed page summarized
Change screenshot (optional)$0.003 per screenshot

No start fee and no fee per detected change: the base check price is fixed, and only optional features are charged per use.

MonitorChecks per monthCost per month
1 page, every hour720$1.44
1 page, every hour, with screenshots and 10 alerted changes720 + 11 screenshots$1.47
20 pages, once a day600$1.20
100 pages, once a day3,000$6.00

With screenshots on, one screenshot is taken when the baseline is saved (or the first time a page has none) and one per alerted change; unchanged checks take no screenshot. Pages that could not be read, and pages whose CSS selector matched nothing, are not charged. E-mail alerts run apify/send-mail on your account (a few seconds of platform usage). Higher Apify plans get volume discounts (see the Pricing tab).

Content Checker itself has no Actor fee in the Apify Store; you pay Apify platform usage for its browser runs, which depends on your plan (checked September 2026). For comparison, some change monitors in the Apify Store charge $0.008 to $0.02 per detected change on top of each check, and AI change summaries elsewhere cost $0.02 to $0.06 each (checked September 2026).

Control your cost

  • Charged: each page that was read and compared ($0.002), plus screenshots ($0.003) and AI summaries ($0.005) only if you turn them on.
  • Free: pages that could not be read, removed pages (404 / 410), pages whose CSS selector matched nothing, and invalid input lines. Every row has charged: true or false, and the error text of free rows ends with "(not charged)".
  • At the start, the log and status message show the plan: number of pages × price (and the most that screenshots or AI summaries could add) = the most the run can cost, compared with your maximum charge per run (set in the run options).
  • When that maximum is reached, the run stops checking new pages. The status message says how many were not checked, SUMMARY.notProcessed lists them (count and up to 100 URLs), and the webhook and e-mail are still sent with incomplete: true and uncheckedPages, so an integration does not read "no alert" as "no changes".

How to use it

  1. Paste the pages to watch, one URL per line (example.com/pricing works too). A line that is not a URL gets its own error row (errorType: "invalid_input", not charged) and the other pages are still checked. For per-page settings, use Pages with per-page settings and add user data to a URL: {"selector": "#pricing", "name": "Competitor pricing"}.
  2. Give the monitor a name (runs with the same name compare against each other).
  3. Optional: set a CSS selector, ignore patterns, keywords, and alerts (e-mail, webhook URL).
  4. Run it once to save the baseline, then create a schedule in Apify Console (Schedules → Create, pick this Actor and your input, choose e.g. "every day at 9:00") to run it automatically.
  5. Optional: turn on Screenshot changed pages and Alert when a page keeps failing (Alerts and noise control). Alert when a page is removed is on by default.
  6. Want to check your alert setup first? Turn on Test alerts without sending (Alerts and noise control): the webhook is not called and the e-mail uses send-mail's mock mode; the result is in the SUMMARY record.

Input example

{
"urls": [
{ "url": "https://www.python.org/downloads/", "userData": { "selector": ".download-list-widget", "name": "Python releases" } },
{ "url": "https://example.com/pricing", "userData": { "selector": "#plans", "name": "Competitor pricing" } }
],
"monitorName": "competitors",
"ignoreCommonNoise": true,
"watchKeywords": ["price", "release"],
"aiSummary": true,
"outputOnlyChanges": true,
"webhookUrl": "https://hooks.slack.com/services/...",
"notifyEmail": "you@your-apify-account-email.com"
}

Output

The first run saves a baseline ("status": "first-check"). Later runs report unchanged or changed. A real changed result (September 2026, httpbin.org/uuid returns a new ID on every request):

{
"url": "https://httpbin.org/uuid",
"status": "changed",
"checkedAt": "2026-09-29T02:38:51.571Z",
"addedCount": 1,
"removedCount": 1,
"changeRatio": 0.333,
"added": ["\"uuid\": \"03c057ca-3989-4dd3-9bbe-076de0a0eb27\""],
"removed": ["\"uuid\": \"3f613ece-f6a4-4943-bfa1-d6a33a3ce95a\""],
"significant": true,
"aiSummary": "The UUID value changed from 3f613ece-f6a4-4943-bfa1-d6a33a3ce95a to 03c057ca-3989-4dd3-9bbe-076de0a0eb27",
"significance": 1,
"mode": "browser",
"via": "browser"
}

Other fields you may see:

  • significant: false with a minorReason (for example "no watched keyword in the changed lines"): reported, but no alert
  • numericChanges: [{ "before": "$19", "after": "$29", "context": "Pro plan $29/month" }]
  • noiseOnly: true on an unchanged page: only dates, times or counters differed (with Ignore dates, times and counters)
  • reorderedOnly: true on an unchanged page: the same lines only moved around, so there is nothing to show and no alert
  • Very long lines (table layouts such as Hacker News or price tables often convert to one huge line) are compared in short pieces, so added / removed show the part that changed, not a 10,000-character line
  • status: "selector-not-found": the watched element is missing (real example: {"status": "selector-not-found", "name": "Missing element", "selector": "#nope-xyz", "message": "The CSS selector \"#nope-xyz\" matched nothing on the page. ..."}); with Fall back to the whole page, the whole page is compared instead and selectorFallback: true is set
  • Locked baseline: baselineAt, driftedSince and newSinceLastRun (alerts fire only when the page differs from what the previous run saw)
  • status: "failed" with error, errorType and consecutiveFailures (not charged; the baseline is kept)
  • On first-check: watchedPreview (the first lines of the watched text) and watchedLines, so you can see whether your CSS selector picked the right part of the page. After a settings change: reason: "settings-changed"
  • status: "removed" with httpStatus (404 or 410), removedAt and significant: true the first time (not charged; the baseline is kept). When the page is back, the result carries restored: true
  • Every row has charged: true or false; successful rows also carry finalUrl and httpStatus. A line that is not a URL: { "input": "acme", "status": "invalid-input", "errorType": "invalid_input", "charged": false }
  • With Screenshot changed pages: screenshotUrl (JPEG after the change, or the baseline shot on the first check) and previousScreenshotUrl (the "before" image: the last screenshot saved for that page; with a locked baseline, the baseline's screenshot). screenshotError if the screenshot failed (not charged)

A real screenshot result (September 2026, httpbin.org/uuid with screenshots on, second run):

{
"url": "https://httpbin.org/uuid",
"status": "changed",
"addedCount": 1,
"removedCount": 1,
"added": ["\"uuid\": \"762816a2-8e92-4d9a-aa9a-05b68c05601e\""],
"removed": ["\"uuid\": \"e83ca153-a8dc-498e-b49c-80ddb4cfe18e\""],
"significant": true,
"screenshotUrl": "https://api.apify.com/v2/key-value-stores/NGtk6Pi14T1p0800F/records/shot-f5056fea96bf70021469b9ac93aae968-20260929034729491.jpg?signature=…",
"previousScreenshotUrl": "https://api.apify.com/v2/key-value-stores/NGtk6Pi14T1p0800F/records/shot-f5056fea96bf70021469b9ac93aae968-20260929034644443.jpg?signature=…"
}

With Alert when a page keeps failing (alertOnError, errorThreshold), pages that failed that many runs in a row are listed in the alert under Problems, once per failure streak, and pages that work again are listed under Recovered. Real SUMMARY excerpt (httpbin.org/status/503, threshold 2, second run):

{
"problems": [{ "event": "problem", "url": "https://httpbin.org/status/503", "count": 2, "status": "failed", "error": "target returned HTTP 503" }],
"notifications": [{ "channel": "webhook", "ok": true, "kind": "json", "status": 200 }]
}

The JSON webhook receives { "monitor": "...", "checkedAt": "...", "changes": [ { "url", "name", "title", "addedCount", "removedCount", "added", "removed", "matchedKeywords", "numericChanges", "aiSummary", "significance", "screenshotUrl", "previousScreenshotUrl" } ], "problems": [ ... ] } (problems only with error alerts), plus incomplete and, when the run stopped at your maximum charge limit, uncheckedPages. A removed page appears in changes with pageRemoved: true and httpStatus; a page that is back has restored: true. With a signing secret, verify the X-Signature-256: sha256=<hex> header (HMAC-SHA256 of the raw body). The SUMMARY record has status (SUCCESS, PARTIAL_RESULTS, FAILED, NO_RESULTS or LIMIT_REACHED), counts and the result of each alert.

Use with AI agents (MCP)

Connect Apify's MCP server (https://mcp.apify.com?tools=tidytools/website-change-monitor) to Claude, Cursor or any MCP client, then ask e.g. "Check whether the pricing pages of these three competitors changed since last week and summarize what changed."

{ "urlList": ["https://example.com/pricing"], "monitorName": "pricing", "aiSummary": true }

Failed items are not charged and carry an errorType.

Use it from code and integrations

Run it from your own code with the Apify API. This call waits for the run and returns the results as JSON (replace YOUR_TOKEN with your Apify API token):

curl -X POST "https://api.apify.com/v2/acts/tidytools~website-change-monitor/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"urlList":["https://www.python.org/downloads/","https://news.ycombinator.com"]}'

The synchronous endpoint waits up to 5 minutes. For bigger runs, start the run with POST https://api.apify.com/v2/acts/tidytools~website-change-monitor/runs and read the dataset when it finishes, or use the apify-client package for JavaScript or Python.

Schedules and integrations: run it daily or weekly with Apify Schedules, get a webhook when a run finishes, or send the results to Zapier, Make, n8n, Google Sheets, Slack and other apps with Apify integrations. Results can be exported as JSON, CSV, Excel or XML.

Tips

  • Use Only output changed pages for scheduled runs, so the dataset contains just the news.
  • Rotating banners, ads or "related articles" blocks: list their CSS selectors in Ignore these parts of the page; they are removed before comparing.
  • If a page reports changes every time, turn on Ignore dates, times and counters, add ignore patterns for the parts that always differ (rotating banners), set Minimum changed lines, or narrow the CSS selector.
  • Use different monitor names for independent watch lists.
  • Advanced settings: Plain HTTP requests from and Proxy help with sites that block data-center requests (proxy usage is billed to your Apify account).

Limitations

  • Compares page text, not images or layout. Screenshots are taken in a separate browser visit right after the check, so a page that changes on every request (like a random ID) can differ slightly from the compared text.
  • Login and newsletter pop-ups are hidden too, and full-page screenshots pin sticky headers so they appear once, as soon as the capture backend supports it (the item then lists what was removed in screenshotCleanup).
  • Screenshot links are signed links to your monitor's key-value store; the 5 newest screenshots per page are kept (plus the locked baseline's).
  • Lines that only moved position are not reported as changes.
  • E-mail alerts use apify/send-mail, which only delivers to the e-mail address of your Apify account. For other recipients, use a webhook (Zapier, Make) or Slack.
  • Only public pages; no logins.
  • Images and other binary files are not compared: an image URL only saves the link as its baseline (and is charged as a page check), so it never reports a change. PDFs and plain-text files are read and compared as text.
  • A page that cannot be reached at all (unknown host, blocked, timeout) is reported as failed and is free; the message can be short, e.g. "target returned HTTP 530" for a host that does not exist.
  • The text converter can leave out elements such as the heading that repeats the page title (h1), title, header, nav or footer. When a CSS selector matches nothing in the converted text, the Actor looks for it once more in the page's raw HTML (read from the Actor's own network with the TidyTools User-Agent; skipped when HTTP route is backend or vm, or in browser mode) and the row says selectorSource: "raw-html". This second look understands tags, #id, .class, [attribute] / [attribute=value], spaces (descendants), > and comma lists; :pseudo-classes, + and ~ are not supported there and still end as selector-not-found. It sees only the HTML the server sends, not content added later by JavaScript. Text taken from raw HTML is plain (headings keep #, list items -), so if a page's selector switches between the two sources, the next check may report one change.
  • Very large pages: only about the first 500,000 characters of text per page are kept as the baseline.

FAQ

Does the Actor collect usage data? The Actor sends one anonymous usage counter per run (input type, item count range, outcome) to improve the tool; no URLs, content or account data.

How often can it check a page? As often as your Apify schedule runs it: hourly, daily or weekly. One page checked every hour is 720 checks, about $1.44 per month.

Can it monitor price changes? Yes. Watch only the price element with a CSS selector (e.g. .product-price), and price and percentage changes are extracted ($19 → $29). Keyword triggers can limit alerts to lines that mention words you choose.

How do I get alerts? By e-mail to your Apify account address, in Slack or Discord, or with a JSON webhook to Zapier, Make, n8n or your own app.

Will it alert me about dates and counters that change on every visit? Not if you turn on Ignore dates, times and counters: dates, times, "5 minutes ago" and view counters are ignored, and you can add your own ignore patterns and a minimum change size.

Can I watch two parts of the same page? Yes. List the page twice with different selectors in Pages with per-page settings (for example .price and .stock); each URL + selector pair is its own baseline and its own page check. The same URL with the same selector listed twice is checked once (https://example.com and https://example.com/ count as one).

What happens if my input has a mistake? The run still ends normally and nothing is charged. A line that is not a URL gets its own invalid-input row and the other pages are checked. An empty list, an invalid ignore pattern (regular expression), an invalid e-mail address or a bad proxy setting ends the run with one free invalid-input row, a status message that names the problem, and SUMMARY.status NO_RESULTS.

Is a failed check charged? No. Unreachable or blocked pages, HTTP errors, removed pages (404 / 410) and selectors that match nothing are free; the row says "(not charged)" and has charged: false.

Support

Open an issue in the Issues tab with the URL and your input. Issues are checked regularly.

Found this useful? A short review on the Store helps other users find it.