Traces how anti-bot scripts re-read the browser fingerprint from nested iframes, about:blank/srcdoc frames, and web workers, the exact contexts where injected stealth code often never runs.
Traces how websites enumerate a visitor's installed extensions: web-accessible-resource probing, DOM and stylesheet artifacts, intra-browser messages, and timing side channels, plus the Chrome and Firefox mitigations that close some of those doors.
Traces the classic Notification.permission vs navigator.permissions.query('notifications') contradiction in headless Chrome: where the signal comes from, why the two APIs use different enums, and why patching it is harder than it looks.
How detectors spot a browser running in a VM or container: software WebGL renderers like SwiftShader and llvmpipe, default 800x600 screens, quantized device memory, and timing artifacts under virtualization.
Traces navigator.plugins from a 15-bit fingerprinting signal to the five hard-coded PDF entries Chrome and Firefox ship today, the empty array that gave away old headless, and why fabricating a PluginArray still leaks.
A field-by-field dissection of the TLS ClientHello, tracing exactly which bytes JA3 and JA4 read: version, cipher suites, compression, extensions, supported_groups, signature_algorithms, supported_versions, key_share, and ALPN.
A reference walk through the full JA4+ suite: how each of JA4, JA4S, JA4H, JA4L, JA4X, JA4T and JA4SSH is constructed, what it captures, and how the a_b_c format lets the parts compose.
A deep dive into uTLS: how the Go library forges a chosen browser's ClientHello through ClientHelloID parrots and handshake control, why Go's crypto/tls is otherwise easy to fingerprint, and where the mimicry still leaks.
Traces GREASE (RFC 8701), the reserved random values browsers inject into the TLS ClientHello to keep extension points usable, and the reason fingerprinting that fails to normalize them produces a different hash on every connection.
Traces how the cipher_suites list and its exact order in a TLS ClientHello identify a client, why that order is fixed per build, and why reordering it to evade detection becomes its own signal.
How the order of TLS extensions became a fingerprint, why Chrome started shuffling that order in early 2023 with a Fisher-Yates permutation in BoringSSL, and how JA4 answered by sorting the list.
How detectors catch tools that forge a perfect browser ClientHello: the mismatch between the TLS layer and the HTTP/2 frames above it, library-specific residue, header order, and version drift.
How TLS session resumption becomes a fingerprint and a behavior signal: session tickets, TLS 1.3 PSK, 0-RTT early data, and the resumption patterns that reveal a client or break a spoof.
Traces how the ALPN protocol list in a TLS ClientHello, and its predecessor NPN, fingerprints a client, and why the offered protocols and their order must agree with the HTTP layer that follows or the whole session looks forged.
A version-by-version catalog of how Chrome, Firefox, Safari, and Edge ClientHellos changed from 2015 to 2026: GREASE, extension permutation, post-quantum key shares, and what a current per-browser fingerprint looks like.
Where TLS fingerprints are actually computed in a server stack: the OpenSSL and BoringSSL callbacks that hand you the raw ClientHello, the nginx, HAProxy, and Envoy modules built on them, and the constraints that decide whether you get the bytes at all.
Traces how a default Python requests handshake gives itself away in the ClientHello: the OpenSSL cipher list, the extension set, the missing GREASE, and why curl-cffi and uTLS-style impersonation exist.
A reference for the HTTP/2 client fingerprint: the SETTINGS frame parameters, the WINDOW_UPDATE increment, the priority frames, the pseudo-header order, and the S|WU|P|PS string Akamai popularised in 2017.
Traces how the order of the :method :authority :scheme :path pseudo-headers fingerprints an HTTP/2 client, why each browser and library orders them differently, and why the signal is a clean browser-vs-client tell that survives header spoofing.
Traces HTTP/2 stream prioritization as a fingerprint: how browsers built dependency trees, why RFC 9113 deprecated the original scheme, what RFC 9218 replaced it with, and which part of the priority signal still labels a client.
How a QUIC client gives itself away before any application data flows: the unencrypted Initial packet, the transport parameters in the TLS-in-QUIC ClientHello, version negotiation, and why server-side detection here is still near-greenfield.
A packet-level tour of the QUIC Initial: long header, version, connection IDs, the salt-derived initial keys, datagram padding, packet coalescing, and what stays observable on the wire for fingerprinting.
How a forged TLS handshake plus a generic HTTP/2 library still contradicts itself at the frame level, and how anti-bot systems turn that cross-layer mismatch into a bot verdict.
Traces how HTTP/1.1 header order and field-name casing fingerprint a client, why every browser and library emits a fixed sequence, and how HTTP/2's mandatory lowercasing erased half the signal while keeping the rest.