The article opens by explaining why even carefully crafted HTTP headers often fail against modern website protections. Servers detect automated clients through TLS fingerprinting long before any application data is exchanged.
TLS handshakes expose a rich set of parameters including supported cipher suites, extension order, elliptic curve groups, and ALPN values. These values form a stable digital signature that distinguishes real browsers from scripts written in Python, Go, or curl.
Historical Evolution of TLS
The text recounts the development from Netscape SSL 1.0 through SSL 3.0 to the IETF-standardized TLS 1.0 in 1999. It describes how RSA key exchange gave way to ECC curves such as X25519 to reduce computational load on mobile devices while enabling perfect forward secrecy via ECDHE.
Examples of cipher suite strings like TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 illustrate how each component specifies key exchange, authentication, encryption, and integrity algorithms.
TLS 1.2 versus TLS 1.3 Handshakes
In TLS 1.2 the full handshake requires two round trips. The Client Hello remains plaintext, revealing the full list of supported versions, ciphers, and extensions. TLS 1.3 reduces this to one round trip and encrypts the server certificate and subsequent messages, leaving only the initial Client Hello visible to passive observers.
Wireshark captures of connections to GitHub demonstrate the structure of a modern TLS 1.3 Client Hello, including the SNI extension and the list of AEAD-based cipher suites.
JA3 Fingerprinting and Its Limitations
The article details the JA3 algorithm created by Salesforce engineers in 2017. It extracts five fields, concatenates them with commas and dashes, and produces an MD5 hash. Real examples show how two consecutive page loads from the same browser generate completely different JA3 hashes because of GREASE (RFC 8701) random extensions.
This randomness renders static JA3 blacklists ineffective against sophisticated clients.
JA4+ Standard
The newer JA4 format addresses these shortcomings. It produces a human-readable string divided into three blocks: JA4_A for high-level connection properties (transport, TLS version, SNI presence, cipher and extension counts, ALPN), JA4_B for a sorted SHA-256 hash of cipher suites, and JA4_C for sorted extensions plus signature algorithms.
An example fingerprint t13d1518h2_8daaf6152771_e2d80978ab2e is dissected to show how each component remains stable despite GREASE noise.
Practical Tools and Evasion
The article concludes with guidance on using the uTLS library in Go to craft custom Client Hello messages that mimic specific browsers. It also introduces the Finch tool for capturing and filtering live traffic to analyze or replicate fingerprints.
These techniques allow security researchers and red-team operators to understand and evade detection mechanisms employed by Cloudflare, WAFs, and anti-fraud platforms.


