Skip to main content
How It Works

How Cloudflare Decides You're a Bot (Without a CAPTCHA)

How Cloudflare detects bots without a CAPTCHA — TLS/JA4 fingerprinting, HTTP/2 signatures, headless-browser checks, behavioral analysis, and a 1–99 bot score, explained for developers and site owners.

How Cloudflare Decides You're a Bot (Without a CAPTCHA)
The gist
  • Cloudflare decides you're a bot mostly before you see a challenge: your TLS handshake, HTTP/2 settings, browser fingerprint, IP reputation, and behavior get scored into a single 1–99 bot score in microseconds.
  • It fingerprints your connection, not just your browser. A User-Agent that says "Chrome" over a TLS/HTTP-2 fingerprint that says "Python" is the single biggest tell; every layer has to tell the same story.
  • The visible CAPTCHA is mostly gone. Cloudflare replaced puzzles with the invisible Managed Challenge and Turnstile, which run background browser checks and hand you a cf_clearance cookie when you pass.

Cloudflare decides you're a bot mostly before you ever see a challenge. It scores dozens of signals — your TLS handshake, HTTP/2 settings, browser fingerprint, IP reputation, and behavior — into a single 1–99 "bot score" that machine-learning models compute in microseconds. A visible puzzle is the last resort, not the first.

A few terms up front. A fingerprint here is a stable signature derived from how your client speaks a protocol, not what it claims to be. The TLS ClientHello is the first message a browser sends when it opens an HTTPS connection. JA3 and JA4 are two ways of hashing that message into a short identifier. A WAF (Web Application Firewall) is the rule engine site owners use to act on the score. Keep those four straight and the rest follows.

The whole pipeline, in one picture

Every request runs a gauntlet of mostly-passive checks, and the output is one number. Many are gathered server-side at the network edge before your browser receives a single byte; others run invisibly in JavaScript once the page loads. Each feeds a bot score from 1 to 99, where 1 means Cloudflare is confident the request is automated and 99 means it's confident it's human.

Flow diagram: a request passes through edge signals (TLS JA4, HTTP/2, IP and ASN), then JavaScript detections, then behavioral analysis, producing a 1-to-99 bot score that a WAF rule turns into Allow, Managed Challenge, or Block.
The detection pipeline. Edge signals and behavior feed a 1–99 score; the site owner's WAF rule decides what happens next.

Site operators don't block at a fixed number. They write WAF rules that combine the score with other attributes. Per Cloudflare's Bot Analytics guidance: "We generally consider traffic below 30 to be automated, but customers might choose to challenge traffic below 40 or block traffic below 10."

This is why a plain requests.get() in Python is often blocked with a 403 on the very first round trip: it never had a chance to "act human," because its TLS handshake already gave it away.

Cloudflare runs this at enormous scale, which is what makes the machine learning viable. Its bot-score documentation notes the ML engine "leverages our global network, which proxies billions of requests daily, to identify both automated and human traffic." That scale is the training data — and the volume of automated traffic is now staggering. By June 3, 2026, Cloudflare Radar data showed bots had crossed the halfway mark: 57.4% of HTML requests across Cloudflare's network were automated versus 42.6% human, with CEO Matthew Prince noting that agentic traffic is "growing so fast that bots have now passed human traffic online for the first time in the Internet's history."

What is TLS fingerprinting? (JA3 and JA4)

TLS fingerprinting identifies your client software from the way it opens an encrypted connection. When any client starts a TLS connection (the "s" in HTTPS), it sends a ClientHello — the opening message of the handshake — listing the TLS version, cipher suites, extensions, elliptic curves, and point formats it supports. Different software stacks send these in different combinations and orders, and that combination is distinctive enough to identify the library or browser.

JA3, created by Salesforce researchers in 2017 and later adopted by Cloudflare, hashes those fields into a 32-character MD5 string. The problem: in early 2023, Chrome 110 began randomizing the order of its TLS extensions, so the same Chrome browser now produces a different JA3 hash on every connection, breaking JA3 for modern browsers (though it still flags non-browser clients like Python requests and curl, which don't randomize).

JA4, developed by FoxIO and launched in September 2023, fixes this. Per Cloudflare's documentation, "JA4 fingerprint adds new functionality by sorting ClientHello extensions and reducing the total number of unique fingerprints for modern browsers." Because it sorts before hashing, it's immune to Chrome's randomization, and it adds signals like ALPN that JA3 lacked. By 2026, Cloudflare, AWS WAF, Akamai, and VirusTotal all use JA4.

The killer signal is a mismatch. If your User-Agent header claims "Chrome 120" but your TLS fingerprint matches Python's urllib3, that inconsistency is itself strong evidence of automation. As one detection engineer put it: you can dodge navigator.webdriver perfectly and still get caught because "your JA3, canvas fingerprint, and plugin list aren't telling the same story."

What is HTTP/2 fingerprinting?

HTTP/2 fingerprinting profiles how your client negotiates the HTTP/2 protocol, a layer sitting just above TLS. HTTP/2 is a binary protocol with configurable parameters, and different implementations set them differently. Akamai's research popularized the technique, finding HTTP/2 fingerprints alone can distinguish browser families with high accuracy.

The Akamai-style fingerprint captures four things, written as pipe-separated sections (SETTINGS|WINDOW_UPDATE|PRIORITY|PSEUDO_HEADER_ORDER):

  • The SETTINGS frame parameters (header table size, max concurrent streams, initial window size), in the order sent.
  • WINDOW_UPDATE: the connection-level flow-control increment.
  • PRIORITY frames: stream dependencies, weights, and exclusivity flags.
  • Pseudo-header order: the sequence of :method, :authority, :scheme, :path, hardcoded per browser (Chrome uses m,a,s,p).

Chrome sends specific SETTINGS values, while curl and Go's net/http send different defaults that immediately reveal a non-browser. Crucially, this catches a common evasion: a scraper can wrap a Chrome-impersonating TLS stack around its own unmatched HTTP/2 implementation, matching JA4 but failing the HTTP/2 check. Cloudflare combines the layers, so every one of them has to agree.

Flow diagram: TLS fingerprint (JA4), HTTP/2 fingerprint, JS environment, and HTTP headers all feed into a check that asks 'do they tell the same story?'. If they agree, the request looks human; if one disagrees, it is flagged as a bot.
Consistency is the real test. Four independent signals have to agree; one that disagrees flags the request.

How does Cloudflare detect headless browsers?

When passive signals aren't decisive, Cloudflare injects JavaScript that inspects the browser environment. Its JavaScript Detections (JSD) engine "performs a lightweight, invisible JavaScript injection on the client side of any request" to identify headless browsers and other automation. It runs without pausing the visitor and populates a pass/fail result (cf.bot_management.js_detection.passed).

Headless browsers leak identity at multiple layers:

  • navigator.webdriver returns true, the most obvious tell, set by default in automated Chrome. Even patching it leaves a detectable property-descriptor anomaly.
  • Canvas and WebGL fingerprinting: the page draws hidden graphics, and because headless browsers often fall back to software rendering instead of a real GPU, the output pixels (and their hash) differ from a real browser's.
  • Missing plugins and media codecs, plus inconsistent navigator properties.
  • Chrome DevTools Protocol (CDP) artifacts: automation frameworks leave side effects like modified error stack traces and injected cdc_ variables (Selenium).

Beyond invisible detection, Cloudflare can escalate to a challenge. Its non-interactive JavaScript challenge runs background tests (proof-of-work, probing for browser APIs) with no user interaction. "I'm Under Attack" mode forces a JavaScript challenge on every visitor and is meant only for active DDoS attacks.

Managed Challenge, Turnstile, and the end of the CAPTCHA

The Managed Challenge is Cloudflare's adaptive, mostly invisible replacement for CAPTCHA. Instead of always showing a puzzle, in Cloudflare's own words, it "defers the decision about whether to serve a visual puzzle to a later point in the flow after more information is available from the browser." When triggered, it first runs "a series of small non-interactive JavaScript challenges" — proof-of-work, proof-of-space, probing for web APIs, browser-quirk detection — and only shows a visible interaction if confidence is still low.

The numbers back it up. In "The end of the road for Cloudflare CAPTCHAs" (April 2022), Cloudflare reported it "reduced the number of CAPTCHAs we choose to serve by 91%… reduce the visitor time spent in a challenge from an average of 32 seconds to an average of just one second." That "Verifying you are human…" interstitial you sometimes hit is the Managed Challenge, usually just the fast, silent check.

Turnstile is Cloudflare's standalone CAPTCHA alternative that any website can embed, even without routing traffic through Cloudflare. It runs a client-side challenge in the background and issues a token the server validates via Cloudflare's Siteverify API. It comes in three modes: Managed (shows a checkbox only if risk is high), Non-Interactive (visible widget, no interaction), and Invisible (completely hidden). It can also use Private Access Tokens (built with Apple and Google on the Privacy Pass protocol) to validate a device via manufacturer attestation instead of fingerprinting. Tokens are single-use and expire after 300 seconds; Managed mode is free for unlimited use.

When you pass a challenge, Cloudflare sets a cf_clearance cookie that acts as your proof of passage; later requests carry it and skip re-challenging until it expires (30 minutes by default). The cookie is tied to the specific visitor and device it was issued to. In practice, rotating your IP or User-Agent mid-session (say, rotating a proxy) tends to get it rejected, and likely your TLS fingerprint too, so you're challenged again.

Sequence diagram: a flagged visitor request goes to the Cloudflare edge, which returns a non-interactive JavaScript challenge; the browser returns a solution; on pass, Cloudflare sets a cf_clearance cookie tied to the session (IP and User-Agent); later requests carry the cookie and are served without a re-challenge until it expires.
A passing browser gets a cf_clearance cookie tied to its session. In practice, rotating its IP or UA (and likely its TLS fingerprint) tends to void it.

A related cookie, __cf_bm, is used by Bot Management to "smooth out the bot score and reduce false positives for actual user sessions"; it expires after 30 minutes of inactivity and its contents are encrypted so only Cloudflare can read them.

How the machine-learning bot score actually works

Cloudflare stacks several detection engines, each of which can influence the score:

  • Heuristics processes every request, matching against a database of known malicious fingerprints. It "gives automated requests a score of 1 for high-confidence, deterministic detections," occasionally 29 when it's still assessing overlap. It's the fastest layer.
  • Machine Learning is the primary engine. Per Cloudflare's docs, "The Machine Learning (ML) engine accounts for the majority of all detections… Produces most scores between 2 and 99." Input features (headers, session characteristics, browser signals) map to the predicted probability the client is human; high-confidence heuristic labels train it.
  • JavaScript Detections is the headless-browser detector described above, contributing a pass/fail.
  • Anomaly Detection is an older unsupervised engine (now deprecated for new customers) that learns a site's baseline and flags outliers.
Flow diagram: four detection engines — Heuristics (score 1 or 29), Machine Learning (scores 2 to 99, most detections), JavaScript detections (pass or fail), and Anomaly detection (baseline outliers) — all feed into a single 1-to-99 bot score.
Four engines, one score. Machine learning does most of the work; heuristics handle the fast, deterministic calls.

Beyond the first request, Cloudflare also watches behavior over time: request timing and cadence, navigation order, request rate, and, on interactive challenges, pointer movement, keystroke timing, and scroll behavior. Traffic that arrives in a perfectly even, machine-paced rhythm looks nothing like a person. This behavioral analysis, integrated in 2019, uses unsupervised learning to build a per-site baseline, and it's harder to evade because the anomalous behavior is often a direct result of the bot's goal.

What network and reputation signals does Cloudflare use?

Because Cloudflare sees a large share of global web traffic, IP and ASN reputation are powerful signals. An ASN (Autonomous System Number) identifies the network an IP belongs to; datacenter ASNs (AWS, Google Cloud) draw more suspicion than residential ISPs, and IPs with abuse history score worse. This threat intelligence is shared across Cloudflare's whole customer base.

To avoid blocking useful automation, Cloudflare maintains a verified-bots allowlist (Googlebot, Bingbot, uptime monitors, and more) exposed via cf.bot_management.verified_bot. It validates these primarily through reverse DNS: it takes the IP and confirms its hostname matches the claimed operator, then backs that with ASN-block validation and public IP lists. This is why a fake "Googlebot" from the wrong network gets challenged: the rDNS check fails.

More recently, Cloudflare introduced Web Bot Auth, which uses cryptographic HTTP message signatures (Ed25519 keys, built on RFC 9421) so AI agents and crawlers can prove their identity rather than relying on spoofable User-Agents. It also shipped AI Labyrinth, which traps misbehaving AI scrapers in a maze of AI-generated decoy pages and fingerprints them from it.

Fascinated by what the browser does under the hood?

So are we — BumbleTap lives in that layer, turning any keystroke into an action on any site. Built on content scripts and a service worker, and free forever.

Add to Chrome — free

Should site owners turn this on? (The product tiers)

Cloudflare's bot tools scale by plan:

Tier Plan What you get
Bot Fight Mode Free Matches known bot patterns, issues a computational challenge site-wide — no rules required.
Super Bot Fight Mode Pro / Business Adds verified-bot allowlisting, per-category actions, static-resource protection, and JavaScript Detections.
Bot Management Enterprise The full product: a 1–99 score on every request, JA3/JA4 fingerprints, WAF + Workers integration, and detailed analytics.

For most site owners, the free/Pro tiers stop the bulk of unsophisticated automation with near-zero configuration. Enterprises fighting credential stuffing, scraping, or inventory hoarding get the granular score to write targeted rules.

Recommendations

Where I'd land depends on which side of the wall you're on.

For site owners:

  1. Start with the built-in modes. Turn on Bot Fight Mode (Free) or Super Bot Fight Mode (Pro/Business) first; they need no rules and stop most commodity bots. Move to Enterprise scoring only when you need the 1–99 number for targeted rules on sensitive endpoints (login, checkout, APIs).
  2. Challenge, don't block, when you're uncertain. Use the Managed Challenge for the "likely automated" band (roughly 2–29) rather than hard blocks, to minimize false positives. Reserve outright blocks for score 1 that isn't a verified bot.
  3. Allowlist verified bots first, before any blocking rules, so you don't accidentally deprioritize Googlebot and harm SEO. Never leave "I'm Under Attack" mode on permanently; it's for active DDoS only.
  4. Use Turnstile for forms (login, signup, contact) as a free, privacy-preserving CAPTCHA replacement, and enforce the token server-side with Siteverify.
  5. Watch for cf_clearance binding issues. If legitimate users report challenge loops, VPNs and proxies that change the IP mid-session are the usual cause; consider lengthening Challenge Passage.

For developers building legitimate automation:

  1. Identify yourself. If you run a legitimate crawler or agent, get on Cloudflare's verified-bots list (rDNS, IP list, or Web Bot Auth) rather than trying to look like a browser.
  2. Keep your client story consistent. TLS, HTTP/2, headers, and the JS environment all have to agree; a mismatch is the single biggest tell.
  3. Respect robots.txt and rate limits. Cloudflare increasingly blocks AI crawlers by default, and the sustainable path is permission, not evasion.

Caveats

  • Detection methods evolve fast, and the specifics are proprietary. Cloudflare publishes the architecture (engines, score, fingerprint types) but not the exact feature weights or thresholds. I'd treat any precise "how to pass" claim skeptically.
  • A lot of the detail in this space comes from anti-bot vendors and scraping-tool blogs, which have a commercial interest; where possible this article leans on Cloudflare's own docs and blog. Third-party figures (e.g. "70+ behavioral signals," "99.5% effectiveness") are marketing characterizations, not first-party guarantees.
  • JA3/JA4 and HTTP/2 fingerprints are only populated on Enterprise Bot Management. Free and Pro plans don't expose those fields, and TLS session resumption or upstream proxies can make fingerprints absent or misleading.
  • The picture is shifting toward AI agents, and Cloudflare's tooling (Web Bot Auth, AI Labyrinth, Pay Per Crawl) is changing quickly in response; some product details may change after this writing (July 2026).

Frequently asked questions

Does Cloudflare still use CAPTCHAs?
Rarely. Cloudflare eliminated its own CAPTCHAs, replacing them with the invisible Managed Challenge and Turnstile. It reported reducing CAPTCHA use by 91% and targeted under 1%. Most legitimate visitors pass background checks and never see anything.
What is a Cloudflare bot score?
A number from 1 to 99 assigned to every request under Bot Management, where 1 means almost certainly a bot and 99 means almost certainly human. Cloudflare "generally consider[s] traffic below 30 to be automated." Site owners write firewall rules against it.
Can you spoof your way past TLS fingerprinting?
Changing your User-Agent doesn't change your TLS fingerprint, which is derived from the handshake itself. Tools exist to mimic a browser's JA3/JA4, but Cloudflare cross-checks TLS against HTTP/2, headers, IP reputation, and JavaScript signals — so a single-layer spoof usually fails.
What is the difference between Turnstile and a Cloudflare Challenge?
A Challenge (like the Managed Challenge) is deployed automatically by Cloudflare's proxy when it flags a request. Turnstile is a widget site owners embed voluntarily on forms; it can run even on sites not behind Cloudflare. Both end in a cf_clearance cookie on a passing browser.
Why does Cloudflare keep challenging me even though I'm human?
Common causes: a VPN or shared IP with poor reputation, a browser extension blocking the challenge JavaScript, or a changing IP that invalidates your cf_clearance cookie. Completing the challenge on a stable connection usually resolves it.
What is JA4 and why did it replace JA3?
JA4 is FoxIO's 2023 successor to JA3. Because Chrome began randomizing TLS extension order in 2023, JA3 produced a different hash every connection. JA4 sorts the extensions before hashing, making it stable and much harder to evade.

Shahzeb Umer

Founder, BumbleTap

Interested in a little of everything. BumbleTap is what happened when he got tired of repeating the same browser clicks and built his own fix.

More from Shahzeb

Master the keyboard-first web.

Get Keystrokes in your inbox — features, tips, news and research, about once a week. No spam, unsubscribe anytime.

One email a week · No spam · Unsubscribe anytime