Common JA4 TLS Fingerprints, Decoded
A lookup table of JA4 fingerprint hashes for Chrome, Firefox, curl, Go, and Python clients, decoded field by field.
On this page
A JA4 fingerprint like t13d1516h2_8daaf6152771_<ja4_c> encodes the TLS ClientHello shape; this page decodes the common Chrome, Firefox, Safari, curl, Go, and Python client strings field by field.
Quick Reference
Rows marked live capture 2026-06-13 were observed against https://tls.peet.ws/api/all with the named client/profile. Treat them as version/profile observations, not permanent identities.
| Client/profile | JA4 fingerprint | HTTP | Source |
|---|---|---|---|
| FoxIO canonical JA4 example | t13d1516h2_8daaf6152771_e5627efa2ab1 | h2 | FoxIO JA4 technical details |
| Published Chrome-family example | t13d1516h2_8daaf6152771_02713d6af862 | h2 | bunny.net JA4 docs; Google Threat Intelligence deep dive; Cloudflare blog |
Chrome 131 profile (curl_cffi chrome131) | t13d1516h2_8daaf6152771_02713d6af862 | h2 | live capture 2026-06-13; curl_cffi target docs |
Chrome 136 profile (curl_cffi chrome136) | t13d1516h2_8daaf6152771_d8a2da3f94cd | h2 | live capture 2026-06-13; Telegram Desktop issue #30733 |
Chrome 142 profile (curl_cffi chrome142) | t13d1516h2_8daaf6152771_d8a2da3f94cd | h2 | live capture 2026-06-13 |
Chrome Android 131 profile (curl_cffi chrome131_android) | t13d1516h2_8daaf6152771_02713d6af862 | h2 | live capture 2026-06-13; curl_cffi target docs |
Firefox 133 profile (curl_cffi firefox133) | t13d1716h2_5b57614c22b0_eeeea6562960 | h2 | live capture 2026-06-13; curl_cffi target docs |
Firefox 135/144 profiles (curl_cffi firefox135, firefox144) | t13d1717h2_5b57614c22b0_3cbfd9057e0d | h2 | live capture 2026-06-13; curl_cffi target docs |
Safari 18.4 profile (curl_cffi safari184) | t13d2014h2_a09f3c656075_7f0f34a4126d | h2 | live capture 2026-06-13; curl_cffi target docs |
Safari 26.0 profile (curl_cffi safari260) | t13d2014h2_a09f3c656075_d0a99439f9b1 | h2 | live capture 2026-06-13; curl_cffi target docs |
Safari 26.0.1 profile (curl_cffi safari2601) | t13d2013h2_a09f3c656075_7f0f34a4126d | h2 | live capture 2026-06-13; curl_cffi installed target list |
| curl 8.5.0 + OpenSSL 3.0.13 default | t13d3112h2_e8f1e7e78f70_375ca2c5e164 | h2 | live capture 2026-06-13 |
Go net/http Go 1.22.2 default | t13d1411h2_cbb2034c60b8_e7c285222651 | h2 | live capture 2026-06-13 |
Python requests default | t13d1712h1_ab0a1bf427ad_882d495ac381 | HTTP/1.1 | live capture 2026-06-13 |
Python httpx default | t13d1712h1_ab0a1bf427ad_8e6e362c5eac | HTTP/1.1 | live capture 2026-06-13 |
OpenSSL s_client -tls1_3 no ALPN | t13d410_16476d049b0b_78f1d400d464 | HTTP/1.1 | live capture 2026-06-13 |
OpenSSL s_client -tls1_3 -alpn h2,http/1.1 | t13d411h2_16476d049b0b_78f1d400d464 | HTTP/1.1 request after h2 ALPN offer | live capture 2026-06-13 |
| Real Chrome latest desktop | [varies by version] | varies | needs JA4DB/export or live real-browser capture |
| Real Firefox latest desktop | [varies by version] | varies | needs JA4DB/export or live real-browser capture |
| Real Safari latest desktop | [varies by version] | varies | needs JA4DB/export or live real-browser capture |
These hashes are environment- and version-specific: they identify the ClientHello and ALPN shape observed with a profile, library, OS, and build, not an eternal client name. The useful detector signal is the mismatch. A default Python, Go, or curl client emits its own non-browser JA4 even when the User-Agent claims Chrome, so JA4 should be read beside headers, HTTP/2 settings, IP reputation, and behavior as covered in the bot-detection stack and HTTP/2 fingerprinting.
Use the table as a lookup index, not a universal allowlist. If a log stores only the prefix, t13d1516h2 is enough to say “TLS 1.3, SNI, 15 ciphers, 16 extensions, h2,” but it is not enough to distinguish Chrome 131-style captures from newer Chromium-family captures. If the full a_b_c value is present, compare all three parts. Rows marked [varies by version] are deliberately unpinned because the ref-pack did not contain a verified literal hash for that real-browser/latest claim.
How a JA4 string is built
JA4 has three parts: ja4_a, ja4_b, and ja4_c, joined with underscores. ja4_a is the readable prefix. Its fields are protocol (t for TLS over TCP, q for QUIC, d for DTLS), TLS version, SNI flag (d when a domain/SNI is present, i when it is absent), two-digit cipher count, two-digit extension count, and the first and last character of the first ALPN value. In t13d1516h2, that means TLS over TCP, TLS 1.3, SNI present, 15 ciphers, 16 extensions, and HTTP/2 ALPN. For the deep prefix breakdown, use the t13d1516h2 prefix breakdown.
| Segment | Value in t13d1516h2 | Meaning |
|---|---|---|
| protocol | t | TLS over TCP (q=QUIC, d=DTLS) |
| TLS version | 13 | TLS 1.3 |
| SNI | d | SNI present (i = absent) |
| cipher count | 15 | 15 ciphers after GREASE removal |
| extension count | 16 | 16 extensions after GREASE removal |
| ALPN | h2 | first/last char of first ALPN = HTTP/2 |
ja4_b | _8daaf6152771 | 12 hex of SHA-256 over sorted ciphers |
ja4_c | _02713d6af862 | 12 hex of SHA-256 over sorted extensions + sigalgs |
ja4_b is the cipher hash. FoxIO defines it as the first 12 hexadecimal characters of SHA-256 over comma-delimited cipher hex codes sorted in hex order, with GREASE ignored. That sorting is the practical difference discussed in JA4 vs JA3: Chrome/Chromium extension and cipher ordering noise should not create a new identifier every time the same set is shuffled.
ja4_c is the extension plus signature-algorithm hash. It is the first 12 hexadecimal characters of SHA-256 over sorted extension hex codes plus signature algorithms in observed order. SNI (0000) and ALPN (0010) are excluded from the hash input because ja4_a already represents them, but they still count in the extension total. That is why two rows can share t13d1516h2_8daaf6152771 while differing only in the last 12 hex characters: the cipher set and readable shape stayed stable, while extension/signature details changed.
Part A is fast to read, but the full string matters. t13d1516h2_8daaf6152771_02713d6af862 and t13d1516h2_8daaf6152771_d8a2da3f94cd are both Chromium-family shapes in the table, yet they are not the same full fingerprint. A lookup system should key on the full a_b_c value when available, then degrade to the prefix only when the log source truncates it.
JA4 also changes when the wire shape changes. Browser version, platform TLS stack, QUIC versus TCP, ALPN list, PSK/resumption behavior, and library updates can all move a client to a new row. JA4DB is the canonical lookup target, but unauthenticated rows were not harvested for this table; the literal hashes above come from public docs, public examples, or live tls.peet.ws captures.
Replaying a fingerprint
curl_cffi is the Python binding over the active Lexiforest curl-impersonate fork. Its impersonation targets replay browser-like TLS, JA4, JA3, and HTTP/2 profiles with calls such as impersonate="chrome131", impersonate="chrome136", impersonate="firefox135", or impersonate="safari260". Pin target names for reproducible captures. Generic aliases like chrome, firefox, and safari move as the package adds newer profiles.
Replaying is not the same as becoming a browser. A Chrome-like JA4 paired with Python-ish headers, non-Chrome HTTP/2 SETTINGS, wrong pseudo-header order, or mismatched IP reputation is still inconsistent. The safer workflow is to capture the target profile at https://tls.peet.ws/api/all, record tls.ja4, compare the HTTP/2 signal, then use that result in tests. The operational library matrix in the TLS impersonation library comparison
and the curl_cffi notes in the curl_cffi TLS fingerprinting notes cover where TLS replay ends and application-layer parity begins.
For debugging blocks, run the same request body through the normal stack and an impersonated stack from the same egress. If both fail the same way, the gate is probably not the ClientHello. If the impersonated path changes the result, inspect JA4, JA3, HTTP/2 SETTINGS, header order, cookies, and origin behavior before assuming the hash alone was decisive.
Sources
- FoxIO JA4 repository — canonical JA4+ spec and tooling entrypoint.
- FoxIO JA4 technical details — algorithm source for
ja4_a,ja4_b, andja4_cconstruction. - JA4DB — official lookup target for JA4+ fingerprints, applications, and detection logic.
- curl_cffi impersonation targets — supported Chrome, Firefox, Safari, and mobile target names.
- curl_cffi repository — the Python binding that replays browser TLS/JA3/JA4/HTTP2 profiles.
- curl-impersonate (Lexiforest fork) — the actively maintained curl-impersonate fork curl_cffi builds on.
- tls.peet.ws API — live TLS/JA3/JA4/HTTP2 reflection endpoint used for capture rows.
- Cloudflare JA4 Signals — public JA4 deployment context and Chrome extension-hash example.
- bunny.net JA4 fingerprinting docs — CDN header behavior and published
t13d1516h2_8daaf6152771_02713d6af862example. - Google Threat Intelligence JA4 deep dive —
behavior_network:lookup example using the published Chrome-family string. - Telegram Desktop issue #30733 — public occurrence of
t13d1516h2_8daaf6152771_d8a2da3f94cdas a Chrome-family mismatch report.