Skip to content
August 2026 · updated 2026-08-25

Why Is the Price Different at Checkout? Our Four Errors

Four times this site has published a price that was wrong, and every one of them was a number the vendor never showed a buyer.

Here's the trap. You open a vendor's pricing page, copy the number into a budget line, and then the price is different at checkout. The pricing page is not lying to you exactly. It is serving four or five different numbers in the same HTTP response, and you read whichever one your eye or your scraper landed on first.

We know because we did it. This site publishes a price for 150 of the 264 tools it tracks, and four times it has published a figure that was wrong in a way we can date. The worst was NICE CXone, carried at $71 a seat when the vendor's floor was $110.

That is 35.5% below the real entry price, and on a fifty-seat contact centre it understates the annual bill by $23,400.

The thing that fooled us was not carelessness with arithmetic. It was a dollar sign. React Server Components serialise a page into a payload full of reference markers written as $1, $13, $L15. A dollar-sign grep returns those as prices.

NICE was the third vendor in one month where that exact trap appeared, after Apollo and Prospeo.

Think of a pricing page as four panes of glass stacked in one window. The rendered text is the front pane. Behind it sit the structured data crawlers read, the markup a stylesheet hides, and a payload where the framework talks to itself.

Every pane has numbers on it. One is an offer.

A price is only a price if the vendor shows it to a buyer, in a currency, for a stated period.

Everything else is a number on a page. This post is the method that rule came out of, written so you can run it. Nothing here is a measurement of any product. Every figure is read off a vendor's served page on 25 August 2026, off a court docket, off a Federal Register citation, or off our own record of being wrong.

What follows: the four corrections with dates, the five layers a pricing page serves, and a live diff across 21 vendor pages. Then what the FTC actually prohibits and what it conspicuously does not, and a twelve-minute audit with pass/fail thresholds to run before a number goes near a deck. If you want the sibling problem, 108 of these 264 tools have no self-serve checkout at all: those make you ask, these answer wrong.

Why is the price different at checkout? The short answer

Because the pricing page and the checkout are built by different teams for different jobs, and only one is required to be right. Marketing owns the pricing page and optimises for a click. Billing owns the checkout and optimises for a charge that will not be disputed. When they disagree, the checkout moves money and the pricing page is the one you screenshotted.

The gap has five recurring shapes, every one found on a live page this month. The billing basis is annual and labelled monthly. The unit is a seat and the page never uses the word. The currency was chosen by your IP address. A slider you did not move set the tier price. And the number in the markup is not the number on screen.

The last one fools automated tooling rather than people. Salesfinity renders $299 to a visitor and serves "price":"149" in its JSON-LD, with priceValidUntil set to 2026-12-31. Both were in the same response on 25 August 2026.

Between the two layers sits $150 per user per month, or $1,800 a user a year.

What counts as a price, and what is only a number on a page

Three tests, all required. A price has a currency symbol attached to it in the markup, not merely nearby in the text. It has a stated period: per month, per year, per minute, once. And a buyer can see it without special access: no view-source, no DevTools, no disabled stylesheet, no crawler user-agent.

Fail any one and it is not a price.

That sounds pedantic until you watch what it deletes. Koncert's pricing page shows a visitor no dollar figure at all, while the served HTML carries a five-column comparison table holding the bare integers 6, 7, 29, 79 and 99. Re-fetched 25 August 2026: still there, still suppressed, on a page with 128 display: none declarations.

Those integers have no currency span and their billing-period span is present and empty. Somebody built a price table, took the prices out, and hid what was left. We recorded 79 as Koncert's entry price, which was our third published figure with no vendor origin. It is now null, and Koncert's record says why.

The word doing the work is offer. A pricing page is a marketing asset. A checkout is closer to an offer, because that is where a vendor accepts money against a stated figure. Everything in between, structured data included, is a claim about a price rather than a price.

Four prices we published that were wrong

Writing this section requires having published prices and then checked them, which is why nobody else in the category writes one. Roughly half of every listing-only price here turned out wrong on the weeks we re-read the pages. Four are worth naming, because each is a different failure mode.

What we publishedWhat was trueGapHow it got inCorrected
NICE CXone $71/seat$110/seat floor$110 is 54.9% above $71React payload markers read as dollar figures; the same figure was in the upstream master plan2026-08-22
Trellus $30/mo$99.99/mo3.33xA hidden 34.99 element in the page, rounded. The vendor had documented this trap in their own HTML comment2026-08-12
Air.ai $0.11/minNo vendor page has ever carried itNot a price at allCirculated only in articles by competitors selling replacementsRemoved
Woodpecker $29 and Koncert $79Woodpecker $35; Koncert publishes nothing$29 was a competitor's rate quoted in Woodpecker's proseNumbers lifted from text adjacent to a priceRemoved

NICE CXone: the 55% one

On 22 August 2026 we read nice.com/pricing directly and found that $71 appears nowhere on it. The ladder is $110, $135, $169, $209 and $249 per agent per month, plus a $0.25 per-interaction rate on the top suite. The real floor is 54.9% above what we had published, which is the same error read the other way as 35.5% below.

The record was corrected to $110 and the CCaaS comparison built on it was rebuilt.

The detail that matters: the wrong figure was not inherited from a bad read of ours. The upstream research plan carried $71 too. Two independent processes reached the same wrong number from the same page, which is what a systematic trap looks like rather than a mistake.

Trellus: the vendor who documented our bug before we found it

In August 2026 trellus.ai/pricing carried an HTML comment left in the published page. Quoted verbatim from our capture of 12 August 2026: "The VISIBLE prices on the page are 99.99 (Power) and 149.99 (Parallel)... The page's HTML also contains a HIDDEN 34.99 element (a leftover/disabled promo) that automated scrapers pick up, but users do NOT see it."

We had recorded $30. That is their hidden number, rounded. A vendor found the bug in their own page, wrote down exactly how it deceives scrapers, and pointed their structured data at the price a human sees.

They did the honest thing and we were the scraper.

Re-fetched 25 August 2026, and the page reports itself last published that morning at 09:01 UTC. The comment is gone. The 34.99 element is still there, twice, carrying the classes price-parallel annual and a scale3d(0.6, 0.6, 1) transform, which is a toggle state rather than a live offer. The JSON-LD still resolves to 99.99 and 149.99 with unitText: "month". Trellus's record reads $99.99.

Air.ai and Woodpecker: numbers with no vendor behind them

Air.ai's $0.11 a minute existed only in articles by competitors selling replacements. Woodpecker's $29 was most likely lifted from prose on Woodpecker's own page comparing a competitor's per-seat rate. Same error both times: a number standing next to a vendor's name is not that vendor's price. Woodpecker's entry figure is $35 with a 500-prospect minimum, and it meters contacted prospects at $0.07 each. Air.ai now serves an unrelated company on its domain. That is worth its own check and it has one on this site: the four ways a vendor stops being sold without announcing it.

The dollar sign that is not a dollar

React Server Components serialise a rendered tree into a flight payload embedded in the HTML. Inside it, references to other chunks are written with a dollar prefix: $1 for the identity component, $L18 for a lazy chunk, $undefined for an absent value, and bare hex-ish integers for anything the serialiser has already emitted once. Next.js, which most of this category's marketing sites now run on, produces these by the hundred.

On nice.com/pricing, fetched 25 August 2026, there are 518 dollar-prefixed tokens in the response.

130 of them are $undefined. Of the 16 distinct tokens that look like a plain integer dollar amount, five are the real prices and eleven are markers, appearing 37 times between them. $41 and $54 are SVG path d attributes. $13, $27 and $35 are dangerouslySetInnerHTML payloads.

Vendor pageDollar tokens visible to a readerDollar-shaped tokens in raw HTML onlyWhat the raw-only ones actually areRead
nice.com/pricing7 ($110 / $135 / $169 / $209 / $249 / $0.25 / $2)9SVG path data, innerHTML payloads, component refs2026-08-25
prospeo.io/pricing027post_text reference markers inside a serialised payload2026-08-25
apollo.io/pricing1 ($0.025)7Component, style and content references2026-08-25
vapi.ai/pricing98noscript children refs and SVG path data2026-08-25
elevenlabs.io/pricing169Props-path references, e.g. $16:props:secondaryNav2026-08-25
leadmagic.io/pricing178Mostly markers; $0.025 is a real rate inside FAQ JSON-LD2026-08-25
lemlist.com/pricing74Real add-on prices inside tooltip attributes, not markers2026-08-25
hunter.io/pricing161$7.50/mois, a French-language tooltip on an English page2026-08-25
kixie.com/pricing04Real prices, in FAQPage structured data only2026-08-25
lead411.com/pricing52$49 in the meta description; $899 is a sweepstakes prize value2026-08-25

Ten of the 21 pricing pages we re-read on 25 August 2026 serve dollar-shaped tokens that no buyer ever sees. That is not a finding about deception. Most of it is a framework artefact and the vendors involved almost certainly have no idea. It is a finding about tooling: any process that greps a modern marketing site for $ followed by digits is reading the framework's internal bookkeeping and calling it a rate card.

Prospeo is the cleanest illustration because it is the extreme case. Its pricing page renders zero dollar figures to a text extractor and carries 27 distinct dollar-shaped tokens in the raw response, running consecutively from $20 to $33, each one a post_text reference inside a serialised block.

A naive read of that page returns fourteen consecutive integers and not one of them is money.

The price the crawlers get, and the buyer does not

Structured data is the second pane. Vendors publish application/ld+json so search engines can show a price in a result snippet. It comes from a different pipeline than the rendered page, often a CMS field set once, and it drifts.

Kixie is the sharpest case in this corpus. Re-read 25 August 2026: zero dollar amounts in the rendered text, four in the markup. The FAQPage JSON-LD carries $30 a month per user for unlimited minutes, $0.011 a text, and $5.00 a month per extra number. Older captures show those answers on screen, so this is a deletion with the machine-readable copy left behind. The effect is that a crawler is told prices a buyer is not.

Salesfinity's gap is wider and points the other way. A buyer sees $299 and a machine is told 149, vendor-reported in both layers, and neither figure carries a note explaining the other. Apollo's OfferCatalog lists Free at 0, Basic at 49 and Professional at 99, each tagged billingDuration: P1M.

Our record for Apollo said $65 a seat, verified 2026-08-11, and 65 appeared nowhere in that document.

On 26 August 2026 we re-read the rendered page in a browser, both toggle states. It opens on annual, labelled Annual billing Save 29%, at $0 / $49 / $79 / $119. Switched to monthly it reads $0 / $69 / $99 / $149. Our record is now $69, the monthly-billing rate. Note what that makes of the OfferCatalog: it is wrong twice over, because 49 is the annual rate rather than a P1M one, and its second tier of 99 is not the annual tier price either, which is 79.

Trellus gets the honourable mention again. Its SoftwareApplication schema names Power at 99.99 and Parallel at 149.99 with an explicit UnitPriceSpecification of one month, matching what a visitor sees to the cent. It took a corpus of 21 to find one worth pointing at.

The price the stylesheet hides

The third pane is CSS. A price present in the HTML and set to display: none is invisible to a buyer, invisible to a screenshot, and perfectly visible to curl. Koncert is the archetype. Avoma is the harder version: its Organization tier appears in served HTML as $24, $29 and $39, two of them behind classes named monthly and yearly that a stylesheet toggles, and that stylesheet is not in the response.

No visitor ever sees the $24. It resolves in the accessibility tree in both toggle states and never on screen. So it was not recorded, and the review published the disagreement instead of picking a side. That is the correct move and it costs a number, which is why almost nobody makes it. The rule this produced: assume any toggled pricing page is hiding a number, and resolve it in a rendered browser. Where the CSS is external and the browser is unavailable, record the ambiguity rather than the figure.

Hunter's page is the cleanest live specimen of the mechanic. Read 25 August 2026, one Starter card holds both prices in adjacent spans: <span data-pricing-table-target="monthlyPrice" class="d-none">$49</span> next to <span data-pricing-table-target="yearlyPrice">$34</span>. The class d-none is Bootstrap's display-none utility. A visitor sees $34. A fetch sees both, and the one that is hidden is the dearer, honest, monthly-billing rate.

The fourth hiding place is not hidden at all. It is a tooltip. lemlist carries three real prices inside tooltip attributes, read 25 August 2026: $9 per email per month for extra senders, $15 a month for a phone number with 400 calling minutes, and $20 per user per month for the WhatsApp add-on. None renders until you hover.

The toggle that only serves one side

Every vendor with an annual discount publishes two numbers that both call themselves monthly: the monthly-billing rate, and the annual rate divided by twelve. This site records the monthly-billing rate, because that is what a buyer pays who has not committed to a year. Mixing bases across a table penalises whoever was recorded on the dearer basis.

Instantly's page, read 25 August 2026, is the cleanest live example anywhere in the corpus. In one block it reads "Growth $37.6 /monthly". In another block on the same page in the same response it reads "Growth Plan $47/mo". The $37.6 is the annual rate divided by twelve, wearing the word monthly.

The gap is 25%, and our record says $47.

ElevenLabs publishes the arithmetic itself, which is rare and creditable. Its FAQ states that annual billing means you pay for ten months, and that "the equivalent monthly price on an annual plan is $5 for Starter, $18.33 for Creator, $82.50 for Pro, $249.17 for Scale, and $825 for Business." The monthly-billing Starter is $6. Our record says $6.

The same page runs a second mechanic in the same card: Creator shows $22 beside "First month 50% off $11 per month". The prominent number is the promotion. The list price is the smaller one. That is the opposite of the usual assumption about struck-through prices, and it is how a promotional rate ends up in a twelve-month budget.

Cal.com shows the third variant. Read 25 August 2026, the page defaults to YEARLY, labels Teams at $12 per user per month with a Save 25% badge, and the monthly figure is not in the served document at all. It arrives only after a click. A fetch of that page can be complete, correct and still contain exactly one side of a two-sided price.

The currency you did not pick

Pricing pages geo-detect. This is the failure mode that produces the most confidently wrong numbers, because the figure looks perfectly normal and is simply denominated in the wrong thing. Woodpecker served ₹3,300 a month to a visitor in India. The same page with the selector set to USD says $35. HubSpot served rupees to an Indian address with no currency selector, so our HubSpot figures come from the vendor's US product catalogue and the review says so. Google Workspace served ₹99, ₹864 and ₹1,080, with 95 rupee markers on one page.

We checked whether this was systemic and it is not. Most vendors serve USD regardless of origin. But Dropcontact prices only in euros, and lemlist's page carries pound and euro symbols alongside dollars on one fetch. A field holding a bare number with no currency cannot represent any of them honestly, which is why Dropcontact's price here is null with the euro figure in prose.

Dropcontact also runs the slider mechanic and contradicts itself between layers, both read 25 August 2026. The rendered page opens at 79 € /monthly and 120 € /monthly, which is wherever the credit slider sits by default. The same document's JSON-LD names "Starter, 500 credits per month. Monthly billing, no commitment" at 29 EUR.

The default view is 172% above the vendor's own published floor, and the floor is only in the markup.

Hunter's page adds a wrinkle worth naming because it will catch someone. It served French copy to a visitor in India (Démarrer, À partir de $7.50/mois) with USD figures. The language localised and the currency did not. Checking the currency selector is not enough on a page like that: check whether the number and the words around it are describing the same market.

The check costs ten seconds. Load the page in a private window, find the currency control, and note whether the number moved when you set it to yours. If there is no control and the currency is not yours, no conversion fixes it: a vendor's foreign-currency list price is rarely the spot rate.

Twenty-one pricing pages, read on one day

Fourteen of the 21 pages earned a row. Every one was fetched on 25 August 2026 with a browser user-agent, from one machine, in one pass. [vendor] means read off the vendor's served page. [not tested] means the row needs a rendered browser or a checkout, and this pass ran neither. Nothing here is a measurement of a product.

VendorWhat a reader seesWhat the raw response also holdsThe gapOur recordBasis
NICE CXone$110 / $135 / $169 / $209 / $249 per agent/mo11 integer markers incl. $13, $27, $35, $41, $54$71 was never on the page$110, verified 2026-08-22[vendor]
Salesfinity$299, plus $0.30JSON-LD price 149, priceValidUntil 2026-12-31$150/user/mo, $1,800/user/yr$299, verified 2026-08-12[vendor]
KixieNo dollar figure at all$30/user/mo, $0.011/text, $5.00/number in FAQ JSON-LDEntire rate card, machine-onlynull, verified 2026-08-12[vendor]
KoncertNo dollar figure at allBare integers 6, 7, 29, 79, 99 in a suppressed tableNo currency, empty period spannull, verified 2026-08-07[vendor]
Apollo.io$0.025 to a text extractorOfferCatalog: 0, 49, 99, all billingDuration P1M65 appeared nowhere; the rendered page reads 49 annual, 79 and 119 above it$69, re-read in a browser 2026-08-26[vendor]
ProspeoZero27 dollar-shaped tokens, $20 through $33None of the 27 is money$49, verified 2026-08-07[vendor]
Instantly$47/mo and $37.6 /monthly, same pageBoth sides of the toggle served25% between two labels that both say monthly$47, verified 2026-08-06[vendor]
ElevenLabs$6/mo Starter; $22 with "first month 50% off $11"Annual equivalents $5 / $18.33 / $82.50 / $249.17 / $825Promotional rate shown larger than list$6, verified 2026-08-05[vendor]
Cal.com$12 and $28 per user/mo, YEARLY defaultNothing. The monthly side is not in the documentOne side of a two-sided price$0 free tier, verified 2026-08-11[vendor]
Trellus$99.99 and $149.99A 34.99 element at scale3d(0.6), plus matching JSON-LDSchema matches the rendered page$99.99, verified 2026-08-12[vendor]
Hunter$34/mo Starter, yearly basis$49 monthly-billing rate inside class="d-none"31% between the shown rate and the hidden one$49, verified 2026-08-07[vendor]
Dropcontact79 € and 120 € /monthly at slider defaultJSON-LD: Starter monthly, no commitment, 29 EURDefault view is 172% above the published floornull, verified 2026-08-07[vendor]
lemlist$55 / $69 / $109$9/email, $15/number, $20/user WhatsApp in tooltipsThree real add-on rates behind a hoverNot re-read this pass[not tested]
Genesys Cloud CX$75 / $115 / $155 / $240 per user/mo, billed annuallySame four, plus "Get custom pricing" on every tier$75/user/mo is the $900/user/yr floornull, verified 2026-08-12[vendor]

Two things fall out. First, the gap is almost never a lie: in most rows both numbers are true statements about something. Second, the cleanest pages are not the cheapest. Trellus and Genesys publish figures that survive every check here, and Genesys still routes every tier to "Get custom pricing".

What one bad read costs on a real shortlist

Modelled from published rates, not measured. Take a buyer who builds a twelve-month budget from pricing pages in one afternoon, which is what actually happens.

ErrorPer unitUnit countMonthly errorTwelve-month error
NICE recorded at $71 against $110$39/agent/mo50 agents$1,950$23,400
Salesfinity read from JSON-LD (149) not the page (299)$150/user/mo8 reps$1,200$14,400
Trellus recorded at $30 against $99.99$69.99/user/mo8 reps$559.92$6,719.04
Instantly $37.6 annual basis read as monthly billing$9.40/mo1 workspace$9.40$112.80
Lead411 $49 read as a workspace price, not per seat$49/seat/mo6 seats$245$2,940
ElevenLabs $11 promo read as list ($22)$11/mo1 workspace$11$132 after month one

The two per-seat rows are the ones that hurt, and per-seat is the assumption a business case gets wrong most quietly. Lead411 publishes $49 and the word seat appears nowhere on the public pricing page. Every figure on it is per seat, which the checkout states.

For a team of six that is the difference between $49 and $294 a month.

Compare that against what the checks cost. Twelve minutes per vendor, on a shortlist of five, is one hour. The NICE row alone repays that hour at $23,400, which nobody should expect to sustain and is a fair description of what the first hour is worth.

The twelve-minute price audit

Run this per vendor before the number goes anywhere. It is the internal procedure this site uses, timed against our own sessions. Do not create accounts, do not enter payment details, and do not defeat a bot check. If a page blocks you, that is a finding, and the honest record is "not verified".

Steps 1 to 4: the rendered page, four minutes

1. Follow the redirects first. curl -s -o /dev/null -w "%{http_code} %{url_effective}\n" -L "$URL". A pricing page landing on a different domain, a 404, or an acquirer's site is the whole answer. Six of our 264 records are marked unreachable and every one was found this way.

2. Load it in a private window and record the currency and the billing toggle's default state before reading any number. A previous session's toggle state persists and will hand you the wrong basis without telling you.

3. Flip the toggle and record both numbers. Write down which is monthly-billing and which is the annual rate divided by twelve. If the page only shows one after flipping, the other side is not in the document and you have half a price.

4. Drive every interactive control to your real volume. Sliders, seat steppers, credit selectors. Lusha's Pro tier is $69.90 at 7,200 credits and $249.90 at 26,400, so the tier name is not the price, the slider is. Its seat stepper revealed a $37.45 charge that grants no credits and that the sale does not discount.

Steps 5 to 8: the layers underneath, five minutes

5. Fetch the raw HTML and diff it against what you saw. This is the step nobody runs and it is the one that caught every error in this post.

curl -s -A "Mozilla/5.0 ... Chrome/126.0" "$URL" -o /tmp/p.html
grep -o 'display: *none' /tmp/p.html | wc -l
python3 -c "import re; [print(b[:600]) for b in re.findall(r'application/ld.json[^>]*>(.*?)</script>', open('/tmp/p.html').read(), re.S)]"

6. Read the JSON-LD and compare every number to the screen. Look at price, priceCurrency, priceValidUntil and billingDuration. A priceValidUntil in the past means the block is stale. A billingDuration of P1M against a page saying annual means one of the two is wrong and you do not yet know which.

7. Search the raw HTML for tooltips and meta descriptions. grep -o 'tooltip"[^}]*\$[0-9][^"]*' found three real lemlist add-on rates that no flat text extraction surfaces. Lead411's $49 is in its meta description and its $899 is a sweepstakes prize, which is exactly the shape of the Woodpecker error.

8. Discard any dollar token that has no currency symbol and no period in the markup. On a Next.js site, treat every bare $NN in a serialised payload as a reference marker until you have found the same figure in rendered text. On nice.com that rule alone deletes eleven of sixteen candidates.

Steps 9 to 11: the surfaces that have to be right, three minutes

9. Go to the checkout and stop before paying. It is the only surface on the site that has to be accurate, because it is where money moves. Lead411's checkout says $49.00 Monthly / Seat / 1000 Exports, and that its middle tier grants exactly the same 1,000 exports as the entry tier for 206% more money. The pricing page never uses the word seat.

10. Find the meter. Search the page and docs for credit, per record, per minute, overage, included. A credit is not a unit: on Lusha a phone number costs 5 credits, on UpLead one credit buys an email and a mobile together. Same headline rate, two different things.

11. Read the terms. This is where the pricing page gets contradicted and almost no competing page looks. BookYourData's headline says "No Subscriptions" while its section 3.7 describes binding-term subscriptions with collections exposure. Salesfinity advertises "unlimited dials" and its section 1.2 caps each user at 10,000 a month.

CheckToolTimePassFail
Redirect tracecurl -L -w url_effective20 secLands on the vendor's own pricing URLDifferent domain, 404, or acquirer
CurrencyPrivate window20 secYour currency, or a selector you setNo control and not your currency
Billing basisToggle both states60 secBoth numbers recorded with their basisOnly one side exists in the document
Interactive controlsBrowser90 secPriced at your real volumeTier price moves and you read the default
display:none scangrep30 secNo suppressed price blocksA price table you cannot see on screen
JSON-LD diffpython3 + grep60 secSchema figures match the rendered pageAny mismatch, or a stale priceValidUntil
Marker discardManual read60 secEvery candidate has a currency and a periodBare $NN inside a serialised payload
CheckoutBrowser, stop before pay4 minCheckout total equals the page figureAny difference. The page is marketing
Meter and termsDocs plus ToS3 minUnit cost computable from published numbersMeter not published. Record it as absent

The threshold that decides everything: if the checkout number does not equal the pricing-page number, the pricing page is marketing and the checkout is the price. If you cannot compute a unit cost from published numbers alone, record "meter not published", which is a finding rather than a gap in your research.

What the audit cannot detect

It cannot tell you the discount you would actually be offered. Every figure it produces is list, and list is the opening position on any contract with a salesperson attached. The gap between list and paid is what this market hides hardest, and no amount of reading a public page surfaces it.

It cannot detect a price about to change. Our sweep re-read 96 listing prices and found roughly half had moved or were wrong, over weeks. Amazon Connect more than doubled while we held the old number: $0.018 a minute survives only in an appendix under "Customer Basic", and a new buyer pays $0.038.

It cannot detect the tier you will actually need. If phone numbers, API access, CRM write-back or SSO sit above the first priced tier, the published price is decorative for you. And it cannot open a page that blocks you. lusha.com/robots.txt names ClaudeBot under Disallow: /, which is policy rather than bot protection, so Lusha's verification date stays put.

Does the FTC actually ban any of this?

Describing published rules is not legal advice, and this section is a boundary marker rather than an authority. The short version: the federal rule aimed squarely at this behaviour exists, is in force, and does not cover business software.

The Trade Regulation Rule on Unfair or Deceptive Fees, 16 CFR Part 464, was published at 90 FR 2066 on 10 January 2025 and took effect 12 May 2025. Section 464.2(a) makes it "an unfair and deceptive practice" to "offer, display, or advertise any price of a covered good or service without clearly and conspicuously disclosing the total price". Section 464.2(b) requires the total price to be disclosed "more prominently than any other pricing information", which is the ElevenLabs promotional-versus-list problem written as a rule.

Then read the definitions section. Covered good or service means "(1) Live-event tickets; or (2) Short-term lodging". That is the entire scope. Concert tickets and hotel rooms.

A B2B SaaS pricing page serving one number to a buyer and another to a crawler is outside it.

Hacker News item 34509188 (317 points, 416 comments, 24 January 2023) opens with the obvious question: "How is this not textbook false advertising?" That is one person's framing on a public thread, and the answer three years later is that it now is, for concert tickets and hotel rooms, by rule. For the software you are buying it remains a case-by-case question under a general statute, which is a different thing to have on your side.

The subscription half moved in the opposite direction and is worth getting right, because a great many pages still describe the 2024 position as current law. The FTC's amended Negative Option Rule, published at 89 FR 90476 on 15 November 2024 and widely called the click-to-cancel rule, was vacated in full by the Eighth Circuit in Custom Communications, Inc. v. Federal Trade Commission, Nos. 24-3137 and 24-3388, decided 8 July 2025, on procedural grounds under the FTC Act.

The Hacker News thread on that decision (item 44504699, 604 points, 559 comments, 8 July 2025) carries the least comfortable reading of it. fwlr writes: "The FTC was warned at the time that they were flouting required procedures and that their rule would therefore not survive legal scrutiny. Lo and behold it did not." One person's characterisation, not a finding of fact. The consequence for a buyer is the same either way: the rule is gone.

InstrumentCitationPublishedApplies fromStatus on 2026-08-25Covers B2B software?
Rule on Unfair or Deceptive Fees16 CFR 464 / 90 FR 20662025-01-102025-05-12In forceNo. Live-event tickets and short-term lodging only
Negative Option Rule, 2024 amendments89 FR 904762024-11-152025-01-14Vacated 2025-07-08Would have. Now moot
Custom Communications v. FTC8th Cir. Nos. 24-3137, 24-3388Decided 2025-07-08ImmediatelyFinalVacated the rule above
Revision conforming rules to court decisions91 FR 65072026-02-122026-02-12In forceRecodified the pre-2024 rule text
Prenotification Negative Option Rule (ANPR)91 FR 123182026-03-13Not yetComment stageUnknown. Scope is what the ANPR asks about
FTC Act s.5 / ROSCA, 15 U.S.C. 8403Statute1914 / 2010In forceIn forceYes, but enforcement is case by case

What is left is section 5 of the FTC Act and ROSCA, enforced case by case rather than by rule. Two live federal actions show the shape, and both are allegations, not findings: FTC v. Shutterstock Inc., 1:26-cv-03955 (S.D.N.Y., filed 13 May 2026), and FTC v. Hims & Hers Health, Inc., 3:26-cv-07871 (N.D. Cal., filed 29 July 2026), both pleaded under 15 U.S.C. 45. Neither has been ruled on.

The practical consequence for a B2B buyer is unglamorous. There is no rule you can point at that requires a software vendor to put the total price on the pricing page. The FTC opened a fresh advance notice of proposed rulemaking on 13 March 2026 at 91 FR 12318 asking whether the old rule needs amending, which means the question is live and unanswered.

Until it is answered, the checkout is your only enforcement mechanism.

What goes wrong in month three

The number and the invoice diverge again after you sign, by different mechanisms. This is the part practitioners write about in public, and it is worth quoting them: vendors publish the rate, only buyers publish the surprise.

On Hacker News item 20464486 (172 points, 124 comments, 17 July 2019), a commenter describes an annual renewal: "My renewal date for this next year came without warning and I was charged again, without recourse." That is one person's characterisation, not a finding of fact. What makes it useful is the reply, where dangrossman shows the vendor did disclose the renewal at signup. Both are right, and the gap is the problem: disclosure at signup and a reminder before the charge are different things.

The contract terms are where this becomes money. UpLead publishes a 60-day cancellation notice, use-it-or-lose-it credits, and a fresh credit charged when a contact's company data changes. A 90-day notice window on an annual term means there are 275 days a year on which you cannot leave. Lead411's published terms govern five plans the vendor stopped selling in 2025, which tells you how often anyone reads them.

Credit expiry is the quiet one. Snov.io sells phone tokens on a separate subscription at $0.02 with a 90-day expiry. HubSpot credits are $0.010 each and expire monthly. A budget built on a per-record cost is wrong by however much of the allowance goes unused. What happens when credits run out mid-month is its own post.

And the largest vendor in the category publishes no price whatsoever. ZoomInfo's 10-K for FY2025, filed 12 February 2026 (CIK 0001794515), reports revenue of $1,249.5 million, net revenue retention of 90% against 87% a year earlier, and 1,921 customers above $100,000 in annual contract value.

Those are the only dated ZoomInfo numbers a buyer can rely on, and they come from a securities filing rather than a pricing page.

Which check to run on which vendor

You will not run twelve minutes on 264 tools and neither did we. Triage by what the page already tells you.

  • Page shows a number and a checkout exists. Run steps 1 to 4 and step 9 only. Six minutes. The checkout settles it and the layers underneath stop mattering.
  • Page shows a number and there is no checkout. Run everything. This is where every error in this post came from, because the number can never be confirmed against a transaction. Apollo, NICE and Genesys all sit here.
  • Page shows no number at all. Skip to steps 5 and 6. Kixie and Koncert both look like gated vendors and both are serving figures in the markup. Then record the vendor as unpriced regardless of what you find, because a figure in structured data is not shown to a buyer.
  • Page is built on Next.js or another RSC framework. Do step 8 before anything else. Check the page source for self.__next_f. If it is there, every bare dollar-integer in the payload is guilty until proven otherwise.
  • Page blocks you. Stop. Record the block and the date. Do not switch user-agents to get past a robots.txt disallow, and do not solve a bot check. An unverified field is honest; a circumvented one poisons every figure downstream of it.

The decision this post exists to produce is one line long: before any vendor number goes into a budget, open that vendor's checkout and read the total, or write "not verified" next to the figure. Nothing else on this page matters as much as that, and it is executable this week on every self-serve tool on your shortlist.

If your shortlist is mostly gated, ask the salesperson for the per-seat figure, the minimum seat count, the billing period and the overage rate in an email rather than a deck. Decks are built by marketing. Emails are written by the person who will be held to them. On the enterprise CCaaS shortlist, where seven of 23 platforms publish a rate at all, that email is the only price you get.

That request lands better than it reads. On Hacker News item 37717689 (46 points, 61 comments, 30 September 2023), a thread specifically about B2B vendors who publish real numbers, thebruce87m writes: "We're even more tired of the asking. ‘Contact us’ == ‘speak to us so we can gauge how much we can shake you down for’." One person's characterisation, not a finding of fact. It is also what the buyer on the other side of your email is assuming, which is why a written figure costs the vendor less goodwill than a call does.

Where this method runs out

Three limits, before anyone treats the audit as complete. The first is that a layer diff proves a discrepancy and never explains it. When Kixie's structured data carries three prices its rendered page omits, we can show both layers and date them. Whether that is a CMS field nobody updated or a deliberate choice, we do not know and do not claim to.

The second is that our corpus is not a random sample. The 21 pages re-read on 25 August 2026 were chosen because they had already produced findings or their records were due. A census of all 264 would give a different rate than ten in 21, and we have not run one.

The third costs us. Every correction here was found because somebody re-read a page, and no mechanism catches an error nobody goes back to. npm run seo warns on any price older than 90 days, and 152 of 264 records carry a verification date, leaving 112 that do not.

A stated limit, not a solved problem.

So why is the price different at checkout?

Because the pricing page was never the offer. It is a document with four or five layers, built by different teams on different timelines, and the layer you read depends on whether you are a person, a crawler, or a script with a regular expression. All the numbers can be true at once and only one is a price.

The version that fits on a sticky note: a price has a currency symbol in the markup, a stated period, and a buyer who can see it without opening DevTools.

Ours failed that test four times in public. NICE at $71 against $110 should worry you most, because nothing about $71 looked wrong, it survived two independent research processes, and only a re-read caught it.

Do the twelve minutes. Or do four of them: private window, flip the toggle, drive the slider, open the checkout and read the total. That catches the four mechanics that cost real money and it is the difference between a number you can defend in a budget meeting and a number you screenshotted.

Questions

Is the price in a site's JSON-LD the real price?
No. It is what the vendor tells search engines, generated by a different pipeline from the rendered page, and it drifts. Salesfinity's JSON-LD carried price 149 on 25 August 2026 while the page showed $299. Kixie's carries a full rate card its page does not show at all. Treat structured data as a lead worth chasing, then confirm it in rendered text or at the checkout before you use it.
Why does a pricing page show dollar signs that are not prices?
React Server Components serialise the page into a payload that uses a dollar prefix for internal references: $1 for the identity component, $L18 for a lazy chunk, $undefined for absent values, and bare integers for repeated values. On nice.com/pricing on 25 August 2026 there were 518 dollar-prefixed tokens, of which eleven distinct integer-looking ones were markers rather than money. Check the page source for self.__next_f before trusting any grep.
How do I tell whether a monthly price is really monthly?
Flip the billing toggle and record both numbers. If flipping produces nothing new, the other side is not in the document. Instantly's page shows $47/mo in one block and $37.6 /monthly in another on the same fetch, and the second is the annual rate divided by twelve. ElevenLabs states its own arithmetic in its FAQ: annual billing means paying for ten months, so the annual-equivalent Starter is $5 against a monthly-billing $6.
Does the FTC junk fees rule cover B2B software pricing?
No. 16 CFR Part 464 took effect on 12 May 2025 and its definitions limit covered goods and services to live-event tickets and short-term lodging. It requires the total price to be shown more prominently than any other pricing information, but only for those two categories. Software pricing is left to section 5 of the FTC Act and ROSCA, enforced case by case.
Is the click-to-cancel rule still in force?
No. The FTC's amended Negative Option Rule at 89 FR 90476 was vacated in full by the Eighth Circuit in Custom Communications, Inc. v. FTC, Nos. 24-3137 and 24-3388, decided 8 July 2025, on procedural grounds. The FTC recodified the pre-2024 rule text at 91 FR 6507 on 12 February 2026 and opened a fresh advance notice of proposed rulemaking at 91 FR 12318 on 13 March 2026. Pages describing the 2024 rule as current law are out of date.
What is the single fastest check if I only have two minutes?
Open the checkout in a private window, enter your real seat count and real volume, and read the total before the final button. Do not pay. It takes about four minutes on a self-serve tool and it settles the billing basis, the per-seat question, the currency and any slider default in one move. If the checkout total differs from the pricing page, the pricing page is marketing.
What do I do about vendors with no checkout at all?
Run the raw-HTML and JSON-LD steps to see whether a figure exists in the markup, then record the vendor as unpriced anyway, because a figure a buyer cannot see is not a price. Then get the per-seat figure, the minimum seat count, the billing period and the overage rate in an email from the salesperson. On this site 108 of 264 tools have no self-serve checkout and 114 publish no price.
Should I use a competitor's comparison page to find a gated vendor's price?
No, and this is where it leaks most often, because a competitor's versus page is frequently the only place a gated vendor's number appears. That is exactly why it cannot be used. Air.ai's $0.11 a minute reached this site that way and had no vendor origin at all. If the vendor does not show it to a buyer, in a currency, for a stated period, there is no price to record.
How often do these prices actually change?
Fast enough that a figure without a date is unusable. One sweep on this site re-read 96 listing prices and found roughly half had moved or were wrong. Amazon Connect's per-minute rate more than doubled while the old figure stood: $0.018 survives only in an appendix under Customer Basic, and a new buyer pays $0.038. Date every price you record and re-check anything older than 90 days.

Tools mentioned

All tools →

Sources

Source interests are labelled. Almost everything published about this subject is written by someone selling into it.

More from the blog

All posts →