Scraping

TLS Fingerprinting (JA3/JA4): How Detection Works and What Gives You Away

Learn how JA3/JA4 TLS fingerprints are built from ClientHello, what bot defenses flag (UA/TLS mismatch, ALPN, extensions), and how to validate consistency.

Ibuki Yamamoto
Ibuki Yamamoto
February 27, 2026 4min read

TLS Fingerprinting (JA3/JA4): How Detection Works and What Gives You Away

JA3 and JA4 are TLS client fingerprints derived from the ClientHello message sent at the start of a TLS handshake—before HTTP headers (and before encryption fully kicks in). That matters for web scraping and automation: you can rotate IPs and tweak cookies, but if your TLS stack stays the same, you often leave a stable signature that CDNs/WAFs can correlate and score.

This guide breaks down how JA3/JA4 are built, what detection teams typically look for in production, and the kinds of “mismatches” that frequently expose automated clients.

What You’ll Learn
  • How JA3/JA4 fingerprints are derived from ClientHello
  • The common mismatches bot detection systems flag—and where they’re observed
  • A practical way to think about mitigation for legitimate automation

What are JA3 and JA4?

JA3 is a TLS client fingerprinting method proposed in 2017 by researchers at Salesforce. When a client starts a TLS connection, it sends a ClientHello before encrypted application traffic begins. The combination of values in that ClientHello—such as the offered TLS version, cipher suites, extensions, supported groups (elliptic curves / named groups), and point formats—tends to vary by implementation (browser, TLS library, OS build). JA3 extracts those numeric lists, serializes them into a canonical string, and hashes it with MD5 to produce a compact identifier. Salesforce’s documentation also spells out the field order and delimiter rules (commas between fields, hyphens between values) and notes how to ignore GREASE values to keep fingerprints stable.

JA4 (often referred to as “JA4+” as part of a broader family) is a successor set of fingerprints designed to address practical limitations of JA3—especially in modern TLS 1.3 environments where implementations can look less distinct or where over-uniqueness creates noise. FoxIO describes JA4 as a human- and machine-readable fingerprint derived from ClientHello, and Cloudflare notes that JA4 reduces the explosion of unique fingerprints in modern browsers by normalizing certain elements (for example, sorting ClientHello extensions).

Important: JA3/JA4 are observed at the TLS layer—earlier than HTTP headers and the User-Agent string. So even if you make your headers look “Chrome-like,” a Python/Go/OpenSSL-looking TLS fingerprint can still conflict with your claimed client identity.

The big picture: how the fingerprint is created

ClientHello is the key

The ClientHello is the first major message in a TLS handshake. It contains the client’s proposed parameters: cipher suite list, extensions, supported groups for key exchange, and more. TLS 1.3 (RFC 8446) explicitly defines that clients send supported groups in order of preference, and that ordering becomes part of the observable “shape” of the client. In practice, what you send, in what order, and with which values is the fingerprint.

What JA3 captures

Conceptually, JA3 builds a string from these ClientHello elements:

  • TLS/SSL Version
  • Cipher Suites (the offered list)
  • Extensions (the offered list)
  • Elliptic Curves / Named Groups
  • Elliptic Curve Point Formats

The resulting string is MD5-hashed to produce the well-known JA3 hash. The original Salesforce write-up also highlights an important implementation detail: ignoring GREASE values (randomized placeholders used to keep TLS extensible) so that modern clients still map to a stable JA3.

What JA4 is trying to improve

JA4 still starts from ClientHello, but it aims to produce a more structured, operationally friendly fingerprint (often described as an a_b_c style format). It also makes certain signals easier to work with—ALPN (for example, whether the client advertises HTTP/2 or HTTP/1.1) is a good example. FoxIO also emphasizes that JA4-style fingerprints can cover both classic TLS over TCP and QUIC (the transport used by HTTP/3), which matters if you’re trying to profile modern browser traffic.

What gives automated clients away

TLS fingerprint vs. User-Agent mismatch

The most common red flag is simple inconsistency: your HTTP layer claims “Chrome,” but your TLS fingerprint looks like a default requests/OpenSSL stack (or some other non-browser library). Edge systems (CDNs/WAFs) can treat that mismatch as a high-confidence automation signal. Cloudflare explicitly documents JA3/JA4 fingerprints as bot profiling inputs and shows that they can be integrated into analytics and enforcement.

Suspicious ALPN

JA4 makes ALPN (Application-Layer Protocol Negotiation) more visible as a feature. ALPN indicates what protocol the client wants to speak after TLS completes—e.g., h2 for HTTP/2 or h1 for HTTP/1.1. FoxIO’s documentation also notes that 00 denotes no ALPN. If you’re trying to look like a browser but you don’t advertise ALPN at all, or you only ever negotiate HTTP/1.1 when a real browser would typically negotiate HTTP/2 (depending on the origin and network path), you create an easy-to-score discrepancy.

Extension sets and ordering

JA3 is (by design) sensitive to ordering. That means fingerprints can drift with library upgrades, OS changes, or different build flags. It also means defenders and attackers end up playing a tuning game around order-sensitive fields. One of the motivations behind JA4’s normalization (such as sorting extensions) is to reduce brittleness and noise from “incidental” ordering differences.

Forcing TLS 1.2 or offering dated ciphers

In real deployments, a concentration of older TLS versions or unusual cipher suite preferences often correlates with automation tooling. Not every legacy client is malicious, but if your TLS characteristics look nothing like a site’s normal user base, risk scores tend to rise.

Note: This article explains detection so you can design legitimate automation (rate control, compliance with terms, authentication flows, and operational safety). If your goal is to bypass access controls, you may violate terms of service and could trigger legal or policy risks depending on your jurisdiction and target environment.

How defenders use JA3/JA4 in practice

Use in WAF/CDN pipelines

Defenders rarely treat JA3/JA4 as a single “blocklist value.” Instead, they combine it with other signals: request velocity, endpoint mix, login failure clusters, and behavioral features. Cloudflare documents that JA3/JA4 can feed both analysis (analytics/logs) and controls (custom WAF rules and Workers logic). In practice that enables correlations like: “high-volume bursts from a single JA4,” or “credential stuffing attempts concentrated in a small set of fingerprints.”

It’s also useful for allow-listing

Fingerprints aren’t only for blocking. You can sometimes use them to quickly remediate false positives by allowing known-good clients. Cloudflare also gives an example use case where mobile app traffic tends to share the same JA3 fingerprint, enabling teams to identify and allow app traffic while challenging other sources.

Practical mitigation for web scraping

Aim for consistency, not “spoofing”

Operationally, the goal usually isn’t “forge a specific value.” It’s to keep your whole client story consistent: TLS fingerprint, HTTP headers, HTTP/2 usage, cookies/sessions, redirect behavior, and whether JavaScript is executed. Detection often triggers on contradictions across layers.

Choosing an implementation approach

There are two common directions:

  1. Use browser automation (for example, Playwright) to rely on a real browser TLS stack.
  2. If you must use an HTTP client library, choose one whose TLS behavior is close to the browser profile you’re claiming.

For the second approach, some teams use curl_cffi-style clients that can approximate specific browser TLS signatures. Treat this as an engineering trade-off: validate that your use case is legitimate, and review the target site’s terms and operational constraints before adopting any approach.

Measure, compare, and verify

In production, improvements usually start with observability:

  1. Measure your client’s JA3/JA4 in a controlled test environment.
  2. Measure the target browser’s JA3/JA4 and diff the results.
  3. Check ALPN, HTTP/2 negotiation, and TLS version alignment.
  4. Correlate changes with block conditions (WAF logs, challenge triggers, edge events).

This is why “just rotate IPs” often fails: JA3/JA4 are far more tied to the client implementation than to the IP address.

Minimal code example

This minimal snippet helps you create a TLS connection and inspect negotiated results. It’s mainly a companion to packet capture (for example, using Wireshark) so you can understand what’s being sent in ClientHello. This code itself does not produce a browser-equivalent fingerprint.

import ssl
import socket

host = "example.com"
ctx = ssl.create_default_context()

with socket.create_connection((host, 443)) as sock:
    with ctx.wrap_socket(sock, server_hostname=host) as ssock:
        print("TLS version:", ssock.version())
        print("Cipher:", ssock.cipher())

Important: JA3/JA4 are not based on the negotiated cipher you print here. They’re derived from the ClientHello offer—the candidate cipher suite list, extensions, their ordering, and related fields. For accurate measurement, capture the raw ClientHello packet or use trusted edge logs.

For specifications and official documentation, start here:






Need help validating TLS fingerprints?

If your scraper works locally but gets challenged in production, we can help you measure JA3/JA4, audit cross-layer consistency (TLS/HTTP/2/headers), and design a compliant collection plan.

Contact UsFeel free to reach out for scraping consultations and quotes
Get in Touch

Summary

  • JA3/JA4 are fingerprints derived from the TLS ClientHello (observable before full encryption), and they tend to remain stable even if you rotate IPs.
  • Common detection triggers include TLS vs. UA/HTTP behavior mismatches, suspicious ALPN/HTTP2 signals, odd extension patterns, and legacy TLS characteristics.
  • For legitimate automation, the practical playbook is consistency and observability: measure → diff → validate against edge logs → iterate.

About the Author

Ibuki Yamamoto
Ibuki Yamamoto

Web scraping engineer with over 10 years of practical experience, having worked on numerous large-scale data collection projects. Specializes in Python and JavaScript, sharing practical scraping techniques in technical blogs.

Leave it to the
Data Collection Professionals

Our professional team with over 100 million data collection records annually solves all challenges including large-scale scraping and anti-bot measures.

100M+
Annual Data Collection
24/7
Uptime
High Quality
Data Quality