Header Diagrams
- Headers are drawn 32 bits wide: each row is 4 bytes, so the row number times 4 is the byte offset, and a field's box is as wide as its bit count.
- The minimums to say out loud: Ethernet 14 bytes (+4 FCS), IPv4 20, IPv6 40, TCP 20, UDP 8, ICMP 8, DNS 12, TLS record 5, HTTP/2 frame 9.
- Header length fields count in 32-bit words (IPv4 IHL, TCP data offset), so
5means 20 bytes and15means 60. The IPv4 fragment offset counts in 8-byte units. - Everything is big-endian (network byte order), with bit 0 the most significant bit of the first byte.
- This page owns the pictures. What each field means is explained once, on the owner page linked under each diagram.
How it works
How to read a header diagram
Protocol specifications draw every header the same way, and this page follows that style. The ruler on top numbers the bits 0 to 31. Each row is one 32-bit word, which is 4 bytes, so the left-hand label gives the byte offsets of that row. A field is a box whose width is proportional to its size: 1 bit is 20 px wide, so a 16-bit field is 320 px and a full row is 640 px on every figure on this page. Dashed outlines mark variable-length or optional parts.
Two conventions to keep straight:
- Network byte order. A multi-byte field is sent most significant byte first. The 16-bit total length
0x003cgoes on the wire as00 3c. Specifications number bits from the left, so bit 0 of a row is the most significant bit of its first byte, the opposite of the usual CPU convention where bit 0 is the least significant. - Header length is in words. IPv4 IHL and TCP data offset count 32-bit words because the header is built from rows. Multiply by 4 for bytes.
Everything below links to the page that explains the fields. Use this page when you need the layout and the offsets.
Layer 2: Ethernet II, 802.1Q, ARP
An Ethernet II frame is a 14-byte header, the payload, and a 4-byte frame check sequence. The preamble and start frame delimiter come before byte 0 and are not counted in the frame size. Fields, address structure and size arithmetic are on Ethernet frames and MAC addresses; switching behavior is on Switches and MAC learning.
The sizes add up as follows: 6 + 6 + 2 = 14 header bytes, and 14 + 46 + 4 = 64 bytes is the smallest frame, 14 + 1500 + 4 = 1518 the largest. Add the 8-byte preamble and SFD and the 12-byte inter-frame gap and one maximum frame occupies 1518 + 8 + 12 = 1538 byte times on the wire, the figure used on the latency and capacity numbers page. An EtherType of 0x0800 means IPv4, 0x0806 ARP, 0x86DD IPv6, and 0x8100 an 802.1Q tag; values of 1500 or less are an old 802.3 length field instead.
The 802.1Q tag is inserted between the source MAC and the EtherType. The VLAN tag semantics are on VLANs.
The TCI is 3 + 1 + 12 = 16 bits. VID 0 and 4095 are reserved, so 4094 VLANs are usable.
ARP maps an IPv4 address to a MAC address on the local link. For IPv4 over Ethernet the packet is 28 bytes. How resolution works is on ARP.
The ARP packet rides in a frame with EtherType 0x0806. Because 14 + 28 = 42 is below the 60 bytes before the FCS, the sender pads the payload with 18 bytes of zeros to reach the 46-byte minimum.
Layer 3: IPv4 and IPv6
IPv4 has a 20-byte fixed header followed by up to 40 bytes of options; the fields are explained on The IP packet, and the fragment fields on MTU, MSS and fragmentation.
IPv6 trades the variable parts for a fixed 40-byte header. The fields are explained on IPv6.
The rows give 8 + 16 + 16 = 40 bytes, of which 32 bytes are the two addresses. Anything optional moves into extension headers chained by the next-header field.
ICMP
ICMP rides directly in an IP packet (IPv4 protocol 1). The mechanics of ping are on ICMP and ping.
The type and code pairs that come up in practice (RFC 792, with the fragmentation-needed MTU field from RFC 1191 and code 13 from RFC 1812):
| Type | Code | Name | When you see it |
|---|---|---|---|
| 8 | 0 | Echo request | ping sends this |
| 0 | 0 | Echo reply | ping's answer, copies identifier, sequence and data back |
| 3 | 0 | Network unreachable | a router has no route to the destination network |
| 3 | 1 | Host unreachable | the last-hop router could not resolve the host (ARP failed) |
| 3 | 3 | Port unreachable | no UDP socket on that port; traceroute's final reply |
| 3 | 4 | Fragmentation needed and DF set | the packet exceeds the next link's MTU and DF forbids fragmenting; carries the next-hop MTU, the basis of path MTU discovery |
| 3 | 13 | Communication administratively prohibited | a firewall rejected the packet with a reply instead of dropping it silently |
| 11 | 0 | TTL exceeded in transit | a router decremented TTL to 0; how traceroute finds each hop |
| 11 | 1 | Fragment reassembly time exceeded | the destination gave up waiting for the rest of a fragmented packet |
ICMPv6 (RFC 4443) keeps the same type, code, checksum layout with different numbers: errors are types below 128 (1 destination unreachable, 2 packet too big, 3 time exceeded, 4 parameter problem) and informational messages are 128 and up (128 echo request, 129 echo reply). Neighbor Discovery messages are types 133 to 137 (RFC 4861). Unlike ICMPv4, the ICMPv6 checksum also covers a pseudo-header of the IPv6 addresses.
Layer 4: TCP and UDP
TCP's fields, flags and options are explained on The TCP segment header.
Row 3 adds up as 4 + 3 + 9 + 16 = 32 bits. RFC 9293 draws the NS bit as part of a 4-bit reserved field because the ECN nonce (RFC 3540) was later reclassified as historic; this course follows the nine-bit layout used on the TCP page.
UDP is the smallest of the set. See UDP for the semantics.
Application and security layer: DNS, TLS, HTTP/2, QUIC
The DNS message begins with a 12-byte header; the record types and resolution are on DNS.
The flag widths add up: 1 + 4 + 1 + 1 + 1 + 1 + 3 + 4 = 16. The 3 Z bits were reserved in RFC 1035; later DNSSEC work (RFC 4035) took two of them for the AD and CD flags.
A TLS 1.3 connection sends everything as records with a 5-byte header (RFC 8446 section 5.1). The handshake and key schedule are on TLS.
HTTP/2 puts a 9-byte header in front of every frame (RFC 9113 section 4.1). Streams and multiplexing are on HTTP/1.1 and HTTP/2.
The widths are 24 + 8 + 8 + 1 + 31 = 72 bits = 9 bytes. The frame types are DATA 0x0, HEADERS 0x1, PRIORITY 0x2, RST_STREAM 0x3, SETTINGS 0x4, PUSH_PROMISE 0x5, PING 0x6, GOAWAY 0x7, WINDOW_UPDATE 0x8 and CONTINUATION 0x9.
QUIC has two header forms (RFC 9000 section 17): a long header for the handshake packets and a short header for everything after. Connection IDs, migration and the handshake are on QUIC and HTTP/3.
Long packet types in the 2-bit field: 0 Initial, 1 0-RTT, 2 Handshake, 3 Retry. In a v1 long header the first byte plus the version, the two length bytes and two connection IDs of up to 20 bytes each make the header at least 7 bytes plus the connection IDs; the short header is the first byte, the destination connection ID and a 1 to 4 byte packet number.
Worked example: parse a TCP SYN from the hex dump
Below is the 60-byte IPv4 packet for a client's TCP SYN to port 443. It was constructed by hand from the RFC layouts, not captured, and both checksums were computed and verified: the IP header checksum b1e6 and the TCP checksum efbc over the pseudo-header, header and options. The addresses are from the private 172.16.0.0/12 range.
The first 20 bytes are the IPv4 header. Row numbers match the IPv4 figure above.
| Bytes | Hex | Field | Value |
|---|---|---|---|
| 0 | 45 | Version, IHL | version 4, IHL 5 = 5 x 4 = 20-byte header |
| 1 | 00 | DSCP, ECN | 0, 0 |
| 2-3 | 00 3c | Total length | 0x003c = 60 bytes: 20 IP + 40 TCP, no data |
| 4-5 | 1c 46 | Identification | 0x1c46 = 7238 |
| 6-7 | 40 00 | Flags, fragment offset | 0x4000 = 010 then 13 zeros: DF set, MF clear, offset 0 |
| 8 | 40 | TTL | 0x40 = 64 |
| 9 | 06 | Protocol | 6 = TCP |
| 10-11 | b1 e6 | Header checksum | ones-complement sum of the ten 16-bit words is 0x24e17, folded to 0x4e19, inverted to 0xb1e6 |
| 12-15 | ac 10 0a 63 | Source address | 172.16.10.99 |
| 16-19 | ac 10 0a 0c | Destination address | 172.16.10.12 |
The next 40 bytes, starting at offset 20, are the TCP header. Row numbers match the TCP figure.
| Bytes | Hex | Field | Value |
|---|---|---|---|
| 20-21 | d4 31 | Source port | 0xd431 = 54321, an ephemeral port |
| 22-23 | 01 bb | Destination port | 0x01bb = 443 |
| 24-27 | 6d 5a 91 c4 | Sequence number | 0x6d5a91c4 = 1,834,652,100, the initial sequence number |
| 28-31 | 00 00 00 00 | Acknowledgment number | 0, meaningless because ACK is clear |
| 32-33 | a0 02 | Data offset, flags | 0xa = 10 words = 40-byte header; low byte 0x02 = SYN only |
| 34-35 | fa f0 | Window | 0xfaf0 = 64,240 |
| 36-37 | ef bc | Checksum | over pseudo-header, header and options; verifies to 0 |
| 38-39 | 00 00 | Urgent pointer | 0, meaningless because URG is clear |
| 40-43 | 02 04 05 b4 | Option: MSS | kind 2, length 4, 0x05b4 = 1460 |
| 44-45 | 04 02 | Option: SACK permitted | kind 4, length 2 |
| 46-55 | 08 0a 00 b7 1b 00 00 00 00 00 | Option: timestamps | kind 8, length 10, TSval 0x00b71b00 = 12,000,000, TSecr 0 |
| 56 | 01 | Option: NOP | one byte of padding so the next option aligns |
| 57-59 | 03 03 07 | Option: window scale | kind 3, length 3, shift 7, so the window means 64,240 x 128 |
Check the arithmetic: the options are 4 + 2 + 10 + 1 + 3 = 20 bytes, the TCP header is 20 + 20 = 40 bytes, the packet is 20 + 40 = 60 = 0x3c bytes. The flag byte is 0x02, so bit by bit the nine flags NS to FIN read 0 0 0 0 0 0 0 1 0, and only SYN (the second from the right) is set.
Try it on real bytes: hover a field or a byte to see where it sits, edit a byte to watch the header checksum stop verifying, or paste your own hex.
Multi-byte fields are big-endian. IHL and TCP data offset count 32-bit words; the IPv4 fragment offset counts 8-byte units. The checksum is the ones-complement of the ones-complement 16-bit sum, so a header with a correct checksum sums to 0xffff.
Gotchas
Interview questions
Show answer
Both are 20 bytes. IPv4 is five 32-bit rows, so IHL is 5, and TCP is also five rows, so the data offset is 5. A TCP segment with no data therefore costs 40 bytes of IP and TCP overhead, and with Ethernet's 14-byte header and 4-byte FCS the smallest TCP-over-IPv4 frame carries 58 bytes of headers.
Follow-ups:
- What is the largest? 60 bytes each. IHL and data offset are 4-bit fields, so the maximum is 15 words x 4 = 60, leaving 40 bytes for options.
- How many bytes is a UDP header? 8, four 16-bit fields.
Show answer
IHL is the Internet Header Length in 32-bit words. 5 means 5 x 4 = 20 bytes, a header with no options. The payload begins at byte IHL x 4. A receiver must use IHL, not a hard-coded 20, because options push the payload later, up to IHL 15 which is 60 bytes.
Follow-ups:
- What if IHL is less than 5? The packet is malformed and is dropped, because the fixed fields alone need 20 bytes.
- Does the same trick exist elsewhere? Yes, TCP's data offset works the same way, and the HTTP/2 frame uses an explicit 24-bit length instead.
Show answer
The 13-bit fragment offset says where this fragment's data starts in the original payload, in units of 8 bytes. Counting in 8-byte units lets 13 bits cover 65,528 bytes, and it forces every fragment except the last to carry a multiple of 8 bytes. On a 1500-byte link a fragment carries 1500 - 20 = 1480 payload bytes, and 1480 / 8 = 185, so the second fragment has offset 185. MF is set on all fragments but the last, and the identification ties them together.
Follow-ups:
- How do you recognise an unfragmented packet? MF is clear and the offset is 0.
- Who reassembles? Only the destination host.
Show answer
The link layer (Ethernet FCS) and the transport layer (TCP, UDP checksums, which cover the addresses through a pseudo-header) already catch corruption, and recomputing an IP checksum at every hop after changing the hop limit was wasted work. Fragmentation moved to the source (an optional Fragment extension header) so routers only forward and never reassemble or split. A router that cannot forward a packet drops it and returns ICMPv6 Packet Too Big, and path MTU discovery tells the sender the limit. Every link must carry at least 1280 bytes.
Follow-ups:
- What does that make mandatory? The UDP checksum, and permitting ICMPv6 Packet Too Big through firewalls.
- Where did the identification and offset fields go? Into the 8-byte Fragment extension header.
Show answer
They are independent fields that probes combine. A sender sets DF so routers will not fragment. A router whose next link is too small drops the packet and returns ICMP type 3 code 4 (fragmentation needed) carrying the next-hop MTU, and the sender lowers its packet size. That is path MTU discovery. TTL (IPv6: hop limit) is separate: it is decremented per hop and a router that reaches 0 returns type 11, which is what traceroute uses. If a firewall blocks the ICMP, large packets silently vanish, a black hole.
Follow-ups:
- How does IPv6 differ? DF does not exist because routers never fragment, so Packet Too Big (type 2) is the only signal.
- What is the usual fix for a black hole? Clamp the TCP MSS or enable packetization-layer discovery.
Show answer
RFC 768 says a transmitted checksum of 0 means the sender did not compute one, because IPv4 already has a header checksum and the application may accept the risk. IPv6 has no header checksum, so the UDP checksum is the only thing that protects the addresses and the data, and RFC 8200 section 8.1 makes it mandatory. If a computed UDP checksum comes out as 0 it is sent as 0xFFFF.
Follow-ups:
- Are there exceptions in IPv6? Tunnel protocols may relax it under RFC 6935 and RFC 6936.
- What does the checksum cover? A pseudo-header with source and destination address, the protocol, and the UDP length, plus the UDP header and data.
Fun facts
- RFC 3514 (an April Fools RFC, 1 April 2003) proposed that the reserved bit in the IPv4 flags field be the "evil bit", set by senders of malicious packets.
- Every Ethernet frame starts with seven bytes of 0xAA (10101010) followed by the start frame delimiter 0xAB, a fixed pattern that lets the receiver's clock lock on.
- The IPv6 header is twice the size of IPv4's 20 bytes, but 32 of its 40 bytes are the two addresses, so only 8 bytes carry control fields.
- A TLS 1.3 record still carries the legacy version
0x0303, which is the TLS 1.2 number, to survive middleboxes that reject unknown versions. - An ARP packet is 28 bytes but has to ride in a 46-byte minimum Ethernet payload, so every ARP frame is padded with 18 bytes of zeros.
Cheat sheet
| Header | Size | Key fields | Explained on |
|---|---|---|---|
| Ethernet II | 14 B header + 4 B FCS (+ 8 B preamble) | dst MAC, src MAC, EtherType | Ethernet frames and MAC addresses |
| 802.1Q tag | 4 B | TPID 0x8100, PCP 3 bits, DEI 1, VID 12 | VLANs |
| ARP (IPv4) | 28 B | operation, sender and target MAC and IP | ARP |
| IPv4 | 20 to 60 B | IHL, total length, ID, DF/MF, offset, TTL, protocol, checksum, addresses | The IP packet |
| IPv6 | 40 B fixed | traffic class, flow label, payload length, next header, hop limit, addresses | IPv6 |
| TCP | 20 to 60 B | ports, seq, ack, data offset, 9 flags, window, checksum, urgent | The TCP segment header |
| UDP | 8 B | ports, length, checksum | UDP |
| ICMP | 8 B + data | type, code, checksum, rest of header | ICMP and ping |
| DNS | 12 B | ID, flags, four counts | DNS |
| TLS record | 5 B | content type, legacy version, length | TLS |
| HTTP/2 frame | 9 B | length, type, flags, stream id | HTTP/1.1 and HTTP/2 |
| QUIC long / short | 7 B + connection IDs / 1 B + DCID + packet number | form, version, connection IDs | QUIC and HTTP/3 |
| DHCP | 236 B fixed + 4 B cookie + options | op, xid, ciaddr, yiaddr, chaddr | DHCP |
| BGP message | 19 B header | marker, length, type | BGP |
What selects the next header:
| Field | Value | Means |
|---|---|---|
| Ethernet EtherType | 0x0800 / 0x0806 / 0x86DD / 0x8100 | IPv4 / ARP / IPv6 / 802.1Q tag |
| IP protocol or next header | 1 / 6 / 17 / 47 / 50 / 58 | ICMP / TCP / UDP / GRE / ESP / ICMPv6 |
| UDP destination port | 4789 | VXLAN |
BGP message types (RFC 4271 section 4): every message starts with a 16-byte marker, a 2-byte length (19 to 4096) and a 1-byte type, 19 bytes in total.
| Type | Message | Purpose |
|---|---|---|
| 1 | OPEN | starts a session: version, AS number, hold time, router ID |
| 2 | UPDATE | announces or withdraws routes |
| 3 | NOTIFICATION | reports an error and closes the session |
| 4 | KEEPALIVE | header only, 19 bytes; proves the peer is alive |
Encapsulation overhead: bytes added to the packet or frame being carried. Each figure is derived from the headers it adds.
| Encapsulation | Added bytes | How it adds up |
|---|---|---|
| 802.1Q VLAN tag | 4 | TPID 2 + TCI 2 |
| PPPoE (RFC 2516) | 8 | PPPoE header 6 + PPP protocol field 2, so the usable MTU is 1500 - 8 = 1492 |
| GRE over IPv4 (RFC 2784) | 24 | outer IPv4 20 + GRE base header 4; the optional key, sequence and checksum fields add 4 each |
| VXLAN over IPv4 (RFC 7348) | 50 | outer Ethernet 14 + IPv4 20 + UDP 8 + VXLAN 8; the inner Ethernet frame is carried whole, so the inner MTU is 1450 |
| IPsec ESP tunnel mode, IPv4 (RFC 4303) | 54 to 73 | outer IP 20 + ESP header 8 + IV (8 for AES-GCM, 16 for AES-CBC) + padding + trailer 2 + ICV (16 for GCM, 12 for HMAC-SHA1-96): GCM is 54 plus 0 to 3 padding, CBC with SHA1-96 is 58 plus 0 to 15 padding; NAT traversal adds an 8-byte UDP header |
The 1450 and 1492 figures also appear on the MTU, MSS and fragmentation page, and IPsec is covered on VPN, IPsec and WireGuard.