Competitor Monitor - SaaS Pricing, Changelog & Messaging avatar

Competitor Monitor - SaaS Pricing, Changelog & Messaging

Pricing

from $9.70 / 1,000 pages

Go to Apify Store
Competitor Monitor - SaaS Pricing, Changelog & Messaging

Competitor Monitor - SaaS Pricing, Changelog & Messaging

Track rival SaaS pricing pages, changelogs, homepages and docs, and get only what changed since your last run: price changes, plans added or removed, new releases, headline rewrites, each with before and after. Alerts go to Slack or a webhook. $10 per 1,000 pages checked.

Pricing

from $9.70 / 1,000 pages

Rating

5.0

(1)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

0

Monthly active users

3 days ago

Last modified

Share

Track your competitors' SaaS pricing pages, changelogs and homepages, and get only what changed since your last run: a price that went up, a plan that appeared or vanished, a new release, a rewritten headline. Each change comes back as a typed signal with its before and after, ready for a brief or a Slack alert.

Two things to know first. The first run only records a baseline, so changes start on the second. And pages are read by rules, so a page that shows a different price on different loads can read as a change that never happened, and is billed as one.

InputCompetitor names with their pricing, changelog, homepage and docs URLs
OutputOne row per page that is new, changed or failed, with typed signals and every field that moved, plus one brief row per run
CeilingNo page cap: every URL you list is checked, within the run's time limit
SpeedA few seconds a page, and 5 to 35 seconds for a page that only appears after its scripts run
Account neededNone on the sites you watch. Pages behind a login cannot be watched
Price$10.00 per 1,000 pages checked ($0.01 each) on the Free plan, a little less on paid plans, plus $0.015 per change, $0.035 per signal a language model wrote and $0.30 per brief. The free plan's $5 a month covers about 500 page checks

🔍 What SaaS Competitor Monitor does

It reads up to four pages for each competitor:

PageWhat it reads
Pricing (pricingUrl)Plan names, prices, buttons and features, and plans added or removed
Changelog (changelogUrl)Release entries
Positioning (homepageUrl)The main headline, the hero text and the primary button
Integrations (docsUrl)New integrations named on the page

Every page is compared with the copy saved on your last run. That copy lives in a key-value store called saas-competitor-change-monitor-state, in your own Apify account, one record per competitor and page. Records are keyed by the competitor's name, so two tasks using the same name share one history, and renaming a competitor starts its history again.

A page that cannot be read comes back failed, is not charged, and the last good copy stays the baseline. Pages that only fill in after scripts run are drawn in a browser, which waits until the text stops growing. A page still drawing after 30 seconds fails, unbilled.

Each signal carries a "why it matters" line. With Generate AI insights on, which is the default, a language model writes that line for every changed page and the signal says ai_written: true. Switch it off and built-in rules write it instead, for free.

When page reading is improved, a page saved by the older reader shows as new once, so a better reading is never billed as a change.

📋 What data you get from each page check

What you getField
Which competitor and which pagetarget_key, competitor, page_type, url
Whether the page is new, changed, unchanged or failedstatus, sync_status
The typed changes, each with a before, an after and a why-it-matters linesignals
Whether a model or the rules wrote that linesignals[].ai_written
Every field that moved, by pathchange_records
On the brief row: how many signals the run found, and a link to the HTML briefsignal_count, brief_url

▶️ How to track competitor pricing changes

  1. Open SaaS Competitor Monitor and click Try for free.
  2. In Competitors, replace the Acme example with your own: a name and the URLs to watch.
  3. Choose What to watch. Untick Generate weekly competitive brief on runs where you do not want the $0.30 brief, and Generate AI insights if the rules' line is enough for you.
  4. Paste a Slack or Discord address into Webhook URL (optional) if you want alerts.
  5. Click Start once to record the baseline, then put the same input on a schedule.

There is no sample row: the first run is the baseline.

💰 How much does it cost to track competitor pricing?

$0.01 per page checked, which is $10.00 per 1,000 checks on the Free plan, a little less on paid plans. On top of that: $0.015 per page that changed, $0.035 per signal whose line a language model wrote, and $0.30 per brief. The free plan's $5 a month covers about 500 page checks, fewer once changes and briefs are added.

Every page read is charged, changed or not. A failed page is not. A signal the rules wrote costs nothing, so with Generate AI insights off a change costs $0.015 however many signals it carries.

The brief is billed on every run it is on for, a quiet one included, so a daily schedule with the brief on is $2.10 a week in briefs alone. Switch it on for one run a week instead.

If you set a maximum charge for a run, it checks only the pages it can still pay for, leaves the rest for the next run, and skips the brief if it no longer fits.

📥 What you give it

{
"competitors": [
{
"name": "Acme",
"pricingUrl": "https://acme.com/pricing",
"changelogUrl": "https://acme.com/changelog",
"homepageUrl": "https://acme.com",
"docsUrl": ""
}
],
"watch": ["pricing", "changelog", "positioning", "integrations"],
"onlyNewSinceLastRun": true,
"weeklyBrief": true,
"generateAiSignals": true
}
FieldDefaultWhat it is
competitorsnone, requiredEach competitor: a name, plus pricingUrl, changelogUrl, homepageUrl and docsUrl. Leave a URL empty to skip that page. The form arrives with an example called Acme; replace it.
watchall fourpricing, changelog, positioning, integrations. Which pages to check.
weeklyBrieftrueWrites a Markdown and an HTML brief of the run's signals. It is $0.30 on every run it is on for.
onlyNewSinceLastRuntrueRows only for pages that are new, changed or failed. Off, every page checked gets a row.
generateAiSignalstrueA language model writes the "why it matters" line on each changed page, $0.035 a signal. Off, the rules write it, free. Unchanged pages never reach the model.
webhookUrlemptyA Slack, Discord or other webhook. It gets a short summary, and only on runs that found a signal.
proxyConfigurationleave it aloneLeave it as it is, or add your own servers here if you want pages fetched through them.

📤 What you get back

A real row from a test run on 30 September 2026. Before that run the saved Starter price had been edited down to $12, so Ghost's live $18 came back as a rise. The model's line is cut short:

{
"target_key": "ghost::pricing",
"competitor": "Ghost",
"page_type": "pricing",
"url": "https://ghost.org/pricing/",
"status": "changed",
"sync_status": "ok",
"signals": [
{
"competitor": "Ghost",
"signal_type": "price_change",
"detail": "Starter: $12/month → $18/month (+50%)",
"before": "$12",
"after": "$18",
"why_it_matters": "Entry price up 50% to $18/month ...",
"page_type": "pricing",
"url": "https://ghost.org/pricing/",
"detected_at": "2026-09-30T19:44:32.138987+00:00",
"is_new": false,
"is_changed": true,
"ai_written": true
}
],
"change_records": [
{
"target": "ghost::pricing",
"change_type": "modified",
"path": "tiers.Starter.price",
"before": "$12",
"after": "$18",
"detected_at": "2026-09-30T19:44:32.139226+00:00"
},
{
"target": "ghost::pricing",
"change_type": "modified",
"path": "tiers.Starter.price_amount",
"before": 12,
"after": 18,
"detected_at": "2026-09-30T19:44:32.139226+00:00"
}
]
}

And the brief row from a run on 30 September, with its link cut short:

{
"type": "weekly_brief",
"generated_at": "2026-09-30T02:33:59.840901+00:00",
"signal_count": 0,
"brief_kv_key": "weekly-brief-html",
"brief_url": "https://api.apify.com/v2/key-value-stores/.../records/weekly-brief-html?signature=..."
}
FieldHow to read it
target_key<competitor>::<page>, where the page is pricing, changelog, homepage or docs.
status, sync_statusnew, changed, unchanged or failed; and ok or failed for the reading itself.
signalsThe typed changes: price_change, plan_added, plan_removed, feature_moved, cta_change, positioning_shift, new_integration or changelog_entry, each with detail, before, after and why_it_matters.
ai_writtentrue when a language model wrote the why_it_matters line. Those are the signals charged $0.035. A rules-written line says false and is free.
change_recordsEvery field that moved, by path, such as tiers.Starter.price, with its before and after.
signal_count, brief_urlOn the brief row: how many signals the run found, and a link to the HTML brief. The Markdown version is in the run's key-value store under weekly-brief.

🧾 Reading the output

There is no sample row and no error code. Every row is either a page or the brief:

RowHow to spot itCharged
A page seen for the first timestatus: "new". No signals: this is the baselineas a page check
A page that movedstatus: "changed", with change_records and usually signalsa page check and a change, plus $0.035 for each signal with ai_written: true
A page that did not movestatus: "unchanged". Only written with onlyNewSinceLastRun offas a page check
A page that could not be readstatus: "failed". url is empty and competitor holds the lower-case short name, so go by target_key; the run log says whyno
The brieftype: "weekly_brief"$0.30

Not every change becomes a signal. A field that moved without matching a rule shows up in change_records only, and still counts as a change. For news you would act on, keep the rows where status is changed.

💡 What people use it for

  • Knowing the week a rival raises a plan, before a customer brings it up on a sales call.
  • Keeping a battlecard's pricing column honest without anyone opening five pricing pages on Monday.
  • Reading a competitor's releases in one weekly brief instead of following four changelogs.
  • Catching a homepage rewrite, which can be the first public sign they are chasing a different buyer.

🚧 What it does not do

  • No pages behind a login. A page that answers with an error or a holding screen instead of content comes back failed too.
  • No screenshots or visual diff. It compares the text and structure it reads.
  • No perfect reading of pricing pages. Plans are found by rules. Scored on 40 real pricing pages, it found 135 of 144 plans. It can mistake a menu item or a calculator for a plan, miss a free plan shown only as the word "Free", and read only part of a tabbed plan layout.
  • No archive. Only the latest good copy of each page is kept. The dataset of each run holds what changed on that run.
  • The model does not find changes. The rules do. The model only writes the "why it matters" line on what they found.
  • It is not an official tool of any platform or company named on this page. Dami's Studio is independent and is not affiliated with or endorsed by any of them.

🧭 Which competitor monitor do you need?

If you wantUse
Changes on a rival SaaS site's pricing, changelog, homepage and docsThis one
Price and stock moves on a rival's product pagesProduct Price & Stock Monitor
New reviews of a rival's app, sorted into bugs, billing and feature requestsApp Review Triage
A rival's Facebook and Instagram adsMeta Ad Library Scraper
The ads a rival runs on LinkedInLinkedIn Ads Scraper
What a rival's site runs on, from DNS records to its tech stackDomain Inspector

❓ Questions people ask

Why did the first run report everything as new?

There was nothing to compare against yet. The first run saves a copy of each page, and from the second run on you get real changes.

Where does it keep last week's pages?

In the saas-competitor-change-monitor-state store in your own account. Delete it to start over, and the next run builds a fresh baseline.

Will I be charged when nothing changes?

For the page checks, yes, and for the brief if it is on. A change is only charged when a page reads differently from last time.

How do I get competitor price alerts in Slack?

Put your Slack incoming-webhook address in webhookUrl. Discord and other webhooks work the same way. Nothing is sent on a run that found no signal.

Can I call it from code or connect it to an AI assistant?

Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/saas-competitor-change-monitor. Either way the run happens on your Apify account at the same price.

It reads public pages, the ones any visitor sees, and nothing behind a login. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the run ID and the competitor URL that misbehaved, and say what the page showed that the row did not.