How to Bypass Cloudflare TLS Fingerprinting (JA3) with Python — 2026 Guide

By Alizaib Jatoi — AziqDev  ·   ·  10 min read  ·  Web Automation & Telegram Bots
Quick Answer (50 words)

Cloudflare detects bots by hashing TLS Client Hello parameters into a JA3 fingerprint. To bypass it in Python, use curl_cffi with impersonate="chrome120" — it produces Chrome's exact TLS stack. Alternatively, use tls-client for custom fingerprints, or Playwright with playwright-stealth for browser-level automation. Pair with residential proxies for scale.

Cloudflare's Bot Management system does not just check IP reputation or rate limits — it fingerprints the TLS handshake itself. Every HTTP library (Python requests, httpx, Node's axios) produces a unique TLS Client Hello that Cloudflare can identify in milliseconds.

This guide is for developers building legitimate data aggregation tools, price monitors, authorized scrapers, and Telegram bots that need to fetch data from Cloudflare-protected endpoints without triggering bot blocks.

Table of Contents

  1. What Is TLS Fingerprinting and What Is a JA3 Hash?
  2. How Does Cloudflare Use JA3 to Detect Bots?
  3. Method 1 — curl_cffi: Impersonate Chrome's TLS Stack
  4. Method 2 — tls-client: Custom TLS Fingerprints
  5. Method 3 — Playwright Stealth: Full Browser Automation
  6. How to Combine JA3 Spoofing with Residential Proxies
  7. JA3 vs JA3N vs JA4+: What Changed in 2025?
  8. Is Bypassing Cloudflare TLS Fingerprinting Legal?

What Is TLS Fingerprinting and What Is a JA3 Hash?

When your browser (or any HTTP client) initiates an HTTPS connection, it sends a TLS Client Hello — an opening message that lists supported cipher suites, TLS extensions, elliptic curves, and compression methods. Different clients produce measurably different Client Hellos.

A JA3 fingerprint is an MD5 hash computed from five fields of that Client Hello:

These five fields are concatenated with hyphens, comma-separated within each field, then MD5-hashed. The result is a 32-character hex string — for example, Chrome 120's JA3 is 8a2a545786c1b7c3fe2e0ec1fd60e7b4.

The technique was published by John Althouse, Jeff Atkinson, and Josh Atkins at Salesforce in 2017. It is now a standard signal in every major WAF. Source: github.com/salesforce/ja3.

How Does Cloudflare Use JA3 to Detect Bots?

Cloudflare's Bot Management scores every request for "bot likelihood." JA3 is one of many signals:

Even if you set a perfect Chrome User-Agent header, your Python requests library still sends a non-Chrome TLS handshake. Headers are application-layer; JA3 is transport-layer — they cannot be faked independently of the underlying TLS library.

Key insight: Changing your User-Agent without changing your TLS library is like wearing a Chrome costume while your TCP handshake says "Python." Cloudflare sees through the costume.

Method 1: How Do You Bypass Cloudflare JA3 with curl_cffi?

curl_cffi is a Python binding for libcurl compiled with Cloudflare's BoringSSL fork — the same TLS library Chrome uses. It produces an exact Chrome TLS fingerprint, not a simulated one.

Install it: pip install curl_cffi

Basic GET request impersonating Chrome 120

from curl_cffi import requests session = requests.Session() response = session.get( "https://example.com/api/data", impersonate="chrome120", headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept-Language": "en-US,en;q=0.9", } ) print(response.status_code) # 200 on Cloudflare-protected sites print(response.text[:500])

Reusing a session across multiple requests (recommended)

from curl_cffi import requests import time with requests.Session(impersonate="chrome120") as session: # First request — establishes session cookies just like a browser would session.get("https://example.com/") time.sleep(1.5) # Human-like pause # Second request — carries cookies automatically response = session.get("https://example.com/api/prices") print(response.json())

Available impersonation targets include chrome99, chrome110, chrome120, chrome124, firefox117, safari17, and more. Match the target to a browser version that your proxy IP would plausibly use.

Method 2: How Do You Use tls-client for Custom Fingerprints?

tls-client is a Go-based library with a Python binding. It lets you construct custom TLS fingerprints from specific cipher suites and extensions — useful when you need a fingerprint not covered by curl_cffi.

Install it: pip install tls-client

Session with Chrome 120 fingerprint and randomized extension order

import tls_client session = tls_client.Session( client_identifier="chrome_120", random_tls_extension_order=True # Avoids static extension order detection ) response = session.get( "https://example.com/api/data", headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "application/json", "Accept-Encoding": "gzip, deflate, br", } ) print(response.status_code) print(response.text)

When to use tls-client vs curl_cffi: Use curl_cffi for most cases — it is actively maintained and handles cookies well. Use tls-client when you need to construct an exact fingerprint that does not map to a preset browser profile.

Method 3: How Do You Use Playwright Stealth for Browser Automation?

For tasks that require JavaScript execution, login flows, or interaction with dynamic content, run a real Chromium browser. playwright-stealth patches the 30+ JavaScript properties that headless Chromium exposes (like navigator.webdriver) to be indistinguishable from a real Chrome session.

Install: pip install playwright playwright-stealth && playwright install chromium

Headless Chromium with stealth mode

from playwright.sync_api import sync_playwright from playwright_stealth import stealth_sync with sync_playwright() as p: browser = p.chromium.launch( headless=True, args=["--no-sandbox", "--disable-blink-features=AutomationControlled"] ) context = browser.new_context( user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", viewport={"width": 1366, "height": 768}, locale="en-US", ) page = context.new_page() stealth_sync(page) # Apply all stealth patches page.goto("https://example.com", wait_until="networkidle") # At this point Cloudflare sees a real Chrome browser data = page.locator("#product-list").inner_text() print(data) browser.close()

Playwright Stealth is slower than curl_cffi but handles the most challenging targets — sites that require JavaScript challenges, cookie consent flows, or interactive CAPTCHAs.

How to Combine JA3 Spoofing with Residential Proxies

JA3 spoofing handles the fingerprint problem. Residential proxies handle the IP reputation problem. Cloudflare scores both. For production scrapers, you need both.

curl_cffi with a residential proxy

from curl_cffi import requests proxies = { "http": "http://user:pass@gate.proxy-provider.com:8080", "https": "http://user:pass@gate.proxy-provider.com:8080", } with requests.Session(impersonate="chrome120") as session: response = session.get( "https://example.com/api/data", proxies=proxies ) print(response.status_code)

See the companion guide — Managing Residential Proxies for Python Web Automation — for proxy pool rotation, backoff strategies, and provider comparisons.

JA3 vs JA3N vs JA4+: What Changed in 2025?

JA3 has known weaknesses — extension order randomization can defeat a static hash. Newer fingerprinting standards address this:

In practice, curl_cffi with a modern Chrome impersonation profile (chrome120+) produces correct JA4 fingerprints as well, because it uses the actual Chrome TLS library. It remains the most reliable solution in 2026.

Legal disclaimer: This section is for general information only and is not legal advice. Laws vary by jurisdiction and use case. Consult a qualified lawyer for your specific situation.

TLS fingerprint spoofing is a technical technique. Legality depends entirely on what you do with it, not the technique itself:

Always review a site's robots.txt and Terms of Service, and limit your request rates to avoid degrading service for other users.

Need a Telegram Bot That Fetches Protected Data?

aziqdev builds custom Telegram bots with built-in web automation — JA3-aware HTTP clients, proxy rotation, and Telegram delivery. All source code delivered to you.

Get a Free Quote →

Related Articles in This Topic Cluster

Sources & Official Documentation