The TCP header is the twenty bytes in front of every segment, carrying ports, sequence and acknowledgment numbers, flags, a window size and a checksum. Options extend it to sixty bytes, and that is where window scaling and selective acknowledgment live.
- 20 bytes minimum, 60 with options, and the offset field says which
- Sequence numbers count bytes, not packets
- Data offset is in 32-bit words, so 5 means 20 bytes
- A zero window is an application not reading, not a network fault
- Window scaling is negotiated in the SYN, and invisible without it
On this page
The fieldsThe TCP header fields, in the order they appear
| Field | Size | What it is for |
|---|---|---|
| Source port | 16 bits | Which process sent this, usually an ephemeral port number |
| Destination port | 16 bits | Which service the data is for, such as port 443 |
| Sequence number | 32 bits | Where the first byte of this segment sits in the data stream |
| Acknowledgment number | 32 bits | The next byte this side expects to receive |
| Data offset | 4 bits | TCP header length in 32-bit words, 5 to 15 |
| Reserved | 4 bits | Unused, and expected to be zero |
| Flags | 8 bits | CWR, ECE, URG, ACK, PSH, RST, SYN, FIN |
| Window | 16 bits | Flow control: how much more data this side can accept |
| Checksum | 16 bits | Error detection over the header, data and pseudo-header |
| Urgent pointer | 16 bits | Only meaningful when URG is set, which is almost never |
| Options | 0 to 40 bytes | MSS, window scale, SACK, timestamps |
Two of those TCP header fields cause more confusion than the rest combined, and both are about units.
Data offset is in 32-bit words, not bytes. A value of 5 means a twenty byte TCP header, and 15 means sixty. Reading the field as a byte count is the classic mistake when parsing a packet by hand.
Sequence numbers count bytes, not packets. A segment carrying 1,460 bytes of data advances the sequence number by 1,460, not by one. This is why acknowledgment numbers appear to jump in odd amounts, and it is the reason TCP can acknowledge part of what it received.
The flagsThe TCP flags, and which ones actually matter
Eight flag bits are defined in the TCP header and four of them carry almost all the meaning in practice.
SYN opens a TCP connection and synchronizes the starting sequence numbers. It appears exactly twice in a healthy connection, once in each direction.
ACK says the acknowledgment number field is meaningful. It is set on every segment after the first, so seeing it is unremarkable and its absence on anything but the opening SYN is not.
FIN closes one direction politely. Each side sends its own, so an orderly shutdown has two, and a connection with one FIN is half closed and still legal.
RST aborts immediately. It is the single most informative flag in any capture, because it means a refusal rather than a failure: nothing is listening on that port number, a firewall rejected the packet, or one side gave up on a connection it no longer recognizes.
The remaining four flags are specialized. PSH asks the receiver to hand the data to the application without waiting, URG and the urgent pointer are effectively obsolete, and ECE and CWR belong to explicit congestion notification, a congestion control mechanism negotiated at connection setup and rarely visible unless you look for it.
The windowThe window, and the fault it exposes
The window field says how much more data the sender of this segment can accept before its buffer is full. It changes constantly, and this flow control is the mechanism by which a slow receiver stops a fast sender from overwhelming it.
Sixteen bits caps the raw value at 65,535 bytes, which was generous when the protocol was written in 1981 and is nothing on a modern link. The window scale option fixes it by declaring a shift factor at connection setup, so the real window is the field multiplied by a power of two.
This has one significant practical consequence: window scaling is negotiated only in the SYN segments, so an analyzer that did not capture the start of the connection cannot know the multiplier and will report window sizes that are wrong by a large factor.
A zero window is worth recognizing on sight. It means the receiver buffer is full and the sender must stop sending data, and it is nearly always an application that is not reading its socket fast enough rather than a network problem.
Blaming the network for a zero window is one of the more common wrong turns in performance work, and the header says plainly where to look instead.
The optionsThe options, where the modern behavior lives
Options appear only in the space between the fixed header and the data, and most of them are negotiated in the SYN.
Maximum segment size declares the largest amount of data this side will accept in one segment, derived from the local MTU. The two ends settle on the smaller of the two values, and a mismatch between that and the real path MTU is the cause of TCP connections that open and then hang on large transfers.
Window scale provides the multiplier described above, without which throughput on a long fast path is capped far below the link speed.
Selective acknowledgment lets a receiver say which non-contiguous blocks of data arrived, so a sender retransmits only the gap rather than everything after it. Without it, one lost packet costs far more than one segment of retransmission.
Timestamps give a round trip measurement on every segment and protect against sequence numbers wrapping on very fast TCP connections.
All four options are ordinary today, and all four are absent if the SYN was blocked, rewritten by a middlebox or stripped by an old firewall. TCP running without window scaling and selective acknowledgment works and performs badly, which is exactly the kind of fault that survives for years.
In the packetWhere the header sits, and what the checksum covers
The TCP header does not travel alone. It sits directly behind an IP header in every packet, and the protocol field of that IP header carries the value 6, which is how the receiving stack knows to hand the rest of the packet to the Transmission Control Protocol rather than to UDP.
That arrangement is why there are no addresses in the TCP header. The port numbers identify the process at each end, and the internet layer underneath supplies the source address and the destination address. A segment on its own cannot say which host it came from.
The checksum is the one field that reaches across that boundary. RFC 793 says the checksum also covers a 96 bit pseudo header conceptually prefixed to the TCP header, and that this pseudo header contains the source address, the destination address, the protocol and the TCP length.
Those twelve octets are never transmitted on the network. Each end builds them from the IP header it already holds, which is why a segment delivered to the wrong host or handed to the wrong protocol fails the checksum even when every byte of the TCP header and the data arrived intact.
The specification itself has moved on, and it is worth citing the current one. RFC 9293, published as Internet Standard STD 7, obsoletes RFC 793 together with the six later RFCs that had each patched part of it. The header format did not change.
In a captureWhat to read first in a capture
Four TCP header fields, read in this order, resolve most investigations.
Look for RST. A reset says the connection was refused or abandoned, and which side sent it tells you which end made that decision.
Check the SYN and the SYN-ACK. TCP options are negotiated there, so a missing MSS, window scale or SACK is visible only at the start. This is why capturing from the beginning of a connection matters so much.
Watch the window. A window falling toward zero is a receiver that cannot keep up, and it points at the application rather than the link.
Follow the sequence numbers. Repeated numbers are retransmissions, and three duplicate acknowledgments of the same number are the receiver saying a packet is missing, which triggers a fast retransmit before any timer expires.
PitfallsWhere people go wrong
Reading data offset as bytes. The field counts 32-bit words. Five means a twenty byte TCP header, and every hand-written parser gets this wrong once.
Assuming sequence numbers count packets. They count bytes, which is what makes partial acknowledgment possible and what makes the arithmetic look strange at first.
Trusting window sizes in a capture that missed the SYN. Without the scale factor the numbers are wrong, and they are wrong in the direction that hides a problem.
Treating a zero window as congestion. It is flow control, deliberately signaled by the receiver, and the cause is an application that is not reading the data fast enough.
Ignoring the difference between a RST and a timeout. A reset is an answer and a timeout is silence. One means something refused you and the other means nothing replied, and they point at completely different causes.
Expecting PSH to mean anything urgent. It asks the stack not to buffer. It has no priority meaning on the network at all.
ComparisonTwo headers, and the trade expressed in bytes
| Criterion | TCP header | UDP header |
|---|---|---|
| Size | 20 to 60 bytes | 8 bytes, always |
| Ports | Yes | Yes |
| Sequence numbers | Yes, per byte | No |
| Acknowledgments | Yes | No |
| Flow control | Yes, the window field | No |
| Options | Yes, up to 40 bytes | No |
| Checksum | Yes, mandatory | Yes, optional on IPv4 |
| Overhead per segment | 20 bytes and up | 8 bytes |
The size row is the trade in one line. Everything TCP adds to the header is a feature that UDP leaves to the application, which is the whole of the TCP against UDP argument expressed in bytes.
FAQFrequently asked questions
What is the TCP header?
The twenty to sixty bytes in front of every segment the Transmission Control Protocol sends, carrying port numbers, sequence and acknowledgment numbers, flags, the window size, a checksum and any options.
How big is the TCP header?
Twenty bytes without options and up to sixty with them. The data offset field in the header says which, measured in 32-bit words.
What is the data offset field?
The TCP header length in 32-bit words. A value of 5 means a twenty byte header with no options, and 15 means the maximum of sixty.
What do the TCP flags do?
SYN opens a connection, ACK acknowledges data, FIN closes one direction, and RST aborts. PSH, URG, ECE and CWR are specialized and rarely the point of an investigation.
What is the sequence number for?
It gives the position of this segment's first byte within the stream, which is how the receiver reassembles data in order and detects what is missing.
Do sequence numbers count packets or bytes?
Bytes. A segment with 1,460 bytes of payload advances the number by 1,460, which is why acknowledgment numbers move in unfamiliar increments.
What is the window size field?
How many more bytes the sender of the segment can accept right now. It is flow control, and it changes on almost every segment.
What is a zero window?
The receiver's buffer is full and the sender must pause. It almost always means an application is not reading its socket fast enough, not that the network is at fault.
What is window scaling?
An option negotiated in the SYN that multiplies the sixteen bit window field, because 65,535 bytes is far too small for a modern fast path.
Why are my window sizes wrong in Wireshark?
Because the capture missed the SYN, so the scale factor was never seen. Capture from the start of the connection and the numbers become correct.
What are TCP options used for?
Maximum segment size, window scaling, selective acknowledgment and timestamps. All are negotiated at connection setup and all are absent if the SYN was interfered with.
What does a RST flag mean?
An immediate abort. Nothing is listening, a firewall rejected the segment, or one side no longer recognizes the connection. It is a refusal, which is more informative than a timeout.
What is the urgent pointer?
A legacy mechanism for marking data as urgent, meaningful only when URG is set. It is effectively unused today and safe to ignore in nearly every capture.
How does the TCP checksum work?
It covers the header, the data and a pseudo-header taken from the IP header, which is why it detects a segment that arrived on the wrong connection as well as one that was corrupted.
What is the TCP header format?
The TCP header format is 20 bytes without options: source port, destination port, sequence number, acknowledgment number, data offset, flags, window size, checksum and urgent pointer. Options such as maximum segment size, window scaling and selective acknowledgment can extend it to 60 bytes.
Keep readingRelated concepts
Read next · Protocols TCP vs UDP Everything in this header is a feature UDP leaves to the application, which is the comparison in one drawing. Open this next10 min- Diagnostics · 12 min Reading a Wireshark Capture Without Drowning in Packets These fields are what you are looking at, and this is how to get to them without drowning.
- Fundamentals · 10 min The IPv4 Header, Field by Field and in Order of Usefulness The header underneath this one, and the source of the pseudo-header the TCP checksum covers.
- Network fundamentals · 9 min TCP Window Size, and Why It Caps Your Throughput Where the 16-bit window value lives in every TCP segment.