JA4 / JA3 fingerprint lookup

Paste a JA4, raw JA4_r, or JA3 fingerprint. We decode its structure, then match it against a reference database of browsers, HTTP clients, and automation tools.

Try:

How to read a JA4

A TLS connection opens with a ClientHello that lists the cipher suites, extensions, and curves the client supports. That list is determined by the client's TLS library, so a Python script, a Go binary, and a real Chrome produce visibly different handshakes no matter what their User-Agent claims. JA4 folds that handshake into a comparable string.

The first ten characters, JA4_a, are human-readable: transport, TLS version, whether SNI is present, the cipher and extension counts, and the first ALPN value. The two twelve-character hashes that follow are truncated SHA-256 digests of the sorted cipher and extension lists - not reversible, which is why naming a client means matching the hashes against a database. For the full explanation, see TLS fingerprinting.

JA4 vs JA3

JA3, the older format, is an MD5 hash of the handshake in wire order. Chrome shipped per-connection extension-order randomization in 2023, which gives every Chrome connection a different JA3 - so JA3 is effectively legacy for modern browsers. JA4 sorts the lists before hashing, so randomization no longer changes the fingerprint. A bare JA3 hash can't be decoded; only the raw JA3 string can.

What a match does and does not tell you

A fingerprint identifies software, not a person. Every up-to-date Chrome on the same platform presents essentially the same JA4 - that uniformity is the point, because it makes deviations meaningful. A match tells you what the client claims to be. Whether it's telling the truth is a separate question: Foil cross-checks the JA4 against the User-Agent, the HTTP/2 fingerprint, and the JavaScript environment, and a contradiction at any layer is where automation gives itself away. See bot detection and headless browser detection for how the layers compose.

Frequently asked

JA4 is a fingerprint of the TLS ClientHello a client sends before any HTTP. It is a three-part string, JA4_a_JA4_b_JA4_c: a readable prefix (transport, TLS version, SNI, cipher and extension counts, ALPN) followed by two truncated SHA-256 hashes over the sorted cipher and extension lists. Unlike JA3, it survives Chrome's extension-order randomization.

The JA4_a prefix decodes by eye: the first character is the transport, the next two are the TLS version, then SNI, a two-digit cipher count, a two-digit extension count, and the first ALPN value. The two hashes are not reversible; you identify them by matching against a database or by decoding the raw (JA4_r) variant.

A JA3 fingerprint is an MD5 hash of the handshake, so the hash itself carries no readable structure. Only the raw JA3 string (version, ciphers, extensions, curves, point formats) can be decoded back into its components.

Yes. Fingerprints are matched against a distilled reference database of common browsers, HTTP libraries, and automation tools. The match tells you what a client is; identifying whether it is lying about that requires cross-checking against the User-Agent, HTTP/2 fingerprint, and JavaScript environment in a live request.