TLS & HTTP transport
Your TLS Handshake, Reflected Back
What the front-end web server saw at the transport layer, plus any JA3 / JA4 the edge chose to publish.
TLS & HTTP transport
Fetching /api/tls.php...
What you can and can't see
This site sits on a shared web host that terminates TLS itself and only surfaces the highlights (version, cipher, ALPN, SNI) to PHP. That's already enough to tell TLS 1.2 from 1.3, HTTP/1.1 from HTTP/2, and to guess your cipher family. Full JA3 / JA4 hashes require a TLS-terminating proxy that writes them as a request header.
TLS-layer signals to watch
- TLS 1.0 / 1.1 = ancient client, likely misconfigured library.
- TLS 1.3 with AES-128-GCM = modern Chromium default.
- TLS 1.3 with CHACHA20 = mobile browser or Firefox on ARM.
- ALPN missing entirely = a very old HTTP library.
- HTTP/1.1 on a modern browser UA = suspicious (real Chrome negotiates HTTP/2 wherever possible).
Note on TCP
TCP-level fingerprinting (initial window size, MSS, TCP options order) can also identify OSes, but it lives below PHP's reach on shared hosting. It shows up in commercial anti-bot products via kernel-level probes at the edge.
Frequently asked questions
→What is TLS fingerprinting?
The TLS ClientHello a browser sends is far richer than the eventual application-layer HTTP: it lists cipher suites in a specific order, advertises extensions in a specific order, includes elliptic curves, signature algorithms, and ALPN protocols. Each real browser has a distinctive shape. JA3 and JA4 are two ways to hash that shape into a fingerprint string.
→Can PHP see the JA3/JA4 fingerprint?
Only if the front-end proxy or load balancer computes it and forwards it as a request header. Cloudflare exposes cf-ja3 / cf-ja4 with Bot Management enabled; HAProxy can be configured to add JA3 via a Lua script; nginx needs the ssl-ja3 module. If your host doesn't do any of that, PHP sees nothing.
→Why do HTTP libraries fail TLS fingerprint checks?
Because Python's requests uses OpenSSL, Go uses crypto/tls, curl uses whatever it was compiled against. Each library has its own ClientHello shape, distinctly different from real Chrome / Firefox / Safari. Anti-bot vendors keep pre-computed JA3 hashes for every popular library and match incoming traffic against them.
→How do scrapers get around TLS fingerprinting?
Two main approaches. First, wrap a library that replicates a real browser's ClientHello: curl_cffi (Python), utls (Go), Node's undici with the right SSL_CIPHER_LIST. Second, drive a real headless browser, which by definition speaks like a real browser. The latter is more reliable but heavier.
→What does HTTP/2 vs HTTP/3 change?
HTTP/2 has its own fingerprint: the SETTINGS frame values, the header table size, the initial window, the priority tree, and the header order all differ per client. Akamai and Cloudflare compute HTTP/2 fingerprints on top of TLS ones. HTTP/3 (QUIC) is even more identifying because it moves TLS into UDP and adds its own transport parameters.