< Back

TLS and TCP Fingerprinting Explained: The Detection Layer That Flags Proxies Even When the IP Looks Clean

Tech

A team runs a scraper through a fresh residential IP. The address checks out on every reputation lookup: clean ASN, no blocklist entries, plausible geolocation, matching timezone. The request still returns a 403 before a single byte of HTML arrives. No CAPTCHA, no rate-limit warning, no chance to argue.

That outcome usually has nothing to do with the IP. It happens in the first few packets, before HTTP headers exist and before JavaScript can run. The server looked at how the connection was established: the shape of the TCP handshake, the byte layout of the TLS ClientHello, the parameters in the HTTP/2 SETTINGS frame. Those signals identified the client as an automation library pretending to be Chrome, and the decision was made in microseconds.

This is the detection layer most teams discover last, usually after burning through a pool of perfectly good IPs. Understanding it changes how you build scraping and automation infrastructure, and it changes what you should expect from your proxy provider.

Why Network-Layer Fingerprinting Beats IP Reputation

IP reputation is expensive to maintain and easy to evade. Fingerprinting the connection is cheap, passive, and hard to fake. A CDN edge node sees millions of handshakes per second and can hash the distinguishing features of each one into a short identifier. If that identifier matches a known automation stack, the request can be dropped before it ever reaches the origin.

The economics favour the defender here. Rotating an IP costs the operator money. Changing a TLS fingerprint requires either a real browser or a patched cryptographic library, which most scraping stacks do not ship with by default.

There is a second reason this layer is powerful: it is a consistency check. Anti-bot systems rarely block on a single signal. They compare what your traffic claims to be against what it demonstrably is. A user agent string claiming Safari on iOS paired with a TCP stack that looks like a Linux server is not suspicious because either half is bad. It is suspicious because the halves contradict each other.

TCP/IP Fingerprinting: The Operating System Speaks First

Before any encryption is negotiated, the SYN packet already leaks details about the sending machine. Passive OS fingerprinting tools have exploited this for two decades, and the technique survives in modern bot management.

The useful fields include:

  • Initial TTL. Linux and macOS typically start at 64, Windows at 128, some network appliances at 255. Combined with observed hop count, this narrows down the sending platform.
  • TCP window size and window scale factor. Different stacks and tuning profiles produce characteristic values.
  • Maximum segment size. A standard Ethernet path yields 1460. Values such as 1360 or 1400 often indicate an encapsulated tunnel with MSS clamping applied somewhere in the path.
  • TCP options and their exact order. The sequence of MSS, SACK-permitted, timestamps, NOP padding, and window scale differs meaningfully between operating systems and kernel versions.
  • TCP timestamps. These can expose approximate system uptime and clock skew. If a hundred supposedly independent visitors share the same clock skew signature, that is a strong clustering signal.

None of these are configurable from application code. They come from the kernel of whichever machine actually opens the socket, which matters enormously once a proxy sits in the path.

TLS Fingerprinting: JA3, JA4, and the ClientHello

The TLS ClientHello is sent in the clear and is remarkably distinctive. It advertises the supported TLS versions, the ordered list of cipher suites, the list of extensions in the order the client wrote them, supported elliptic curves, EC point formats, signature algorithms, and ALPN protocols.

JA3 was the first widely adopted method for turning that into a fingerprint: concatenate those fields, hash the result, and compare against a library of known clients. It worked well enough that anti-bot vendors built large databases of JA3 hashes mapped to real browser builds, scripting libraries, and known bot frameworks.

JA3 has since aged. Chrome began randomising the order of TLS extensions, which made a single hash unstable across sessions and forced detection systems to adapt. JA4 and its related fingerprints answer that by sorting the volatile components, separating the fingerprint into readable segments rather than one opaque hash, and incorporating signals like ALPN and the number of extensions. The practical consequence for operators is that shuffling extensions is no longer a workaround. The rest of your handshake still identifies the library that produced it.

A few common fingerprints are effectively self-reporting. Python's default HTTPS stack, Go's crypto/tls, Node's undici, and stock curl each produce a ClientHello that no consumer browser would ever send. Pairing any of them with a browser user agent is one of the most reliable bot signals available.

HTTP/2 Fingerprinting: The Layer Above

Once TLS completes and ALPN negotiates h2, the connection reveals another set of parameters. The HTTP/2 SETTINGS frame carries values for header table size, initial window size, maximum concurrent streams, and maximum frame size. Real browsers send specific, stable combinations. The initial WINDOW_UPDATE increment, whether stream priority information is included, and the order of the pseudo-headers (:method, :authority, :scheme, :path) all vary between implementations.

Ordinary header order matters too. Browsers emit request headers in a consistent sequence, and libraries that build headers from an unordered map do not. Anti-bot vendors combine these into an HTTP/2 fingerprint that sits alongside the TLS one, and cross-check both against the declared user agent.

Where Teams Get This Wrong

Fixing the user agent and nothing else. Rewriting the UA string while leaving the underlying TLS stack untouched makes traffic more detectable, not less, because it creates a contradiction that would not otherwise exist.

Assuming residential IPs are sufficient. A high-trust IP raises the ceiling on how much traffic you can send. It does not repair a handshake that identifies your client as a scripting library.

Running requests through a TLS-terminating middlebox. Any component that decrypts and re-encrypts traffic replaces your client fingerprint with its own. Debugging proxies and some corporate gateways do exactly this, which is why a script can pass locally and fail in production.

Treating headless browsers as automatically safe. A real browser engine gives you a genuine TLS and HTTP/2 fingerprint, which is a large advantage. It does not protect you from higher-layer checks, and some headless configurations still alter negotiation defaults.

Never measuring the fingerprint at all. Most teams debug this blind. Capturing what your stack actually sends, from the exit IP it will use in production, turns guesswork into a measurable variable.

Where Proxies Fit In

Proxies do not create fingerprints, but they sit in the path where fingerprints are formed, and the type of proxy you use determines what the target server observes.

The key distinction is which machine opens the TCP connection to the target. When traffic is tunnelled through a SOCKS5 or HTTP CONNECT proxy, the TLS handshake passes through untouched, so the target sees your client's TLS fingerprint. The TCP/IP characteristics, however, come from the exit node's kernel. That is why the plausibility of the combination matters: a residential IP fronted by a well-behaved consumer network stack tells a coherent story, while an IP that geolocates to a home broadband subscriber but presents a hardened server stack does not. Working through ethically sourced residential and mobile proxy pools with real network paths behind them keeps the lower layers consistent with the story the IP tells.

Session control is the second contribution. TCP timestamps, connection reuse patterns, and HTTP/2 connection lifetime all carry clustering signals. Being able to hold a sticky session for the duration of a logical task, then move cleanly to a different exit, prevents dozens of workers from collapsing into a single behavioural cluster. This is where pool diversity earns its cost: residential, ISP, datacenter, and mobile exits each present different transport characteristics, and matching the pool to the target's tolerance is a genuine engineering decision. EnigmaProxy covers all four pool types with business-grade reliability and broad geo-coverage, which makes that matching exercise practical rather than theoretical.

Finally, verify before you scale. Running your client through a proxy testing tool and comparing what the far end reports against what you intended is the fastest way to catch a leaking DNS resolver, an unexpected MSS value, or a handshake that no longer matches the browser you claim to be.

Where This Is Heading

Fingerprint suites replace single hashes. The move from one opaque hash to segmented, multi-layer fingerprints across TCP, TLS, and HTTP/2 makes evasion by superficial mutation far less effective. Expect detection to be scored across layers rather than matched against a blocklist.

Encrypted ClientHello narrows the surface, slowly. ECH hides some handshake detail from passive observers on the path, but the destination server still sees the inner handshake. Edge providers will keep fingerprinting because they are the endpoint, not an eavesdropper.

Machine learning over consistency, not signatures. The valuable question for a defender is no longer "have I seen this hash before" but "do these signals belong together". Coherence across IP type, transport stack, TLS handshake, and behaviour becomes the thing to optimise.

QUIC and HTTP/3 add a new fingerprint surface. QUIC initial packets, transport parameters, and version negotiation are already being profiled. Teams standardising on HTTP/3 should assume the same scrutiny applies there.

Conclusion

A clean IP is table stakes, not a strategy. If your success rate collapses despite good addresses, the problem is usually a contradiction between layers: an automation library's handshake wearing a browser's name, or a consumer IP fronted by a stack that no consumer device would produce.

The fix is coherence. Use clients that produce authentic TLS and HTTP/2 fingerprints, avoid middleboxes that rewrite your handshake, keep sessions scoped to logical tasks, and choose exit types that match what you claim to be. Getting the transport layer right makes the IP layer far more forgiving, and a provider like EnigmaProxy, with diverse and ethically sourced pools, gives that work a stable foundation to build on.