How Bot Management scores a request
Cloudflare calculates the Bot Score at its edge — the network of servers between the visitor and the website — before the origin server (the customer's actual backend) ever sees the request. The inputs are the JA4 TLS fingerprint (a signature of how the client opens an encrypted https connection), the HTTP/2 SETTINGS frame (low-level connection settings that often give away automation tools), IP reputation, ASN type (the kind of network the IP belongs to, e.g. a datacenter vs. a home ISP), request rate patterns, and — when a JavaScript challenge has fired previously — the __cf_bm cookie carrying the result. The score is exposed to the customer via the cf.bot_management.score field in Workers and in firewall rules.
The customer decides what to do with the score. A common setup is block under 30, challenge 30–60, allow above 60, with allowlists for verified bots (Googlebot, Bingbot — Cloudflare maintains the list and labels them). Because the model is shared across the whole network, a scraper that fingerprints as Bot Score 12 will get blocked or challenged on every protected site at once.
Bot Management vs Turnstile vs Bot Fight Mode
Three Cloudflare products are easy to mix up, so here is how they differ:
| Product | Tier | What it does |
|---|---|---|
| Bot Fight Mode | Free | Blunt heuristic block of known datacenter / cloud IPs. Easy to identify (blocks before JS runs) and the lightest of the three layers; a residential proxy changes the IP reputation it keys on. |
| Bot Management | Enterprise | Continuous ML scoring per request. Authorized automation needs a coherent, consistent browser configuration across all four detection layers to score as a normal client. |
| Turnstile | Free / managed | A widget you embed on a specific endpoint (login, signup). Issues cf_clearance on solve. Can be invoked by Bot Management as a challenge. |
A single protected site can run all three in layers: Bot Fight Mode catches the cheap traffic, Bot Management scores the rest, and Turnstile is shown when the score is borderline.
How different clients score
Scores as a bot: Python requests with a Chrome User-Agent — the header claims Chrome but the connection fingerprint doesn't match, so Bot Score lands around 3. Playwright with default settings also scores low, because CDP (the Chrome DevTools Protocol it uses to drive the browser) leaks and the score is ~15. Datacenter proxies of any flavour, and residential proxies with a mismatched timezone, score poorly too.
For authorized automation behind the free tier (Bot Fight Mode): curl_cffi with Chrome impersonation (it copies Chrome's real TLS fingerprint) plus a residential proxy generally presents a consistent client.
For authorized automation behind Bot Management: a real browser such as Camoufox or CloakBrowser with a clean residential or ISP IP, a matched Accept-Language header, and patient request pacing keeps the configuration coherent. High-volume workflows on sites you are permitted to access often route through a managed API. The tell-tale sign that Bot Management (not the free tier) is in front of you is the cf-mitigated header on a block — Bot Fight Mode blocks return a plain 403 with no cf-mitigated.
