JA4 Fingerprint Decoder
Decode any JA4 TLS fingerprint field by field — transport, TLS version, SNI, cipher and extension counts, and ALPN — plus a browser-family guess.
On this page
A JA4 fingerprint summarises a client’s TLS ClientHello into a string like t13d1516h2_8daaf6152771_d8a2da3f94cd. The first part is human-readable and fully reversible; the two hashes that follow are not. Paste any JA4 below to break it down.
| Segment | Field | Decoded |
|---|---|---|
t | Transport | TLS over TCPClassic TLS handshake over a TCP connection. |
13 | TLS version | TLS 1.3Highest version from the supported_versions extension (GREASE ignored), or the legacy version field. |
d | SNI | present (connecting to a domain)d = the Server Name Indication extension was sent; i = it was not. |
15 | Cipher suites | 15 offeredCount of cipher suites with GREASE values removed (capped at 99). |
16 | Extensions | 16 presentCount of TLS extensions, GREASE removed. SNI and ALPN ARE counted here — they are only excluded from the JA4_c hash. |
h2 | First ALPN | HTTP/2The application protocol the client preferred — h2 = HTTP/2, h1 = HTTP/1.1, h3 = HTTP/3, 00 = none. |
8daaf6152771 JA4_b — truncated SHA-256 of the sorted cipher list. One-way: it identifies, it doesn’t decode.
d8a2da3f94cd JA4_c — truncated SHA-256 of the sorted extensions (minus SNI & ALPN) plus the signature algorithms in order. Also one-way.
What the decoder can and can’t recover
A full JA4 has three parts, a_b_c, and they are not equal:
a— the readable prefix (t13d1516h2). Six fixed fields: transport, TLS version, SNI presence, cipher count, extension count, and first ALPN. Every field is a direct encoding, so the decoder reconstructs all of it exactly.b— the cipher hash (8daaf6152771). A truncated SHA-256 of the client’s cipher-suite list, sorted before hashing so extension-order randomization can’t move it. SHA-256 is one-way: you can confirm a known list produces this hash, but you can’t run it backwards.c— the extension hash (d8a2da3f94cd). Truncated SHA-256 of the sorted extensions (with SNI and ALPN removed) plus the signature algorithms in their original order. Also one-way.
So the decoder reads a and matches b/c against a small set of known fingerprints. That’s the same shape of problem a CDN solves at scale — it can’t reverse your hashes either, so it compares them against a fingerprint database. How Websites Detect Bots in 2026 covers how that comparison drives a block-or-allow decision.
Why the counts matter
The cipher and extension counts are the fields people most often misread. Both exclude GREASE values (the deliberately random entries browsers inject to keep middleboxes honest). The extension count includes SNI and ALPN — they’re only removed from the c hash, not from the count. That’s why a modern Chrome reports 15 ciphers and 16 extensions rather than the larger raw numbers you’d get by counting GREASE.
For the meaning of one specific, very common prefix, see the t13d1516h2 reference. For why JA3 gave way to this format, see JA4 vs JA3; for how detection vendors use the fingerprints, see How Websites Detect Bots in 2026. To actually produce a chosen JA4 from Python, see TLS Fingerprinting with curl_cffi.
Reference set
The browser-family guess uses a deliberately small, conservative set drawn from FoxIO’s published JA4 database: t13d1516h2 and the PSK session-resumption variant t13d1517h2 (both Chromium), t13d1715h2 (Firefox), and t13d2014h2 (Safari), plus two full Chrome hashes for desktop version ranges. JA4 has no canonical public reverse-lookup database, so a “no match” doesn’t mean the fingerprint is invalid — only that it isn’t in this set. A prefix no mainstream browser uses is usually a scripted client.
Sources
- FoxIO-LLC/ja4 — JA4 technical spec — the authoritative field-by-field construction rules.
- ja4db.com — community fingerprint lookups (availability varies by region).