# JA4 / JA3 TLS fingerprint decoder

> Decode a JA4 TLS client fingerprint or a JA3 fingerprint into its fields, compute the hashed JA4 from raw values, or compute a JA3 MD5. It auto-detects which you paste. All in your browser.

- Tool: https://ronutz.com/en/tools/ja4-fingerprint-decoder
- Family: Security & WAF

---

## What it does

A JA4 is a fingerprint of a TLS client, computed from the fields in its ClientHello: the TLS version, the cipher suites it offers, the extensions it sends, the signature algorithms, and the ALPN. Two clients that build their ClientHello the same way produce the same JA4, which is how servers, proxies, and passive sensors recognize client software without decrypting anything. This tool decodes a JA4 into its parts, or computes the hashed JA4 from the raw, unhashed values. It all runs in your browser.

## How a JA4 is built

A JA4 has three sections joined by underscores, `JA4_a_JA4_b_JA4_c`, for example `t13d1516h2_8daaf6152771_e5627efa2ab1`.

- **JA4_a** is human-readable and ten characters long:
  - transport: `t` for TLS over TCP, `q` for QUIC, `d` for DTLS;
  - TLS version: `13` for TLS 1.3, `12` for 1.2, and so on, read from the supported_versions extension when present;
  - SNI: `d` when the ClientHello carries a server name (a domain), `i` when it does not (a bare IP);
  - the cipher count as two digits;
  - the extension count as two digits (this count includes SNI and ALPN);
  - the ALPN marker: the first and last character of the first ALPN value, so `h2` for HTTP/2, or `00` when there is no ALPN.
- **JA4_b** is the first twelve hex characters of the SHA-256 of the cipher list, sorted.
- **JA4_c** is the first twelve hex characters of the SHA-256 of the extension list (sorted, with SNI and ALPN removed) followed by the signature-algorithm list in its original order.

Because JA4_b and JA4_c are truncated hashes, they are one-way: the tool can show them but cannot recover the cipher or extension lists from them.

## GREASE

GREASE (the reserved values from draft-davidben-tls-grease) keeps TLS extensible by making clients send random unused values that servers must ignore. JA4 ignores them too, so they never affect the counts or the hashes. If you paste raw values that include GREASE, this tool filters them out before counting, sorting, and hashing.

## Sorting is what makes JA4 robust

Older fingerprints like JA3 hashed the cipher and extension lists in the order the client sent them. Modern browsers now deliberately randomize the order of TLS extensions on each connection, which changes a JA3 every time and defeats it. JA4 sorts the ciphers and extensions before hashing, so the fingerprint stays stable even when the client shuffles the order. That is the main reason JA4 has largely replaced JA3.

## Worked example

The fingerprint `t13d1516h2_8daaf6152771_e5627efa2ab1` decodes to TLS over TCP, TLS 1.3, SNI present, 15 cipher suites, 16 extensions, and ALPN `h2` (HTTP/2). This is the worked example from the JA4 specification, and it is one of this tool's golden vectors: the SHA-256 of its sorted cipher list gives `8daaf6152771`, and the sorted extensions plus signature algorithms give `e5627efa2ab1`.

## A note on licensing

JA4 (TLS client fingerprinting) is released by FoxIO under the permissive BSD 3-Clause license, the same terms as the original JA3, so it is free to implement, including in commercial tools. The other members of the JA4+ family, such as JA4S, JA4H, JA4X, and JA4T, are under the FoxIO License 1.1, which does not permit monetization without a separate agreement, so this tool implements JA4 only.

## JA3, the predecessor

This tool also handles JA3, the older fingerprint JA4 replaced. A JA3 is the MD5 of five decimal fields from the ClientHello in the order they were sent: `SSLVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats`, for example `769,47-53-5-10-49161-49162-49171-49172-50-56-19-4,0-10-11,23-24-25,0`. Paste a JA3 string and the tool computes its MD5 and breaks out the fields; paste a bare 32-character MD5 and it recognizes it as a JA3 hash, which, being one-way, it cannot decode. JA3 is BSD 3-Clause like JA4. It is order-sensitive, so a browser that randomizes its extension order produces a different JA3 on each connection, which is the reason JA4 exists.

## Using it

The tool auto-detects what you paste: a JA4 has underscores, while a JA3 is decimal fields separated by commas, or a bare MD5. Paste a hashed JA4 to decode it, a raw JA4_r (the `JA4_a` value followed by the unhashed cipher, extension, and signature-algorithm lists, separated by underscores) to compute the hashed JA4, a JA3 string to compute its MD5 and see its fields, or a JA3 MD5 to identify it. The raw JA4 path sorts and GREASE-filters the lists for you, so sorted and original-order inputs produce the same canonical JA4.

## Standards and references

- [FoxIO JA4: TLS Client Fingerprinting (technical specification)](https://github.com/FoxIO-LLC/ja4/blob/main/technical_details/JA4.md) - the JA4 algorithm, field definitions, GREASE handling, and the worked example used as golden vectors
- [FoxIO-LLC/ja4 (README and licensing)](https://github.com/FoxIO-LLC/ja4) - JA4 is BSD 3-Clause; the rest of JA4+ is FoxIO License 1.1 (no monetization)
- [draft-davidben-tls-grease: Applying GREASE to TLS Extensibility](https://datatracker.ietf.org/doc/html/draft-davidben-tls-grease-01) - the GREASE reserved values that JA4 ignores

## Related reading

- [Passive TLS Fingerprinting: JA3, GREASE, and the Churn That Led to JA4](https://ronutz.com/en/learn/passive-tls-fingerprinting-ja3.md): A ClientHello announces the client in the clear, and the combination of versions, ciphers, and extensions is characteristic of the software that sent it. This covers how JA3 turns that into a hash, why GREASE has to be stripped, how extension-order randomization broke JA3 (the churn), how JA3N and JA4 restore stability, and where a TLS fingerprint fits as a signal for secure web gateways and adaptive authentication.
- [What Is a JA4 TLS Fingerprint?](https://ronutz.com/en/learn/what-is-a-ja4-tls-fingerprint.md): How a TLS ClientHello becomes a stable fingerprint of the client software, why JA3 faded once browsers began randomizing extension order, how JA4 fixes that by sorting before hashing, and what JA4 can and cannot tell you.
