Pricing Page Change Monitor avatar

Pricing Page Change Monitor

Pricing

$5.00 / 1,000 page checkeds

Go to Apify Store
Pricing Page Change Monitor

Pricing Page Change Monitor

Watch any SaaS pricing page and get a structured diff when plans, prices or limits change. Detects plan cards automatically, keeps state between runs, and can call your webhook (Slack, Discord, Zapier, Make, n8n).

Pricing

$5.00 / 1,000 page checkeds

Rating

0.0

(0)

Developer

AIBuildersUse

AIBuildersUse

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

Pricing Page Change Monitor: track SaaS price changes and get alerts

Pricing Page Change Monitor watches any list of SaaS pricing pages and tells you exactly what changed since the last run: a plan's price went up or down, a plan was added or removed, or the plan details (limits, credits, features) were rewritten. Each run compares the page with the snapshot saved by the previous run and outputs a clean dataset of changes, with an optional webhook alert to Slack, Discord, Zapier, Make or n8n.

It's built for competitor price tracking, SaaS market research, and procurement teams that need to know when a vendor changes its prices.

What does Pricing Page Change Monitor do?

  • Extracts plans and prices from pricing pages: plan cards, pricing tables, and comparison tables. It reads $, €, £, ¥ and ₹ prices and billing periods (per month, per user, per year, one-time).
  • Renders JavaScript pages automatically. Most pages are fetched over fast plain HTTP. When a page only shows its prices after JavaScript runs (React, Next.js, Webflow and similar), a headless Chromium browser loads it instead.
  • Diffs against the previous run. Snapshots are saved in a named key-value store, so scheduled runs compare against each other.
  • Outputs only what matters: price_changed (with increase/decrease), plan_added, plan_removed, plan_details_changed, page_text_changed, plus clear error rows when a page can't be read.
  • Sends a webhook with all changes in one POST. The payload works with Slack and Discord incoming webhooks as is.
  • Lets you scope the check with a CSS selector when you only care about one part of a page.

Use cases

  • Competitor price monitoring: know the same day a competitor raises prices, launches a new tier, or drops a free plan.
  • Vendor and procurement watch: track the tools your team pays for (AI tools, dev tools, SaaS seats) and catch price increases before renewal.
  • Market research and pricing strategy: build a history of how a category's pricing moves over time.
  • Newsletters and analysts: get a ready-made feed of pricing changes to write about.
  • Internal alerts: pipe changes into Slack, a Google Sheet, or a CRM through Zapier, Make or n8n.

How to use it

  1. Add the pricing page URLs you want to watch. Optionally add a CSS selector, either for all pages or per URL.
  2. Run the Actor once. The first run saves a baseline for each page (one row per plan detected), so you can check that it reads the plans correctly.
  3. Create a schedule (for example daily or weekly) in Apify Console. Every later run outputs the changes, plus one no_change row per unchanged page.
  4. Optional: add a webhook URL to get the changes pushed to you.

Keep the same State store name across runs. To track two independent lists, give each its own store name.

Input

FieldDescription
urlsPricing pages to monitor. Each item can carry its own selector.
cssSelectorOptional CSS selector used for all pages without their own selector, e.g. #pricing.
renderModeauto (default: HTTP, browser only when needed), http, or browser.
textDiffModepricing_lines (default) also reports changed price-related lines outside the plan cards; all reports any text change; off reports plan and price changes only.
ignoreTextPatternsRegular expressions for text to ignore, e.g. rotating banners, A/B test copy, dates.
includeUnchangedOn by default: each unchanged page gets one no_change row, so every run shows what was checked. Turn off to output only real changes.
webhookUrl, webhookHeadersWhere to POST the changes, with optional headers (e.g. Authorization).
webhookOnBaselineAlso call the webhook on the first (baseline) run.
stateStoreNameName of the key-value store that keeps the snapshots. Default pricing-page-monitor-state.
maxConcurrencyPages checked in parallel (1–10).
proxyConfigurationOptional Apify Proxy for sites that block data-center IPs.

Example input:

{
"urls": [
{ "url": "https://cursor.com/pricing" },
{ "url": "https://lovable.dev/pricing" },
{ "url": "https://www.coderabbit.ai/pricing", "selector": "main" }
],
"renderMode": "auto",
"textDiffMode": "pricing_lines",
"webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ"
}

Output

Each dataset row is one change. Example of a price change:

{
"url": "https://cursor.com/pricing",
"label": null,
"selector": null,
"checkedAt": "2026-11-04T15:50:02Z",
"previousCheckedAt": "2026-11-03T15:49:18Z",
"fetchMethod": "http",
"plansDetected": 6,
"changeType": "price_changed",
"plan": "Plus",
"oldPrice": "$10",
"newPrice": "$8",
"oldPrices": ["$10"],
"newPrices": ["$8"],
"addedPrices": ["$8"],
"removedPrices": ["$10"],
"direction": "decrease",
"summary": "'Plus' price changed: $10 -> $8"
}

A new plan looks like {"changeType": "plan_added", "plan": "Super", "newPrice": "$100", "summary": "New plan 'Super' at $100", ...} and a removed one like {"changeType": "plan_removed", "plan": "Legacy Pro", "oldPrice": "$20", ...}. On the first run you get one baseline row per detected plan with its price. A summary of every run is saved as the OUTPUT record in the run's key-value store.

You can download the dataset as JSON, CSV, Excel, XML or HTML, or read it through the Apify API.

Change types

changeTypeMeaning
baselineFirst run for this page: the plans and prices that were saved.
price_changedA plan's main price changed (direction is increase or decrease).
plan_added / plan_removedA plan appeared or disappeared.
plan_details_changedA plan's limits, credits or feature text changed, but not its main price.
page_text_changedPrice-related text elsewhere on the page changed (added/removed lines are included).
no_changeThe page was checked and nothing changed (turn off with includeUnchanged).
plans_not_foundThe page loaded but no prices were found. The previous snapshot is kept, so a broken load can't create false "plan removed" alerts.
selector_not_foundThe CSS selector matched nothing.
fetch_errorThe page could not be loaded after retries.

Webhook payload

One POST per run when there are changes:

{
"event": "pricing_changes_detected",
"runStartedAt": "2026-11-04T15:50:02Z",
"runId": "abc123",
"changeCount": 2,
"text": "Pricing changes detected:\n- https://cursor.com/pricing: 'Plus' price changed: $10 -> $8\n- https://cursor.com/pricing: New plan 'Super' at $100",
"content": "(same text, for Discord)",
"changes": [ { "changeType": "price_changed", "plan": "Plus", "oldPrice": "$10", "newPrice": "$8" } ]
}

The text field makes it work with Slack incoming webhooks, and content makes it work with Discord. Zapier, Make and n8n can use the changes array.

How much does it cost?

The Actor uses pay-per-event pricing: you pay a small fee per pricing page checked, plus Apify's standard Actor start fee. Pages that fail to load are not charged. Watching 20 pricing pages once a day costs roughly $3 a month. Set a maximum cost per run in Console and the Actor stops before going over it.

Tips

  • Schedule it. The value is in repeated runs. Daily is plenty for most pricing pages.
  • Noisy page? Some vendors A/B test their copy. Add the changing phrase to ignoreTextPatterns, or set textDiffMode to off to get plan and price changes only.
  • Only one section matters? Use a CSS selector such as #pricing or main.
  • Memory: 1024 MB (default) is enough for any page. In http mode, 512 MB is enough.

FAQ

Does it work on pages that load prices with JavaScript? Yes. In auto mode the Actor first tries plain HTTP and switches to a headless browser when the page has no readable prices without JavaScript.

Will it detect a change in the monthly vs annual toggle? It reads what the page shows by default, plus any prices present in the page text. If a page shows annual prices only after a click, use a CSS selector on the section that holds both, or monitor the page's annual pricing URL if it has one.

What if the page layout changes? Plan names and prices are matched by name, not position, so reordering cards does not create false alerts. If a redesign renames plans, you'll see plan_removed and plan_added rows, which is usually what you want to know.

What about pages that show no prices at all, like "Contact sales"? The text diff still reports changes to the plan names and price-related text. Use textDiffMode: "all" for any change at all.

Can I reset the baseline? Change stateStoreName (or delete the store in Console) and the next run starts fresh.

Is it legal to monitor pricing pages? The Actor only reads public pricing pages, as a visitor's browser would. Check each site's terms of use for your use case.

Limitations

  • Prices must be written with a currency symbol or code (for example $20, €15, 20 USD). Pages that only say "Free" or "Contact us" are tracked through the text diff.
  • Pages that also list per-token API prices or add-ons (for example model pricing tables) produce extra "plan" rows for those items. They stay stable between runs and still alert you when those prices change.
  • Pages behind a login or a bot challenge can't be read; try proxyConfiguration with residential proxies.

Feedback

Found a page it reads wrongly? Open an issue in the Actor's Issues tab with the URL, and it will be looked at.