Binary Data in Network Protocols

May 28, 20265 min read

Why Protocols Use Binary

Text-based formats like JSON and XML are easy for humans to read. But network protocols favor binary encoding for three reasons: compactness, parsing speed, and determinism.

A binary protocol assigns fixed byte positions and bit widths to every field. The parser reads bytes at known offsets — no string splitting, no quote escaping, no ambiguity. This makes binary protocols faster to parse and smaller on the wire.

Consider a simple message carrying a temperature reading:

FormatRepresentationBytes
JSON{"temp":23.5}14
Binary (float32 + 1 byte ID)\x01\x41\xbc\x00\x005

The binary version is 64% smaller. At scale — thousands of messages per second — this difference compounds into meaningful bandwidth savings.

Binary in TCP/IP Headers

The TCP header is a classic binary protocol. Each field occupies a fixed bit range:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data |           |U|A|P|R|S|F|                               |
| Offset| Reserved  |R|C|S|S|Y|I|            Window             |
|       |           |G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Every field has a precise byte position and bit width. The parser knows exactly where to find the source port (bytes 0-1), the sequence number (bytes 4-7), and the flags (bits in byte 13).

Bit-Level Operations

Reading binary protocol fields requires bitwise operations:

// Read source port from TCP header (bytes 0-1, big-endian)
const sourcePort = (header[0] << 8) | header[1];

// Read the SYN flag (bit 1 of byte 13)
const synFlag = (header[13] & 0x02) !== 0;

// Read data offset (upper 4 bits of byte 12)
const dataOffset = (header[12] >> 4) * 4; // in bytes

These operations translate directly to how the protocol specification defines each field.

Binary in WebSocket Frames

WebSocket uses a binary framing protocol on top of TCP. Each frame has a header that encodes metadata in specific bits:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Key details:

  • The FIN bit (bit 0) indicates the last frame in a message
  • The opcode (bits 4-7) distinguishes text frames (0x1) from binary frames (0x2)
  • The MASK bit indicates whether the payload is XOR-masked (required for client-to-server frames)
  • The payload length uses 7 bits for lengths 0-125, with 126 and 127 as escape codes for 16-bit and 64-bit lengths

This compact header adds only 2-14 bytes per frame — far less than an HTTP-style text header.

Endianness in Network Protocols

Binary protocols must specify byte order (endianness). Network protocols use big-endian (also called network byte order) by convention.

// Big-endian: most significant byte first
// Value 0x1234 stored as [0x12, 0x34]

// Little-endian (common on x86 CPUs): least significant byte first
// Value 0x1234 stored as [0x34, 0x12]

JavaScript's DataView lets you specify endianness explicitly:

const view = new DataView(buffer);
const port = view.getUint16(0, false); // offset 0, big-endian
const length = view.getUint32(2, false); // offset 2, big-endian

Always pass false (big-endian) when reading network protocol data.

Binary in DNS Messages

DNS queries and responses use a binary format where even domain names are compressed. Instead of repeating example.com in every record, DNS uses pointer compression — an offset that points back to a previously encoded name.

Normal:     \x07example\x03com\x00           (13 bytes)
Compressed: \xc0\x0c                          (2 bytes — pointer to offset 12)

This compression can reduce DNS message sizes by 50% or more in responses with many records sharing the same domain suffix.

Practical Binary Tools

TaskToolUse Case
Inspect raw bytesxxd, hexdumpDebug binary protocol data
Parse in JavaScriptDataView, ArrayBufferRead/write binary in browsers
Parse in Pythonstruct moduleUnpack binary structs
Capture trafficWiresharkAnalyze live protocol data

Key Takeaways

  • Binary protocols are more compact and faster to parse than text-based alternatives
  • Fields occupy fixed bit positions — parsers read bytes at known offsets using bitwise operations
  • TCP, WebSocket, and DNS all use binary framing for efficiency
  • Network byte order is big-endian; always specify endianness when reading binary data
  • Understanding binary encoding helps you debug protocol issues and write efficient parsers

Try It Yourself

Convert text to binary and back to see how characters map to bytes using our Text to Binary tool. Paste any text, inspect the binary representation, and understand byte-level encoding firsthand.