Skip to content

v1.0.1 — a marker that fired on good pages

Choose a tag to compare

@jehrr jehrr released this 16 Sep 16:12
· 15 commits to main since this release

A challenge marker was wrong, and it was one that could have cost money. cf-turnstile fired on five of five pages BBB actually served. Only the signal ordering in detect_page_state — the listing payload is checked before any marker — kept a good page from being reported as a challenge, and challenge is the state that spends.

What was measured

Counted across every capture taken 2026-09-16:

served (6) challenge (2) hard block
cf_chl_opt 0 7, 7 0
__cf_chl 0 3, 3 0
cf-chl- 0 1, 0 0
challenges.cloudflare.com 0 1, 0 0
cf-turnstile 1 on 5! 1, 0 0
/turnstile/v0/api.js 0 0, 0 0

The cause is not BBB. 2Captcha's Scraping Browser auto-solve extension injects chrome-extension://kjmkgkdkpedkejedfhmfcenooemhbpbo/…/turnstile/hunter.js with a cf-turnstile-response input into every page it loads, and every capture in this repo was taken that way.

Fixed

  • cf-turnstile and /turnstile/v0/api.js removed from BOT_CHALLENGE_MARKERS; challenges.cloudflare.com added.
  • The marker guard in the suite had been passing for the wrong reason — it ran only against BBB's 404, fetched with plain curl, which carries no extension injection. It now also runs against a listing fetched through the Scraping Browser, and asserts in both directions: no marker on a served page, every marker firing on a real challenge, and each excluded string really present on a served page.

352 offline checks, up from 340.

Which captcha this site actually uses

BBB sits behind Cloudflare and refuses in two shapes — both HTTP 403, both titled … | Better Business Bureau®:

what it is solvable
Just a moment... a Cloudflare Managed Challenge (Turnstile) yes — a real test
You have been blocked a flat refusal: no widget, no sitekey no — a solve buys nothing

Separately, BBB has its own reCAPTCHA Enterprise on every page (render=<sitekey>, so v3 rather than a v2 checkbox), guarding its review and complaint forms. This scraper never touches those forms — so no captcha was ever solved, and nothing was ever spent on one.