What is JA3?
JA3 is a TLS client fingerprinting method that reads five fields from the ClientHello, joins their decimal values into a single string and hashes it with MD5. The fields are TLS version, cipher suites, extensions, supported elliptic curves and EC point formats. The 32-character result groups clients by TLS library and configuration.
The JA3 string joins five fields with commas: the TLS version, then dash-separated lists of cipher suites, extension types, supported groups and EC point formats, written as decimal code points in the order the client sent them. GREASE values are stripped first. MD5 over that string produces the hash you see in logs. JA3S is the server-side counterpart, built from the ServerHello's version, chosen cipher and extensions. Salesforce engineers published both in 2017, and network monitors such as Zeek and Suricata can record them against the connection.
A JA3 hash identifies a TLS stack and its settings, never a person. Every install of the same browser build on the same platform shares one value, which is what makes blending in possible and what makes hash blocklists blunt instruments. The distinctive values belong to tooling: a default python-requests install, curl against system OpenSSL, Go's net/http, a Node HTTP client. Threat intelligence work originally paired JA3 with JA3S to recognise malware families by the handshake their implants negotiate.
Two limits pushed the field along. JA3 preserves list order, so once Chrome began shuffling its extension order the same browser started producing a different hash on every connection, which wrecked allowlists built on a single value. The output is also one opaque digest, so you cannot ask whether a client offered HTTP/2 in ALPN or supported TLS 1.3 without a lookup table that maps hashes back to inputs. JA4 answers both by sorting the lists and keeping part of the fingerprint readable.
JA3 stays widely deployed because it is cheap to compute and nearly everything already logs it. Treat it as one input rather than a verdict. The useful signal is agreement: a JA3 known to belong to Chrome on Android arriving with Chrome-on-Android headers, matching HTTP/2 settings and a mobile carrier ASN. Any one of those alone is thin evidence. A python-requests JA3 wearing a browser User-Agent, by contrast, is scored in a single rule.
Where you meet it
You meet JA3 in a Zeek ssl.log, a Suricata alert, or a WAF rule that bans one hash outright. From the automation side you meet it as a 403 that never reaches your parsing code. Pull your client's JA3 from an echo endpoint, compare it with a real browser's on the same machine, and decide whether to swap TLS stacks or stop claiming to be a browser in your headers.
Common questions
Is JA3 still used?
Yes. It is cheap, well supported in Zeek, Suricata and most CDNs, and still records useful groupings. Browser extension-order randomisation made single-hash allowlists unreliable, so newer detection stacks log JA4 as well and often keep both values on the same connection record.
Can two different programs have the same JA3?
Yes, and most do. Any two programs linking the same TLS library with the same options negotiate the same handshake, so a dozen OpenSSL-based tools can share one hash. JA3 tells you which stack and configuration produced a connection, not which application or which user.
Why does JA3 use MD5?
MD5 is used as a short, fast label for the joined field string, not as a security control. Nothing about JA3 depends on collision resistance. If you need the underlying values you have to keep the original string, since the hash alone cannot be reversed.
Related terms
Real 4G/5G mobile and residential IPs
PROXIES.SX runs carrier IPs in 100+ countries with HTTP and SOCKS5 on every endpoint. $4/GB down to $2.40/GB at volume, free endpoints and rotation, and your GB never expire.