JA4 TLS Fingerprinting: Identifying Clients at CDN Edge Servers

· James Thornton · 12 min read

Every TLS handshake reveals more about a client than just its encryption capabilities. The specific combination of cipher suites, extensions, supported groups, and signature algorithms in a ClientHello message creates a fingerprint as distinctive as a human thumbprint. JA4, the successor to the widely adopted JA3 fingerprinting method, transforms these TLS handshake parameters into a structured, human-readable hash that CDN edge servers use to identify client software, detect bots masquerading as browsers, and enforce security policies before a single byte of HTTP data is exchanged.

The Evolution from JA3 to JA4

JA3, created by John Althouse, Jeff Atkinson, and Josh Atkins at Salesforce in 2017, pioneered passive TLS client fingerprinting by generating an MD5 hash from the ClientHello's TLS version, cipher suites, extensions, elliptic curves, and elliptic curve point formats. The approach was revolutionary — security teams could identify malware, bots, and unauthorized clients purely from their TLS behavior without decrypting traffic or inspecting payloads.

But JA3 had limitations that became apparent at CDN scale. The MD5 hash was opaque: e7d705a3286e19ea42f587b344ee6865 reveals nothing about the client without consulting a lookup database. Minor changes in cipher suite ordering — common between browser point releases — produced completely different hashes, creating fingerprint fragmentation. And as TLS 1.3 reduced the visible cipher suite list to just a few standardized options, JA3 fingerprints became less distinctive, with many different clients producing identical hashes.

JA4 addresses all three problems. Its fingerprint format is structured and readable: t13d1516h2_8daaf6152771_b0da82dd1658. The first section (t13d1516h2) encodes the TLS version (1.3), whether SNI is present (d for domain), the number of cipher suites (15), the number of extensions (16), and the ALPN value (h2 for HTTP/2). The second and third sections are truncated SHA256 hashes of the sorted cipher suites and sorted extensions respectively. Sorting eliminates order-dependent fragmentation, and the readable prefix gives immediate context to anyone analyzing the fingerprint.

How JA4 Fingerprint Construction Works

When a client initiates a TLS connection to a CDN edge server, the edge server receives the ClientHello message as the first packet in the TLS handshake. The JA4 fingerprint is computed from this message using a deterministic algorithm that produces identical output for identical ClientHello parameters regardless of field ordering.

Performance Comparison: Edge vs Origin Processing
Metric Edge Processing Origin Processing Improvement
Latency (p50)8–15 ms120–300 ms15–20x faster
Cache Hit Ratio85–95%N/AReduces origin load
TLS Handshake1–5 ms (nearby PoP)50–150 ms10–30x faster
Bandwidth Cost$0.01–0.04/GB$0.05–0.12/GB3–5x cheaper
Availability99.99% (multi-PoP)99.9% (single DC)10x fewer outages
JA4 Fingerprint Construction from TLS ClientHello TLS ClientHello TLS Version: 0x0303 (1.3) SNI: cdn.example.com Cipher Suites (15) 0x1301, 0x1302, 0x1303 0xc02c, 0xc02b, 0xc030... Extensions (16) SNI, ALPN, key_share sig_algs, psk_modes... ALPN: h2, http/1.1 Signature Algorithms ecdsa_secp256r1_sha256... Section A: Readable t13d1516h2 Section B: Cipher Hash Sort ciphers → SHA256 8daaf6152771 Section C: Ext Hash Sort exts+sig_algs → SHA256 b0da82dd1658 JA4 Fingerprint t13d1516h2_8daaf6152771_b0da82dd1658

The construction process follows these steps:

Section A encodes the protocol context in a human-readable string. The first character indicates the protocol: t for TCP-based TLS, q for QUIC, d for DTLS. The next two characters encode the TLS version (13 for TLS 1.3, 12 for 1.2). A single character indicates SNI presence: d if a domain is present, i if only an IP address is used. Two-digit counts of cipher suites and extensions follow, then the first and last characters of the ALPN value (h2 becomes h2, http/1.1 becomes h1).

Section B sorts the cipher suite values numerically, concatenates them with commas, and computes a truncated SHA256 hash (first 12 characters). The sorting ensures that two clients offering the same cipher suites in different orders produce identical Section B values, solving JA3's fragmentation problem.

Section C applies the same sorted-hash approach to the extension types, appending the signature algorithms as an additional differentiator. This captures the full extension set including supported groups, key share types, and PSK modes that distinguish modern TLS 1.3 clients from each other.

The JA4 Fingerprint Suite

JA4 is not a single fingerprint but a suite of complementary fingerprints, each capturing a different protocol layer. Together, they create a multi-dimensional client profile that makes evasion significantly harder than spoofing any single layer.

JA4S: Server Hello Fingerprint

JA4S captures the server's TLS response — the ServerHello message. This fingerprint records which cipher suite the server selected, which extensions it included, and the ALPN protocol it chose. JA4S is useful for identifying CDN edge servers themselves, detecting TLS-terminating proxies in the request path, and identifying misconfigured servers that select weak cipher suites. When correlated with JA4, the JA4+JA4S pair reveals both ends of the TLS negotiation.

JA4H: HTTP Client Fingerprint

JA4H moves above the TLS layer to fingerprint the HTTP client's behavior. It hashes the HTTP header names (in order), their values, and the Cookie header separately. Each HTTP client constructs requests with characteristic header ordering: Chrome sends headers in a different order than Firefox, and both differ from curl or Python's requests library. A bot using a legitimate Chrome JA4 TLS fingerprint but sending HTTP headers in Python's order is immediately flagged by the JA4H mismatch.

JA4T: TCP Fingerprint

JA4T fingerprints the TCP connection parameters visible in the SYN packet: window size, maximum segment size (MSS), window scale factor, and TCP options ordering. These parameters are set by the operating system's network stack, not by application-level code, making them extremely difficult for bots to forge without kernel-level modifications. A bot running on a Linux VPS claiming to be a macOS Safari user will have Linux TCP characteristics that contradict the claimed identity.

JA4X: X.509 Certificate Fingerprint

JA4X fingerprints the TLS certificates presented during mutual TLS authentication. It hashes the certificate's issuer and subject fields, identifying the certificate authority and the certificate's organizational identity. This fingerprint helps detect forged or self-signed certificates used by malware or unauthorized clients in mTLS environments.

Bot Detection with JA4 at CDN Scale

The primary application of JA4 at CDN edge servers is bot detection. The detection model compares the client's declared identity (User-Agent header) against its actual identity (JA4 fingerprint suite) and flags inconsistencies.

JA4 Bot Detection Pipeline at CDN Edge Incoming TLS + HTTP Extract Fingerprints JA4: t13d1516h2_... JA4H: ge11nn07_... JA4T: 65535_64_... UA: Chrome/120 Fingerprint DB Chrome 120 → JA4: abc... Firefox 121 → JA4: def... Python req → JA4: ghi... curl → JA4: jkl... Decision Engine UA says: Chrome 120 JA4 says: Python MISMATCH! Allow Challenge Block Rate Limit Common JA4 Fingerprint Patterns Chrome 120+: t13d1517h2_8daaf6152771_e5627efa2ab1 Firefox 121: t13d1516h2_1dd575fd6bd2_94ef5e863e99 Safari 17.2: t13d1514h2_a09f3c656f24_c7bc145bf912 Python/req: t13d1507h2_cf83e1357eef_5e5079be3d9a Go net/http: t13d1505h2_2a8bf6baf2be_e3b0c44298fc curl 8.x: t13d1512h2_3dc9088124ed_d5f44ef7f7c1

The detection pipeline operates in three stages:

Stage 1: Fingerprint Extraction. During the TLS handshake, the edge server's TLS termination layer (typically OpenSSL, BoringSSL, or a Rust-based TLS library) extracts the ClientHello parameters and computes the JA4 fingerprint. This computation happens inline with the handshake, adding negligible latency. The fingerprint is attached to the connection context and available to all subsequent processing layers.

Stage 2: Database Correlation. The extracted JA4 fingerprint is compared against an in-memory database of known fingerprints. CDN providers like Cloudflare, Fastly, and Akamai maintain continuously updated fingerprint databases built from their global traffic observation. These databases map JA4 hashes to known client software: browsers, mobile apps, API clients, bots, and malware families.

Stage 3: Identity Verification. The database match is compared against the client's claimed identity in the HTTP layer. A request claiming to be Chrome 120 (via User-Agent) but presenting a JA4 fingerprint matching Go's net/http library is an identity mismatch. The bot management engine scores this mismatch along with other signals: request rate, behavioral patterns, IP reputation, and threat intelligence data.

Implementing JA4 at the Edge

CDN edge servers implement JA4 extraction at the TLS termination layer, which means the fingerprint is available before any HTTP processing begins. This positioning gives the edge server the earliest possible detection signal.

For nginx-based edge servers, JA4 extraction integrates as a module that hooks into the SSL handshake callback. The module populates nginx variables ($ja4, $ja4s) that downstream configuration blocks reference for rate limiting decisions, WAF rule evaluation, and access logging. The fingerprint persists for the lifetime of the TLS connection, so HTTP/2 multiplexed requests on the same connection share a single JA4 computation.

At edge function platforms, JA4 data is typically exposed as a request property. Cloudflare Workers, for example, surface the JA4 fingerprint through the cf.botManagement object, allowing edge function code to implement custom logic based on client identity. A WAF rule might block all requests where the JA4 fingerprint indicates Python's requests library but the User-Agent claims to be a browser, while allowing authenticated API clients using Python with proper API keys.

Evasion Techniques and Countermeasures

Sophisticated bot operators are aware of TLS fingerprinting and employ evasion techniques. The most common approach uses libraries like curl-impersonate or tls-client that modify the TLS stack to mimic legitimate browser fingerprints. These tools configure OpenSSL or BoringSSL with the exact cipher suites, extensions, and parameters that Chrome or Firefox would present, producing a JA4 fingerprint indistinguishable from the real browser.

The JA4 suite's multi-layer approach counters single-layer evasion. Even when the JA4 (TLS) fingerprint matches Chrome, the JA4H (HTTP) fingerprint often reveals the deception. Chrome sends HTTP headers in a specific order: Host, Connection, sec-ch-ua, sec-ch-ua-mobile, sec-ch-ua-platform, Upgrade-Insecure-Requests, User-Agent, Accept, and so on. Curl-impersonate matches the TLS layer but may not match this exact HTTP header sequence, producing a JA4H fingerprint that does not correspond to any known Chrome version.

The JA4T TCP fingerprint adds a third dimension. A bot running on a Linux cloud VPS presents Linux TCP window sizes, MSS values, and TTL values — even when the JA4 and JA4H fingerprints match macOS Safari. A real Safari user connects from macOS, which has distinctly different TCP stack parameters. Matching all three layers simultaneously requires the bot to modify kernel-level TCP parameters, which is possible but significantly increases the operational complexity and cost of running the bot infrastructure.

CDN providers complement JA4 with behavioral analysis. A client with a perfect Chrome JA4 fingerprint suite but accessing 500 pages per minute, never loading CSS or images, and never executing the inline analytics beacon clearly behaves unlike a real browser user. JA4 provides the static identity check; behavioral analysis provides the dynamic intent check. The combination produces false positive rates below 0.01% for enterprise CDN deployments.

JA4 and Zero Trust Architecture

In a zero trust architecture, JA4 fingerprinting serves as a device posture signal. The edge BFF or API gateway evaluates the JA4 fingerprint alongside the authentication token, device certificate, and request context to make per-request authorization decisions.

A zero trust CDN policy might specify: "Allow access to /api/admin/* only when the JA4 fingerprint matches a known corporate browser, the JA4T fingerprint matches a corporate-provisioned device OS, and a valid MFA-backed session token is present." This policy enforces device compliance at the edge — a stolen token used from a non-corporate device with a different JA4T fingerprint is rejected, even though the token itself is valid.

For AI agent and machine-to-machine communication, JA4 helps distinguish authorized automation from unauthorized scraping. Authorized API clients present known JA4 fingerprints that match their registered client profiles. An API key issued to a Python application should present a Python JA4 fingerprint; if the same key appears with a Go fingerprint, the CDN flags potential key theft and can trigger step-up verification or key rotation.

Privacy and Compliance Considerations

JA4 fingerprinting operates on network protocol metadata, not on content. The fingerprint is derived from the TLS handshake, which occurs before any application data is exchanged and does not require decrypting user traffic. This positions JA4 as a privacy-preserving security mechanism: it identifies the client software, not the user.

However, the combination of JA4 with IP address and session data could theoretically contribute to user tracking. GDPR and privacy regulations require that CDN operators document their use of TLS fingerprinting in their privacy policies and ensure that fingerprint data is processed only for legitimate security purposes (bot detection, abuse prevention) rather than for advertising or user profiling.

CDN providers typically store JA4 fingerprints in access logs alongside request data. Organizations subject to data retention regulations should include JA4 data in their log retention policies and ensure that log analysis systems treat fingerprint data with the same security controls applied to other client metadata. The fingerprint itself does not constitute personal data under most frameworks, but its combination with other request fields may meet the threshold for personal data classification in some jurisdictions.

Deployment Best Practices

Start JA4 deployment in observation mode. Log JA4 fingerprints alongside User-Agent strings for two to four weeks without taking enforcement actions. This baseline reveals the fingerprint distribution of your legitimate traffic and identifies any unusual but authorized client software. Many organizations discover legitimate internal tools, monitoring systems, and partner integrations during the baseline period that would have been incorrectly blocked by an immediate enforcement deployment.

Build your fingerprint policy from observed legitimate traffic rather than from a blocklist of known bad fingerprints. A allowlist approach — permitting known-good JA4 fingerprints for specific endpoints — is more resilient than a blocklist because new bot tools produce new fingerprints that a blocklist cannot anticipate. For public-facing endpoints, use JA4 mismatches (UA/fingerprint inconsistency) as a primary signal rather than fingerprint matching, since this catches impersonation regardless of which fingerprint the bot presents.

Combine JA4 with DDoS protection, rate limiting, and WAF rules in a layered defense architecture. JA4 excels at identifying what a client is; rate limiting controls how much a client can do; WAF rules inspect what a client sends. No single layer catches everything, but together they create a defense depth that dramatically raises the cost for attackers while keeping false positive rates negligible for legitimate users.

External References

References & Standards: W3C Web Performance · OWASP CDN Security