TLS Fingerprint Test
docInspect your TLS handshake fingerprint. Understand how servers identify client stacks and detect anomalies.
A TLS fingerprint is the shape of your TLS handshake — the ordered list of cipher suites, extensions, elliptic curves, and signature algorithms your client offers before any encrypted data is exchanged. It is generated by the TLS library and the browser build, not by anything you type, and it is visible to the server before your first HTTP request is sent.
What the handshake exposes
When a client connects, it sends a ClientHello containing:
- Cipher suite list — which algorithms it supports, in a specific order
- Extension list — SNI, ALPN, supported groups, signature algorithms, key share, and dozens of optional extensions, also ordered
- Elliptic curve list — the groups it will accept for key exchange
- TLS version range — the versions it is willing to negotiate
Different software stacks make different choices here. Chrome, Firefox, Safari, curl, Python's requests, Go's net/http, and a random Android WebView each produce a distinguishable pattern. Because the pattern is determined by the code, it is far more stable than a User-Agent string, which is trivially editable.
JA3 and JA4
Two naming schemes are in common use:
| Scheme | Input | Output | Notes |
|---|---|---|---|
| JA3 | TLS version, cipher suites, extensions, curves, curve formats | 32-character MD5 | Introduced by Salesforce in 2017. Still widely deployed. MD5 makes collision-based evasion theoretically easier, and the format does not separate TLS 1.2 from 1.3 cleanly. |
| JA4 | Same inputs, plus ALPN and a version-sorted structure | Readable structured string | Introduced by FoxIO in 2023. Human-readable, splits TLS 1.3 correctly, and is easier to alert on. |
Both schemes exist because the hash is only useful if the server can compare it against a database of known clients. A JA3 of ... that matches Chrome means "this claims to be Chrome and behaves like Chrome". A mismatch means the claim and the behaviour disagree.
Why it beats the User-Agent
The User-Agent is a string the client chooses. It can be set to anything by a header override, a proxy, or a browser extension. The TLS handshake, by contrast, comes out of the TLS library that actually performs the encryption. To change it convincingly you must either use the same library and version as the browser you are impersonating, or patch the library's defaults — which is exactly what tools like curl-impersonate do, and why they exist.
This is the mechanism behind most "the site blocked me even though my User-Agent said Chrome" reports. The UA said Chrome; the handshake said Python.
Common fingerprints
- Chrome on Windows — very common, large Grease extension set, specific cipher ordering. Blending in is easy because the population is huge.
- Safari on macOS/iOS — distinct extension set and curve preference. Common enough not to stand out on its own.
- Firefox — different cipher ordering and a smaller extension set; identifiable but not suspicious.
- curl and Python requests — minimal extension sets, no browser-like ALPN profile. The classic automation signature.
- Headless browsers — modern ones mimic Chrome closely, but edge cases in extension ordering still leak.
What sits on top of TLS
TLS is not the only layer with a signature:
- HTTP/2 — the SETTINGS frame values, window sizes, and header ordering form an Akamai-style fingerprint.
- HTTP/3 / QUIC — transport parameters and the QUIC initial packet structure carry the same kind of signal.
- Header order — browsers emit headers in a consistent order; scripts rarely reproduce it exactly.
A consistent client matches on all of these. An inconsistent one matches on some and fails on others, which is more detectable than a uniform non-browser client.
When the mismatch actually matters
For ordinary browsing, it does not. For these cases, it does:
- Scraping and automation — the fingerprint is the first filter, applied before rate limits.
- Account security — a login from a residential IP but a Python TLS stack is a strong signal.
- Privacy auditing — checking whether your VPN client leaks a different TLS profile than your browser is a legitimate self-check.
FAQ
Can I change my TLS fingerprint?
Not without changing the software that performs the handshake. Browser extensions cannot rewrite a ClientHello. Tools that do exist reimplement the handshake in a library that mimics a target browser.
Does a VPN change it?
No. The VPN moves packets; it does not re-encode the handshake. Your TLS fingerprint arrives at the destination unchanged.
Is JA3 still relevant?
Yes, but it is increasingly paired with JA4 and HTTP/2 fingerprints. Detection stacks rarely rely on one signal.
Why does my browser show a different fingerprint than my phone?
Different TLS libraries and different build flags. Same vendor does not mean identical handshake across platforms.