PROTOCOLS-FUN . PACKET ANATOMY

TCP Anatomy

RFC 9293 (STD 7)
rev 2026.08
header 20 bytes fixed
with options up to 60 bytes
checksum pseudo-header

TCP's 20-byte fixed header is the same shape it was in RFC 793 (1981). What's changed since is everything built on top of it: the flags byte gained two bits for congestion control in 2001, and the Options field picked up window scaling, selective ACKs, and timestamps - none of which required touching the fixed header at all. RFC 9293 (2022) is a full rewrite of the spec, but explicitly changes no wire format - it exists to consolidate 40+ years of clarifications and errata into one document. Every example on this page is 192.0.2.10:51234 (client) opening a connection to 203.0.113.5:443 (server) - RFC 5737 documentation addresses. Hover a field to light its bytes, click a field marked + for its lookup table.

header20-60 bytesspecRFC 9293 (STD 7)

Every TCP segment opens with a 16-bit source port and a 16-bit destination port - that's the entire addressing TCP adds on top of whatever carries it (IPv4 or IPv6). Everything else in the header exists to make a reliable, ordered byte stream out of an unreliable, unordered network.

source & destination ports (4 bytes)

Client ephemeral port 51234 connecting to server port 443 (HTTPS).

the header hasn't moved in 44 years. RFC 9293 (2022) obsoletes RFC 793, 879, 2873, 6093, 6429, 6528, and 6691, and updates RFC 1011, 1122, and 5961 - but it's a specification consolidation, not a wire-format change. The 20-byte layout on the Fixed Header tab is byte-for-byte what RFC 793 defined in 1981.
size20 bytes, no optionsspecRFC 9293 ยง3.1

A SYN segment opening a connection - the simplest real TCP header, no options. The Flags tabs zoom into byte 13 across two eras; the Options tab shows what a real modern SYN adds on top of this.

fixed header, a bare SYN (20 bytes)

Sequence number is the client's Initial Sequence Number (ISN) - historically meant to be hard to predict, since a guessable ISN is what off-path TCP hijacking attacks target.

byte13specRFC 793 (1981)bits used6 of 8

In the original spec, the two high bits of this byte were just unused Reserved bits - part of a 6-bit reserved field that spanned the end of byte 12 and the start of byte 13. Only 6 control bits existed at all.

flags byte, 1981 (8 bits, 2 reserved)

Example: ACK+SYN set (0x12) - a SYN-ACK, the second segment of the three-way handshake.

byte13 (same byte)specRFC 3168 (2001)bits used8 of 8

Explicit Congestion Notification claimed the two previously-reserved bits for CWR and ECE, letting a router mark congestion instead of dropping a packet - if both endpoints negotiated ECN support during the handshake. Same byte, same bit positions, new meaning.

flags byte, 2001+ (8 bits, all assigned)

Example: ECE+ACK set (0x50) - the sender is being told a router marked Congestion Experienced on the return path.

a ninth flag that didn't stick. RFC 3540 (2003) proposed an experimental NS ("nonce sum") bit, carved from what remained of the reserved field, to help detect receivers that lie about ECN to get better throughput. It's now Historic status - never widely deployed, and this page doesn't draw it since sources disagree on its exact final bit position, which is itself a small lesson in how quickly an experimental RFC's details become hard to pin down once nobody implements it.
size20 bytes here, up to 40 totalalignment4-byte boundary

Everything TCP has gained since 1981 lives here: Maximum Segment Size, Window Scale, SACK Permitted, and Timestamps - the four options a real modern SYN actually carries. Data Offset (in the Fixed Header tab) would read 10 (40 bytes total) with these attached.

a realistic modern SYN's options (20 bytes)

MSS 1460 (Ethernet MTU minus IP+TCP headers), Window Scale shift 7 (RFC 7323, obsoletes RFC 1323), SACK Permitted (RFC 2018), and a Timestamps option padded to the 4-byte boundary with a NOP.