Skip to content

WebSocket Frames: Text, Binary, Close, Ping, Pong

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Websocket Frames: Text, Binary, Close, Ping, Pong. We cover key concepts, practical examples, and best practices to help you master this topic.

WebSocket communication uses a frame-based protocol. Each frame has an opcode indicating its type: text (0x1), binary (0x2), close (0x8), ping (0x9), or pong (0xA). Control frames (close, ping, pong) can interleave with data frames.

What You'll Learn

  • Frame structure: opcode, mask, payload length, masking key
  • Text vs Binary frames
  • Close frame status codes and reasons
  • Ping and Pong for keepalive
  • Frame fragmentation (continuation frames)

Why It Matters

Understanding frames helps debug low-level issues, implement custom WebSocket servers, and optimize message handling. Frame manipulation is essential for proxy and gateway implementations.

Real-World Use

Discord uses binary frames for voice data and text frames for chat. Trading platforms use binary frames for price data. Ping-pong is standard for connection keepalive in all production WebSocket implementations.

flowchart LR
    Frame[WebSocket Frame] --> Opcode[Opcode: 4 bits]
    Frame --> Mask[Mask: 1 bit]
    Frame --> Length[Payload Length: 7/7+16/7+64 bits]
    Frame --> Masking[Masking Key: 0 or 4 bytes]
    Frame --> Payload[Payload Data]
    Opcode --> Text[0x1: Text]
    Opcode --> Binary[0x2: Binary]
    Opcode --> Close[0x8: Close]
    Opcode --> Ping[0x9: Ping]
    Opcode --> Pong[0xA: Pong]

Teacher Mindset

Frames are the atomic unit of WebSocket communication. Text frames carry UTF-8 data. Binary frames carry arbitrary bytes. Ping-pong frames keep the connection alive. Close frames terminate the connection gracefully.

Code Examples

// Example 1: Sending different frame types
const ws = new WebSocket('ws://localhost:8080');

// Text frame (UTF-8 string)
ws.send('Hello, world!');

// Binary frame (ArrayBuffer)
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setUint32(0, 42);
ws.send(buffer);

// Binary frame (Blob)
ws.send(new Blob([buffer]));

// Binary frame (typed array)
ws.send(new Uint8Array([0x00, 0x01, 0x02]));
// Example 2: Handling close frames with status codes
const ws = new WebSocket('ws://localhost:8080');

ws.onclose = (event) => {
  console.log(`Closed: ${event.code} - ${event.reason}`);
  // 1000: Normal closure
  // 1001: Going away (server restart)
  // 1008: Policy violation
  // 1011: Unexpected error
};

// Server-side close with reason
ws.close(4001, 'Session expired');
// Example 3: Server ping-pong keepalive
const WebSocket = require('ws');

const server = new WebSocket.Server({ port: 8080 });

server.on('connection', (ws) => {
  ws.isAlive = true;

  ws.on('pong', () => {
    ws.isAlive = true;
  });

  // Ping every 10 seconds
  const interval = setInterval(() => {
    if (ws.isAlive === false) {
      console.log('Terminating dead connection');
      return ws.terminate();
    }

    ws.isAlive = false;
    ws.ping();
  }, 10000);

  ws.on('close', () => clearInterval(interval));
});

Common Mistakes

  • Closing connections without a status code (should send 1000 for normal)
  • Using text frames for binary data (causes UTF-8 encoding errors)
  • Not implementing ping-pong, leading to zombie connections
  • Sending frames larger than the server max frame size
  • Forgetting that client-to-server frames must be masked

Practice

  1. Send a text, binary, and ping frame from a WebSocket client.
  2. Handle close frames with different status codes.
  3. Implement server-side ping-pong with timeouts.
  4. Fragment a large message into multiple continuation frames.
  5. Challenge: Write a program that inspects and prints raw frame data (opcode, length, payload).

FAQ

What is the difference between text and binary frames?

Text frames are validated as UTF-8. Binary frames carry raw bytes. Use text for JSON/XML and binary for images, protobuf, or compressed data.

What is frame masking?

Client-to-server frames must be masked with a random 4-byte key. Server-to-client frames are not masked. This prevents cache poisoning attacks.

What are the standard close codes?

1000 (normal), 1001 (going away), 1008 (policy violation), 1011 (unexpected error). Codes 3000-4999 are available for applications.

Can I send multiple frames in one message?

Use fragmentation: the first frame has FIN=0, intermediate frames have FIN=0 and opcode=0 (continuation), the last frame has FIN=1.

What is the maximum frame size?

The payload length field supports up to 2^63 bytes. Practical limits are set by the server implementation.

Mini Project

Build a WebSocket server that distinguishes between text and binary frames. Echo text frames back to the sender. For binary frames, interpret the first 4 bytes as a 32-bit integer and send back its square. Implement ping-pong keepalive.

What's Next

Next, you will learn about the differences between ws:// and wss:// protocols.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro