Anti-bot teams never trust what a client says about itself. The User-Agent header is a string anybody can set, and the TLS handshake that websites actually fingerprint can be borrowed from a real browser with the right client library. But there is a third layer that gets far less attention, and it is the hardest one to fake: the IP and TCP headers of the packets that physically arrive at the server. Those are produced by the kernel of the machine that sends them, not by anything your HTTP client configures.

This post is about what that layer reveals. We captured the opening packets of four different connections to one of our own servers, including two exits from our own UK mobile proxy fleet, and read them the way an anti-bot engineer would. The short version: a proxy exit that is a real phone does not need to imitate anything, and the details that prove it are exactly the details a pool of emulated exits gets wrong.

What a SYN packet leaks

Every TCP connection starts with a SYN packet, and its headers are full of small facts set by the sender's operating system:

None of these fields travel through your proxy client's configuration. Whatever machine's network stack actually emits the packets is what the destination sees.

The experiment: four connections, one server

We pointed four different connections at a plain Ubuntu server we control, capturing every arriving SYN on port 80 with tcpdump and naming them with p0f, the standard passive fingerprinting tool (version 3.09b), which reads the same fields and estimates the sender's operating system, hop distance and link MTU from a single packet.

The four sources:

  1. a desktop Linux workstation on a UK fixed-line connection, connecting directly;
  2. a second Ubuntu server in the same datacenter, connecting directly (the datacenter baseline);
  3. through our SOCKS5 endpoint pinned to a device on the EE network, using the -ee username token;
  4. the same, pinned to a device on the Three network (-three).

The proxied connections used the ordinary public endpoint, no different from any customer request:

curl -x socks5h://USER-ee:PASS@proxy.simplyproxies.com:6890 http://<server>/

Each request exits from a different real device (the fleet rotates), so the exit IP is a fresh carrier address per run. An identity check on one EE-exit run, queried through ip-api.com, returned:

{"country":"United Kingdom","isp":"British Telecommunications PLC",
 "org":"EE Limited","mobile":true,"query":"31.94.6.212"}

Results:

Connection p0f OS guess Hop distance MSS (implied MTU) TCP window, scale Options, in order
Workstation, direct Linux 2.2.x-3.x 16 1460 (1500) 64240, wscale 7 mss, sackOK, TS, nop, wscale
Datacenter server Linux 2.2.x-3.x 16 1460 (1500) 64240, wscale 7 mss, sackOK, TS, nop, wscale
Mobile exit, EE-hosted Linux 2.2.x-3.x 18 1362 (1402) 65535, wscale 9 mss, sackOK, TS, nop, wscale
Mobile exit, Three-hosted FreeBSD 21 1320 (1360) 65535, wscale 12 mss, nop, wscale, sackOK, TS

p0f condenses each SYN into a raw signature. The EE exit's reads:

raw_sig  = 4:46+18:0:1362:65535,9:mss,sok,ts,nop,ws:df,id+:0
|            |  |       |    |    |   |
|            |  |       |    |    |   +-- option list: mss, sackOK, timestamps, nop, window scale
|            |  |       |    |    +------ window scale factor 9
|            |  |       |    +----------- advertised window 65535
|            |  |       +---------------- MSS 1362
|            |  +------------------------ 18 hops travelled
|            +--------------------------- TTL 46 on arrival
+---------------------------------------- IPv4

Reading the results like an anti-bot engineer

All four connections are 64-class. The workstation and the datacenter server arrived 16 hops out (TTL 48); the two phones arrived 18 and 21 hops out (TTL 46 and 43). That is consistent with every source being a Linux-family kernel starting at 64, which Android phones are. Nothing here pretends to be anything.

The mobile exits advertise smaller segments. MSS 1362 and 1320 imply path MTUs of 1402 and 1360, against 1500 for both fixed-line sources. That is the cellular path showing through: carrier backhaul and NAT44 equipment run smaller effective MTUs, and the phone's kernel scales its opening segment to match. No HTTP library decides this. It comes from the route, on the carrier's network, at connection time.

The two phones do not match each other. Different window scale factors (9 and 12) and a different option order. They are different physical devices with different kernel builds, on different carrier paths. A synthetic pool emulating "Android" tends to converge on one polished signature; a fleet of real devices drifts the way real traffic does.

And a lesson in humility: p0f got one wrong. It guessed FreeBSD for the Three-hosted exit. Its signature table is over a decade old, and kernels built since then can fall outside it entirely. Passive fingerprinting produces hints, not verdicts. That cuts both ways: it means a coherent real device can be misnamed, and it also means a well-built emulation can survive a casual look. Serious anti-bot systems weigh the whole stack, not one tool's guess.

The purchased comparison: another provider's UK mobile pool

Fingerprinting your own exits is only half the story, so we ran the same session's checks against a competing product: a paid subscription to a commercial UK "mobile" proxy pool from another provider (kept unnamed; the point is the check, not the brand). The plan was the same packet capture, but their gateway refused the destination before any packet flew. A raw-IP target is rejected outright with a SOCKS5 "connection not allowed by ruleset" reply (code 2 in the SOCKS5 specification), so the exit can only be reached through hostnames, and the two hostnames under our own control were refused just as instantly. Long-established connectivity-check domains used in the same tests passed without trouble. Why specific hostnames are refused is the provider's policy, not something an outsider can inspect; the practical effect is stated plainly: no packet-layer capture against this pool was possible, so for this product the comparison rests on the layer anti-bot systems check first, what IP intelligence sees.

So for this pool the packet layer is off the table, and we compared at the layer anti-bot systems check first: what IP intelligence sees. Six rotating exits, each queried through ip-api.com (one cross-checked on ipinfo.io) in the same session as our own checks above:

Exit ASN IP-intelligence classification
86.147.174.211 AS2856 British Telecommunications mobile: false
109.147.231.92 AS2856 British Telecommunications mobile: false
82.43.185.13 AS5089 Virgin Media mobile: false
82.35.120.116 AS5089 Virgin Media mobile: false
86.191.212.69 AS2856 British Telecommunications mobile: false
81.136.87.164 AS2856 British Telecommunications mobile: false (reverse DNS: ...btcentralplus.com, a BT consumer range)

Six for six UK fixed-line consumer ranges. Not one mobile-carrier ASN. Our own exits, checked through the same API minutes apart, returned mobile: true on every run, from carrier ASNs (Hutchison 3G, Telefonica UK, EE Limited).

What you make of that depends on your task. If a site greets fixed-line consumer IPs and mobile-carrier IPs the same way, nothing is lost. But the plan is sold as mobile, and a buyer running the industry-standard check sees mobile: false on every sample: the label did not survive the check. Whether those exits are phones parked on home Wi-Fi, recycled fixed-line hardware, or something else inside the pool, we cannot see, and we will not guess; what a buyer can verify from outside is exactly what we have quoted.

The honest caveats, stated plainly: one provider, one plan, one afternoon, six rotating samples, at one point in time. Pools change; another region or month might differ. But the asymmetry of effort is the part worth remembering. Checking took one API call per exit. Selling the story takes a fleet.

Why this matters for proxies

The signal an anti-bot system really uses is coherence. Each layer of a connection is set by a different component: the HTTP library sets headers and (with the right library) the TLS fingerprint; the operating system sets TTL, MSS and the TCP option list; the network path sets the hop count and, through its MTU, the MSS. When a visitor claims one thing and their packets say another, the layers disagree.

A browser-impersonating scraper behind a datacenter proxy is the classic mismatch: the TLS handshake and User-Agent say Chrome on Windows, but the SYN says a Linux server kernel on a 1500-MTU network a few hops from a hosting company. Each piece is individually defensible; together they are a costume with the tag still on.

A real phone exit is the opposite case. The IP registry says mobile carrier, the MSS says a 1400-class cellular path, the TTL distance says many hops from a 64-class phone kernel, and the TLS and headers, if you run a mobile-profile client, say a phone too. Nothing is being imitated, so nothing can fall out of character.

The honest limit runs in both directions. A phone cannot pretend to be Windows, and no proxy can make it: the exit's packets are what they are. If your targets are mobile sites and apps, a phone exit is not a workaround, it is the genuine article. If you specifically need to look like a desktop on a fixed line, pick an exit that is one.

Try it yourself

On any Linux server you control:

# capture incoming SYNs (let the capture finish before reading the file)
sudo tcpdump -i any -w /tmp/syn.pcap 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0 and port 80'

# read them back: TTL, window, options
tcpdump -nn -vv -r /tmp/syn.pcap | head

# or let p0f interpret: OS guess, hop distance, link MTU
p0f -r /tmp/syn.pcap

Connect once directly and once through your proxy, then compare the two SYNs: TTL class and hop distance, MSS and implied MTU, window scale, option order. If your proxy's exit tells the same story as the IP it hands out, you are looking at a real machine. If the story contradicts the HTTP and TLS layers above it, you have found the seam.

Summary

Last verified 2026-10-21

Try It With Real UK Mobile IPs

Run the examples in this guide through genuine UK 4G/5G exits. 500 MB free, no card required.

Start Free Trial