Introduction
Passive OS fingerprinting is how a server works out which operating system you use from the first packet your device sends to open a connection. It asks nothing and sends nothing back. That packet, the TCP SYN, is built by the operating system's network stack, not by the browser, and Windows, Linux and Apple systems each build it a little differently. So the packet carries the family of the system that sent it.
On its own this is a small leak. A website learns you are on Windows, which your browser usually tells it anyway. It becomes useful to anti-fraud and bot-detection systems when they compare it with what the browser claims. A browser that reports Windows over a packet that looks like Linux usually means a proxy or a VPN server sits in between. A browser that reports Windows over a packet that looks like a Mac usually means the browser is not telling the truth about the system it runs on.
If sites keep showing you CAPTCHAs while you use a proxy or a VPN, this mismatch can be part of the reason. The CAPTCHA Trap explains which other signals push a site to challenge you.
Passive OS Fingerprinting, in One Paragraph
Every TCP connection starts with a handshake, and the client speaks first with a SYN packet. Its header carries values the operating system picks by default: the initial TTL, the receive window, the maximum segment size, the window scale, and a list of TCP options in an order the standard leaves open. Read together, these values form a TCP fingerprint, and reading them is called TCP fingerprinting, or TCP/IP stack fingerprinting. The difference between active and passive OS fingerprinting is whether the observer sends any packets of its own. A passive fingerprinter only reads packets that arrive anyway. An active one, like Nmap's OS detection, sends its own probes and studies the replies, which shows up in firewall logs. The best-known passive tool is p0f, which turns the SYN into an OS label. JA4T, published by FoxIO in 2024, writes the same packet down as a short string such as 64240_2-1-3-1-1-4_1460_8, which FoxIO lists as Windows 11. Neither needs JavaScript or cookies, and the browser has no say in either.
What the First Packet Contains
The fields
- Initial TTL. Every router a packet crosses lowers its TTL by one (IPv6 calls it the hop limit). The receiver sees the reduced number and rounds it up to the nearest usual starting value. p0f's documentation notes that almost every system starts at 64, 128 or 255. Linux and Android start at 64, which is the kernel default. macOS and iOS also start at 64, the default in Apple's XNU kernel. Windows starts at 128.
- Window size. How many bytes the sender will accept before it has to acknowledge them. The field is 16 bits, so it tops out at 65,535, and RFC 7323 says the window in a SYN is never scaled.
- Window scale. An option that multiplies the window of every later packet by a power of two, up to 2 to the 14th. RFC 7323 ties it to the receive buffer the system reserves, so it depends on the operating system but also on memory and tuning.
- MSS. The maximum segment size, the largest amount of data the sender wants in one packet. It follows from the link. Ethernet carries 1,500-byte packets, and IPv4 and TCP headers take 40 of those bytes, which leaves 1460. IPv6 headers take 60, so the same link gives 1440. A DSL line using PPPoE commonly gives 1452, and a tunnel lowers the value further because its own headers need room.
- The options and their order. A SYN lists its options by number: 2 for MSS, 3 for window scale, 4 for "SACK permitted", 8 for timestamps, 1 for a no-op padding byte and 0 for end of list. RFC 9293 defines how options are encoded, not which order they come in, so each stack writes them its own way. p0f's documentation calls the option layout "one of the most valuable TCP fingerprinting signals".
Three families, three layouts
The option layout separates the three families on its own. The timestamp and the TTL confirm it.
| System family | Option layout in the SYN | Timestamp | Initial TTL |
|---|---|---|---|
| Windows | 2-1-3-1-1-4: MSS, no-op, window scale, no-op, no-op, SACK permitted | Not sent by default | 128 |
| Linux, Android, ChromeOS | 2-4-8-1-3: MSS, SACK permitted, timestamp, no-op, window scale | Sent | 64 |
| macOS, iOS, iPadOS | 2-1-3-1-1-8-4-0: MSS, no-op, window scale, no-op, no-op, timestamp, SACK permitted, end of list | Sent | 64 |
The layouts come from p0f's signature file and match FoxIO's notes: Windows does not use the timestamp option, Unix-based systems do, and Apple's list ends with an end-of-list marker.
What the packet cannot do reliably is split a family. macOS and iOS share the XNU kernel and send the same layout. p0f's own signature for recent Macs is labelled "MacOS X 10.9 or newer (sometimes iPhone or iPad)". Desktop Linux, Android and ChromeOS share the Linux kernel. Window size and scale do differ between versions and devices, but they move with memory, settings and the network, so a split based on them is a guess.
Whose Packet Does the Server See?
A server can only fingerprint the machine that opened the TCP connection to it. Whatever sits between you and the site decides whose SYN that is.
Home router and carrier NAT. Address translation rewrites addresses and ports, but your device still builds the SYN, so your system shows through. That is how p0f can tell that several systems share one address.
A VPN tunnel. WireGuard, OpenVPN in its usual tunnel mode and IPsec wrap your IP packets inside their own. The VPN server unwraps them and sends them on, so the site receives the SYN your system built. It carries the VPN's address, and the MSS is usually smaller because the tunnel headers take space.
A proxy. An HTTP proxy, a SOCKS proxy, the Shadowsocks and Trojan family, residential proxy networks and corporate web proxies all take your data and open their own TCP connection to the site. RFC 9110 describes an HTTP CONNECT proxy exactly this way: it connects to the requested server and then forwards bytes. The site fingerprints the proxy server, and proxy servers typically run Linux.
A VPN service that does both. In May 2024 FoxIO reported two consumer VPN services that handed the web ports, 80 and 443, to a proxy on their own servers. On those ports the destination saw a Unix fingerprint whatever the client was, while on another port the client's own Windows layout came through the tunnel.
Tor. Tor carries TCP streams, not IP packets, and the exit relay opens the connection to the website. The Tor Project's FAQ on alternate designs lists "IP packets reveal OS characteristics" among the problems with forwarding packets instead. The site fingerprints the exit relay.
What each of these tools hides, and from whom, is compared side by side in VPN vs Proxy vs Tor.
A CDN in front of the site. Many sites sit behind a CDN or a load balancer that terminates TCP itself. The site's own server then never sees your SYN, and only the CDN can read it.
Your Proxy Says Windows, Your Packets Say Linux
An OS mismatch, which some detection tools call a TCP fingerprint anomaly, can go two ways, and they carry different weight.
The first is a Linux packet under a browser that reports Windows, macOS or iOS. This is what a proxy, a proxy-based VPN, a scraper on a cloud server or an automation script in a Linux container looks like when it sends a Windows User-Agent. The packet alone cannot tell an honest Windows user behind a Linux proxy apart from a Linux machine that pretends, so detection systems tend to read it as "probably a proxy" and then check the address against VPN and hosting lists. The pattern is well enough known that some proxy providers sell a setting that makes their servers' SYN imitate Windows or macOS. Their own documentation gives the reason: the servers run Linux, and anti-fraud systems notice the gap.
The second is a Windows or Apple packet under a browser that reports a different family. Proxy servers typically run Linux; Windows proxies are uncommon and Mac ones rare, so this packet most likely came from the device itself, and the browser is the part that is wrong. That is the classic trace of an anti-detect browser, which rewrites the User-Agent, the platform and the Client Hints but cannot reach the kernel that builds the SYN. A VPN tunnel does not hide it, because the tunnel forwards the real packet. The tools that do this are covered in Fake Browser Detection, and the same lie seen from inside the browser is the subject of Device Integrity.
A third layer helps decide the ambiguous case. A proxy that only relays bytes, as CONNECT and SOCKS do, passes the browser's TLS handshake through untouched. So a Safari-style TLS fingerprint under a Linux SYN points to a real Apple device behind a proxy, not to a Linux machine in disguise. TLS Fingerprinting explains that layer.
None of this is proof. A careful anti-detect setup, or a proxy with that imitation setting turned on, sends a SYN that matches the claimed system, and then there is nothing to catch. An honest user can also land in the second case, for example a Mac behind a corporate web proxy that runs on Windows.
TCP Fingerprint Test: the packet.guru TCP/OS Card
The TCP/OS Fingerprint card of the Privacy & Trust Index runs this comparison on your own connection, and it can only read the packet of the visitor who opened the page. It names one of three families, Windows, Apple (macOS and iOS) or Linux and Android, and compares it with the operating system your browser reports about itself.
If your traffic leaves from more than one address, for example over both IPv4 and IPv6 or through a split VPN route, the card says so in its details.
| Result | What it means | What to do |
|---|---|---|
| OS match | The connection and the browser name the same family. | Nothing |
| OS mismatch, red | The connection shows Windows or Apple, and the browser reports another family. Your real system got past the browser's claim. | Find what changes your browser's reported OS. See the next section. |
| OS mismatch, orange | The connection shows Linux under a browser that reports another family: usually a proxy, a VPN server or a relay in front of you. In some cases the details name it: a VPN, a datacenter network, iCloud Private Relay. | Nothing if you use one on purpose. If you do not, check what routes your traffic. |
| OS hidden by Tor | A Tor exit opened the connection, so your system never reached the site. | Nothing |
| Undetermined or probe unreachable | The card could not read the operating system from your connection this time. | Nothing. No conclusion is drawn. |
Of these results, the red one weighs most on the Trust score. An orange result weighs little, because a proxy or a VPN you chose is not a lie. Whether the address itself belongs to a VPN or a datacenter is a separate question, covered in IP Reputation. The badge on the card shows how your own result counts, and its details say how sure the card is.
Below the cards, the Connection Fingerprint panel prints the raw values: the detected family, the initial TTL, the window, the MSS, the window scale, whether SACK and timestamps are present, and your JA4T string.
How to Make the Two Layers Agree
If the card shows a red mismatch you did not expect, something is changing what your browser reports. The usual causes are a User-Agent switcher extension, an anti-detect profile, the device emulation in the browser's developer tools, or a setting that overrides the User-Agent. Turn it off or use a clean browser profile. The fix belongs in the browser, because the packet is the part telling the truth.
If you want your system hidden at the network layer, a tunnel VPN will not do it. A proxy that opens its own connections, or Tor, replaces your fingerprint with the server's. That trades one signal for another: the site then sees a server's packet under a desktop browser, which reads as a proxy.
Do not try to make the packet match a fake. Rewriting the SYN to fit a borrowed identity is what anti-detect operators do, and it only matters when the browser is already lying. For an ordinary user the safest profile is a consistent one: your real browser on your real system, behind a VPN if you like. Fake Browser Detection explains why hiding and faking get treated so differently.
If you run detection yourself, read the SYN where TCP actually terminates, which behind a CDN means at the CDN or on a host reached directly. Treat a Linux packet under a desktop browser as a proxy hint, a Windows or Apple packet under a different claim as the stronger signal, and neither as a reason to block on its own.
p0f and JA4T: Two Ways to Record the Same Packet
p0f was written by Michał Zalewski. The first version dates from 2000, and the current one, version 3, is a complete rewrite whose last release is 3.09b. It reads the client's SYN and the server's SYN+ACK, matches them against a signature file, and prints a label such as "Linux 3.11 and newer" together with an estimate of how many hops away the sender is. Its signatures write the window as a multiple of the MSS (mss*20, for example), so they keep matching when the link changes. It also watches for NAT and application-level proxies by noticing when the TTL, MSS or timestamps coming from one address stop fitting together, and it can fingerprint HTTP. Its weakness is age: the newest entries in its database are "Linux 3.11 and newer", "Windows 7 or 8" and "MacOS X 10.9 or newer", and newer Windows and macOS releases fall through to its broad generic entries.
JA4T comes from FoxIO, the company behind the JA4+ family, and was published in April 2024. The JA4T format records four raw values instead of a label, joined by underscores: the window size, the option numbers in the order they appear, the MSS, and the window scale. FoxIO's example 64240_2-1-3-1-1-4_1460_8 reads as a 64240-byte window, the Windows option layout, a full Ethernet MSS and a scale of 8. The string is meant to be logged with every session and compared; whoever reads it decides what it means. The TTL is left out. FoxIO also defines JA4TS for the server's SYN+ACK and JA4TScan, an active scanner, and JA4+ plugins exist for Wireshark, Zeek and Arkime.
| Aspect | p0f | JA4T |
|---|---|---|
| Output | An OS label from a signature file | A raw string. The meaning comes from whoever reads it. |
| Window | Often as a multiple of the MSS | The number as sent |
| TTL | Used, plus a hop-distance estimate | Not included |
| MSS | Used to guess the link: Ethernet, DSL, tunnel | Kept as sent and read for tunnel overhead |
| Also covers | NAT and proxy hints, HTTP fingerprinting | Logged beside JA4 (TLS) and JA4H (HTTP) |
| License | LGPL | FoxIO License 1.1: internal and academic use allowed, selling it needs an OEM license |
For a mismatch check the two are equivalent, since both keep the option layout. JA4 fingerprints the TLS handshake and JA4T the TCP SYN beneath it, and their licenses differ: JA4 is BSD 3-Clause like JA3, but JA4T is not.
FAQ
Q: What is a TCP fingerprint?
A: It is the set of values in the first packet of a TCP connection that the operating system chooses by default: initial TTL, window size, MSS, window scale and the order of the TCP options. Different system families fill them in differently, so the packet points to Windows, Apple or Linux without the browser saying anything.
Q: How do I check my TCP fingerprint?
A: Open the Privacy & Trust Index. The TCP/OS Fingerprint card shows which system family your connection points to and whether it matches your browser, and the Connection Fingerprint panel below the cards prints the raw values and your JA4T string.
Q: What is the difference between p0f and JA4T?
A: p0f is a tool that matches the packet against a signature database and prints an OS label. JA4T is a format that writes the window, option order, MSS and window scale into one string such as 64240_2-1-3-1-1-4_1460_8, and whoever logs it decides what it means. p0f's database stops at systems from the early 2010s; JA4T dates from 2024.
Q: Can a website see my operating system without JavaScript?
A: Yes, if its server, or the CDN in front of it, reads the TCP handshake. The packet arrives before any page code runs, so turning off JavaScript changes nothing. Reliably it reveals the family, not the version or the device model.
Q: Does a VPN change my TCP fingerprint?
A: It depends on how the VPN carries your traffic. A tunnel such as WireGuard or OpenVPN forwards your own packets, so the site still sees your system's layout, usually with a smaller MSS. A VPN that hands web traffic to a proxy on its server, a plain proxy, or Tor opens a new connection, and the site sees that server's fingerprint instead.
Q: Why does my TCP fingerprint say Linux when I use Windows?
A: Your traffic most likely passes through a proxy or a VPN server that runs Linux and opens the connection on your behalf. That is normal for proxies and for some VPN services. It reveals that a proxy is in use, not that your browser is lying.
Q: Can a TCP fingerprint be spoofed?
A: Yes, by changing how the system or the proxy builds its SYN. Some proxy providers offer that as a setting, and careful anti-detect setups do it. A browser extension cannot, because the packet is built by the kernel and not by the browser.
Sources
- RFC 9293: Transmission Control Protocol (TCP), IETF, August 2022.
- RFC 7323: TCP Extensions for High Performance, IETF, September 2014.
- p0f v3, Michał Zalewski, project page and documentation.
- JA4T: TCP Fingerprinting, FoxIO, April 2024.
- Investigating Surfshark and NordVPN with JA4T, FoxIO, May 2024.
Which operating system does your first packet reveal?
Run the Privacy & Trust Index check and open the TCP/OS Fingerprint card to see the family your connection points to and whether it agrees with your browser. Your JA4T string is in the Connection Fingerprint panel below the cards.
