SaaS Pricing & Changelog Monitor avatar

SaaS Pricing & Changelog Monitor

Pricing

from $2.90 / 1,000 page checkeds

Go to Apify Store
SaaS Pricing & Changelog Monitor

SaaS Pricing & Changelog Monitor

Reads public SaaS pricing and changelog pages into plans, prices and release notes, then reports what changed since the last run. Not a sitemap diff. Obeys robots.txt. JavaScript-only tables are flagged, not guessed.

Pricing

from $2.90 / 1,000 page checkeds

Rating

0.0

(0)

Developer

Muhammet Mustafa Dincer

Muhammet Mustafa Dincer

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Security

Limited permissions

Share

Reads a public pricing page or changelog into structured plans and release notes, then, on the next run, reports what changed: a new plan, a price move, a feature added or removed, a new changelog entry.

A sitemap monitor tells you a URL was added. This Actor tells you the Pro plan went from $20/month to $25/month, or that a changelog gained "Lifecycle triggers for automations" on 2026-11-04.

What you get

DoesReads plans (name, price, currency, period, features) and changelog entries (date, title, summary). Compares them with the previous run
InputPricing, changelog or features URLs, or a bare domain. Up to 25
OutputOne page row with the plans and entries. One change row per difference
Change typesplan_added, plan_removed, price_changed, features_changed, changelog_added, changelog_removed, feature_added, feature_removed
NeedsNo login, no browser. Public https pages
PricingPay per event. $0.0002 to start, $0.004 per page checked, $0.015 per reported change (free plan). A baseline run has no change charge. This file is the intended price; it is not applied until the Actor is published
Does notRead a sitemap, crawl the whole site, log in, or guess prices from a JavaScript-only shell

Quick start

Leave the prefilled pages (https://buttondown.com/pricing and https://ghost.org/changelog) and click Start. The first run returns one page row per URL with status baseline_saved. Run the same input again later. Pages that did not change are omitted. A real change comes back as its own row, with a one-line summary.

A bare domain such as example.com checks only /pricing, /plans, /price, /changelog, /changes and /whats-new (and /features if you turn that page type on). If you know the page, paste the URL. The Actor does not open sitemap.xml.

How a pricing page is read

  1. Embedded product data (schema.org Offer with a plan name and a price). This is the strongest reading. An AggregateOffer price range is ignored.
  2. Plan cards in the HTML: a short price ($20, €9, Free, Custom) in the same block as a heading, plus the list items under that heading.
  3. A comparison table whose header cells are plan names and whose cells contain prices, when the cards are not a clear group.

The method is stored on extractionMethods (json-ld or html-plans) and extractionConfidence is high, medium or none.

A page whose path is /changelog is not mined for stray prices. A page whose path is /pricing is not mined for stray dates.

How a changelog is read

Entries come from a <time> date plus the nearest heading, newest first, up to Max changelog entries (default 25). A changelog page that has fewer than two entries in the HTML, and that links its own RSS or Atom feed, is read from that feed instead. The feed has to live on the same site and the link has to be a changelog.

Entries older than the oldest entry still in the window are the window sliding forward. They are not reported as removed.

What the first run stores

Changes mode saves a baseline in a named key-value store, saas-pricing-changelog-monitor-state, under the Watchlist name. The same name on the next run compares against that baseline. Snapshot mode returns the current plans and entries and saves nothing.

The baseline stores plan names, amounts, currencies, periods and feature lists, plus changelog dates and titles. It does not store the raw HTML.

When the page cannot be read

Pricing tables are often drawn by JavaScript. A plain request then returns an empty shell. The Actor does not invent plans from that shell. The row status is javascript_shell and extractionWarning explains it. Paste a server-rendered URL, or a changelog that publishes RSS.

If a later run cannot read a page that previously had a good baseline (a redesign, a challenge page that still returned HTML, a much smaller and different set of plans), the status is extraction_failed. The previous plans are kept. They are not reported as removed. extraction_failed is not a change charge.

Layout reading (html-plans) can break when the site redesigns. JSON-LD offers survive a visual redesign. The warning on an html-plans row says so.

Changes

{
"pages": ["https://example.com/pricing", "https://example.com/changelog"],
"pageTypes": ["pricing", "changelog"],
"mode": "changes",
"onlyChanged": true,
"monitorName": "competitors"
}

A price change row looks like this:

{
"recordType": "change",
"changeType": "price_changed",
"url": "https://example.com/pricing",
"planName": "Pro",
"previousPriceText": "$20",
"priceText": "$25",
"previousAmount": 20,
"amount": 25,
"currency": "USD",
"summary": "Pro price changed from $20 to $25."
}

A page row carries the full plans and changelogEntries arrays. Change rows carry only the difference.

onlyChanged hides pages that match the baseline. It does not hide a page that could not be read.

Change types you turn off are not charged. The new reading is still saved, so a left-out change is not reported on a later run either. extraction_failed is the exception: the baseline is not replaced.

Features pages

Turn on the Features page type for a marketing page that lists capabilities and has no prices. Headings become features. Later runs report feature_added and feature_removed. A pricing page's own feature bullets stay on the plan, as features_changed.

Politeness

The Actor sends a named user agent, stays on the site you named (redirects off the site are dropped), and obeys robots.txt unless you turn that off. A disallowed page is not fetched and not charged. Sitemap: lines in robots.txt are ignored. Requests to a private, local or IP address are rejected. There is no browser and no login.

Pricing

EventFree plan
Actor start$0.0002
Page checked$0.004
Change reported$0.015

A page that is blocked, missing, or disallowed by robots.txt is not charged. A baseline run charges a page check and no changes. Checking two pages every day and getting one price change a week is about $0.26 in page checks plus $0.015 for the change, before the start event.

Local sample

On 5 November 2026 a local run read three public pages (maxChangelogEntries 8, watchlist live-demo). Each came back baseline_saved. A second run of the same input compared the saved baseline and reported all three unchanged, with no new dataset rows and no change charge.

Buttondown pricing came from embedded product data (json-ld, confidence high):

PlanPrice
FreeFree (up to 100 subscribers)
Basic$9 (up to 1,000 subscribers)
Standard$29 (up to 5,000 subscribers)
Professional$79 (up to 10,000 subscribers)
Advanced$139 (up to 20,000 subscribers)

Ghost's changelog came from the HTML (html-changelog, confidence high). The newest of the eight kept entries were 2026-11-04 "Lifecycle triggers for automations", 2026-10-21 "Stripe Checkout customization" and 2026-10-15 "Tier-specific welcome sequences".

Umami pricing came from the plan cards (html-plans). Hobby Free/month, Pro $20/month, Business $200/month, Enterprise Custom, each with its feature list. That row carries the layout warning: a redesign can break the reading, and a later failed read keeps the previous baseline instead of reporting every plan as removed.

{
"recordType": "page",
"url": "https://umami.is/pricing",
"pageType": "pricing",
"status": "baseline_saved",
"summary": "Baseline saved: 4 plans.",
"extractionMethods": ["html-plans"],
"extractionConfidence": "high",
"plans": [
{ "name": "Hobby", "priceText": "Free/month", "amount": 0, "currency": "USD", "period": "month" },
{ "name": "Pro", "priceText": "$20/month", "amount": 20, "currency": "USD", "period": "month" },
{ "name": "Business", "priceText": "$200/month", "amount": 200, "currency": "USD", "period": "month" },
{ "name": "Enterprise", "priceText": "Custom", "amount": null, "currency": null, "period": null }
]
}