TLS fingerprinting (JA3/JA4): why a scraper gets flagged

You polished your scraper. The User-Agent of a real Chrome, perfect headers, a nice residential IP. And yet the server answers 403 before it even serves a single line of HTML. What gave you away happens one layer below everything you usually control: in the TLS handshake, the very first thing a client sends over HTTPS.
What happens before HTTP
When a client opens a secure connection, it starts with a message called the ClientHello. This message goes out in the clear, before any full encryption, and before a single HTTP header. It announces the client's technical capabilities:
- the supported TLS versions;
- the list of encryption algorithms (the "cipher suites"), in a specific order;
- the enabled extensions;
- the supported elliptic curves and point formats.
The key point: this list and its order vary depending on the software library that establishes the connection. The Chrome on your machine, Firefox, Python's requests library or curl don't negotiate TLS the same way. Each has its own way of introducing itself.
From signature to hash: JA3
In 2017, engineers at Salesforce had a simple idea. Since the ClientHello is stable and characteristic, why not turn it into a fingerprint. The method, named JA3, takes five fields from the message, strings them together, and computes a hash. The result is a short string that identifies the way TLS is negotiated, and therefore the real software behind the connection.
The server doesn't take your word for it. It computes your TLS fingerprint and compares it to the ones it knows.
Python's requests library produces a fingerprint that is immediately recognizable as non-browser. It doesn't matter that your User-Agent proudly displays "Chrome": if the TLS fingerprint says "Python", the server sees the contradiction and raises its suspicion score.
Why JA3 gave way to JA4
In 2023, Chrome introduced a change: the order of the extensions in the ClientHello is now randomized on every connection. Good practice from a security standpoint, but with an immediate side effect: a real Chrome's JA3 fingerprint became different on every session, making the signal unusable.
The answer was JA4, a new method that sorts the elements before hashing them. The fingerprint becomes stable again, despite the randomization. In 2026, the switch from JA3 to JA4 is nearly complete across all the major protection vendors.
And it doesn't stop at TLS
Once the encrypted connection is established, another layer takes over: the HTTP/2 protocol. Here too, the way the dialogue opens is characteristic, notably the order of the pseudo-headers and certain technical parameters. A strictly alphabetical header order, for example, is a classic signature of an automated client that no real browser produces.
The lesson for anyone collecting data
The conclusion is a little counterintuitive. People often think that scraping cleanly is a matter of proxies and well-copied headers. In reality, the real issue is end-to-end consistency. Everything has to tell the same story:
- the TLS fingerprint must match a real browser (JA4);
- the HTTP/2 handshake must follow;
- the headers and their order must be those of the announced browser;
- and behind it all, the behavior has to hold up.
Reproducing this consistency by hand is endless work, because the reference fingerprints change with every browser version. That's the whole point of a service like WyndPath: to present, on every request, a complete and consistent signature, without you having to chase the latest version of Chrome. You request a URL, you receive the page, within the rules published by the site.
Collect this data without getting blocked
WyndPath handles proxies, JavaScript rendering and anti-bot bypass in a single API call. Pay-per-success.
Start for free →