How to track competitor pricing pages
September 25th 2026 · Akash Rajpurohit
Pricing pages look like the easiest thing on the web to extract. They are tables, mostly, with numbers in them. In practice they are among the most awkward, because a pricing page is a marketing artifact designed for persuasion rather than a data source designed for reading.
TLDR
- The number on the page is often one view of pricing, not the pricing. Toggles, currency and region all change it.
- Extract into a fixed shape you define, not whatever shape each competitor happens to use.
- Capture the qualifiers, because “$29” without “per seat, billed annually” is a fact you will misread later.
- Daily is enough. Pricing changes are rare and deliberate.
- Keep the page, not just the figures, or you cannot explain a change or repair a bad extractor.
Why pricing pages resist extraction
Four things make them harder than they look.
The page shows one state at a time. Monthly and annual prices usually live behind the same toggle, and only one is rendered. Capture without thinking and you record whichever the page defaults to, which may not be the one you compared last month.
Currency and region vary by visitor. Many pricing pages localise. The figure you get depends on where the request appeared to come from, which means your history can shift for reasons that have nothing to do with the competitor changing anything.
Plan structures are not comparable. One vendor sells seats, another usage, another a base fee plus overage. Forcing all three into a single “price” column produces a table that is tidy and wrong.
The important part is often not the number. A plan that quietly drops a feature, adds a cap, or moves something behind “contact us” has changed more meaningfully than one that moved from $29 to $31.
Decide what you are actually tracking
Before extracting anything, write down the question. The answer changes the whole design:
- “Did the headline price move?” Then you need the plan names and figures, and little else.
- “Are we still cheaper at our customers’ volume?” Then you need the usage tiers and overage rates, which are usually further down the page or on another one.
- “What are they positioning against us?” Then the feature lists matter more than the prices.
- “Did they change packaging?” Then plan names, plan count and what sits behind “contact sales” are the signal.
Most tracking projects fail here rather than technically. They capture prices because prices are extractable, and then discover the interesting changes were never in the numbers.
Extract into your shape, not theirs
Define the schema you want and extract into it. Something like:
{
"plans": [
{
"name": "Growth",
"price_amount": 99,
"price_currency": "USD",
"billing_period": "month",
"billing_commitment": "annual",
"unit": "per workspace",
"included": "50,000 credits",
"overage": "$9 per 10k",
"is_contact_sales": false
}
],
"captured_at": "2026-11-03T09:00:00Z"
}
The qualifiers are the point. 99 on its own is not a fact you can act on; 99 USD per month, committed annually, per workspace is. A schema forces those to be captured or explicitly null, rather than quietly dropped because the extractor only looked for a number.
Pin the request context too. Same currency, same region, same billing toggle every time. A comparison across different views of a pricing page is not a comparison.
Compare meaning, not markup
Diffing the raw page fires constantly, because pricing pages carry testimonials, logos, rotating copy and experiment buckets that change without the pricing changing.
Compare the extracted structure instead. Then a change is a specific, explainable statement: this plan’s price moved, this plan appeared, this one went to contact-sales. That is something you can put in an alert that a human will actually read.
Alert on the things that matter and stay quiet on the rest. A new testimonial is not a pricing change.
Daily is plenty
Pricing changes are rare, deliberate, and usually announced. Checking every hour buys you almost nothing and costs you goodwill, since a pricing page hit sixty times a day from one source is conspicuous.
Daily catches everything that matters within a day. If a launch is expected, tighten temporarily and put it back afterwards.
Keep the page, not just the numbers
Store the extracted markdown alongside the structured result.
Two reasons, both learned the hard way. When an alert fires you want to see the page as it was, not infer what happened from two JSON blobs. And when you eventually discover your extractor has been misreading a plan for a month, having the pages means you can re-extract history rather than losing it.
Raw pages are cheap to store compared to the cost of not having them.
What good tracking looks like
- Fetch the pricing page daily, with the same locale and toggle state
- Extract into your fixed schema, qualifiers included
- Compare structures, not markup
- Alert with the specific change, not “the page changed”
- Keep both the structure and the page
The engineering here is straightforward. The judgement is in step two, and it is worth spending an afternoon on the schema before writing any code, because a schema that cannot express “per seat” will silently record something false and keep doing it.
If you want the fetch and extraction handled, extract pulls a page into a schema you define, and scrape gives you the clean markdown to keep alongside it. Failures are never billed, so a pricing page that was temporarily unreachable costs nothing and does not land in your history as a change. A work email gets you 500 free credits.
[ FAQ ]
How do I track a competitor's pricing?
Fetch the pricing page on a schedule, extract the plan names and figures into a fixed shape, and compare against what you stored. The difficulty is that pricing pages express the same information very differently from one another.
Why is extracting pricing harder than it looks?
Because a plan's price depends on toggles, currency, billing period and region, and the page often shows one combination at a time. What you capture may be a view of the pricing rather than the pricing.
How often should I check a pricing page?
Daily is plenty for almost everyone. Pricing changes are rare, deliberate and announced; checking hourly mostly buys you noise and a higher chance of being blocked.
Should I store the whole page or just the numbers?
Both. The numbers are what you compare, and the page is what lets you explain a change or fix an extractor that turns out to have been wrong for a month.
Is tracking competitor pricing allowed?
Public pricing pages are published to be read, and reading them politely at a low rate is ordinary practice. This is not legal advice, so check your own obligations, and respect robots.txt and sensible rate limits either way.
Try it on your own URLs.
Sign up with a work email for 500 free credits, no card required.