Skip to content

WebSocket HTTP Upgrade — Complete Guide

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Websocket HTTP Upgrade. We cover key concepts, practical examples, and best practices to help you master this topic.

The WebSocket connection begins with an HTTP upgrade handshake. This standard mechanism allows WebSocket to work through existing HTTP infrastructure while switching to a more efficient protocol.

What You'll Learn

  • HTTP upgrade request structure
  • Key handshake headers
  • Server response format
  • Security during the handshake
  • Troubleshooting handshake failures

Why It Matters

Understanding the handshake is essential for debugging connection issues, implementing custom servers, and configuring proxies that handle WebSocket traffic.

Real-World Use

A cloud provider's load balancer must recognize WebSocket upgrade requests and route them correctly. Understanding handshake headers allows ops teams to configure proxies that do not drop or time out WebSocket connections.

Flow Chart

sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: GET /ws HTTP/1.1
    C->>S: Upgrade: websocket
    C->>S: Connection: Upgrade
    C->>S: Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
    C->>S: Sec-WebSocket-Version: 13
    S->>C: HTTP/1.1 101 Switching Protocols
    S->>C: Upgrade: websocket
    S->>C: Connection: Upgrade
    S->>C: Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    Note over C,S: Full-duplex communication begins

Code Examples

Example 1: Manual Upgrade Request

const http = require('http');
const crypto = require('crypto');

const key = crypto.randomBytes(16).toString('base64');

const options = {
  hostname: 'echo.example.com',
  port: 80,
  path: '/ws',
  headers: {
    'Upgrade': 'websocket',
    'Connection': 'Upgrade',
    'Sec-WebSocket-Key': key,
    'Sec-WebSocket-Version': '13',
  },
};

const req = http.request(options);
req.end();

req.on('upgrade', (res, socket) => {
  const acceptKey = res.headers['sec-websocket-accept'];
  const expectedAccept = crypto
    .createHash('sha1')
    .update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
    .digest('base64');

  if (acceptKey === expectedAccept) {
    console.log('WebSocket handshake successful');
    // Now use socket for WebSocket communication
  }
});

Expected output: Client performs manual WebSocket handshake and verifies the server's accept key.

Example 2: Server-Side Handshake Verification

const http = require('http');
const crypto = require('crypto');

const server = http.createServer((req, res) => {
  res.writeHead(400);
  res.end();
});

server.on('upgrade', (req, socket, head) => {
  const key = req.headers['sec-websocket-key'];
  const version = req.headers['sec-websocket-version'];

  if (version !== '13') {
    socket.write('HTTP/1.1 426 Upgrade Required\r\n\r\n');
    socket.destroy();
    return;
  }

  const acceptKey = crypto
    .createHash('sha1')
    .update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
    .digest('base64');

  socket.write(
    'HTTP/1.1 101 Switching Protocols\r\n' +
    'Upgrade: websocket\r\n' +
    'Connection: Upgrade\r\n' +
    `Sec-WebSocket-Accept: ${acceptKey}\r\n` +
    '\r\n'
  );

  console.log('WebSocket connection established');
  // WebSocket communication follows
});

server.listen(8080);

Expected output: Server validates the WebSocket version, computes the accept key, and completes the handshake.

Example 3: Handshake with Custom Headers

// Client with custom headers
const ws = new WebSocket('wss://api.example.com/ws', {
  headers: {
    'Authorization': 'Bearer token123',
    'X-Client-Version': '2.1.0',
    'X-Device-Id': 'device-456',
  },
});

// Server extracting custom headers
server.on('upgrade', (req, socket, head) => {
  const auth = req.headers['authorization'];
  const clientVersion = req.headers['x-client-version'];
  const deviceId = req.headers['x-device-id'];

  if (!auth || !auth.startsWith('Bearer ')) {
    socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
    socket.destroy();
    return;
  }

  const token = auth.slice(7);
  if (!validateToken(token)) {
    socket.write('HTTP/1.1 403 Forbidden\r\n\r\n');
    socket.destroy();
    return;
  }

  console.log(`Client ${deviceId} v${clientVersion} connected`);
  // Complete handshake...
});

Expected output: Custom headers passed during the WebSocket handshake enable authentication and client identification.

Common Mistakes

Mistake Explanation
Missing Connection: Upgrade header Both Upgrade and Connection headers are required for a valid handshake
Wrong Sec-WebSocket-Version Only version 13 is widely supported; older versions are obsolete
Ignoring Sec-WebSocket-Accept verification Clients should verify the server's accept key to prevent hijacking
Forgetting the magic GUID The server must append 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 before hashing the key
Not validating origin header In production, validate the Origin header to prevent cross-origin WebSocket attacks

Practice Questions

  1. What HTTP status code indicates a successful WebSocket upgrade?
  2. What is the purpose of the Sec-WebSocket-Key header?
  3. How does the server compute the Sec-WebSocket-Accept value?
  4. What happens if the server does not support WebSocket?
  5. Can custom headers be passed during the WebSocket handshake?

Challenge

Build a WebSocket server that authenticates clients during the handshake using a custom token header. Reject unauthorized connections with appropriate HTTP status codes and log all handshake attempts.

FAQ

Can a WebSocket handshake use HTTP/2?

WebSocket over HTTP/2 is defined in RFC 8441 but has limited browser and server support compared to HTTP/1.1 upgrade.

What happens if the server returns a non-101 response?

The connection falls back to HTTP. The client should handle non-101 responses and may retry with a different strategy.

How long does the handshake take?

The handshake adds one round trip beyond the TCP connection setup, typically 10-50ms on fast networks.

Can I send data during the handshake?

No, data cannot be sent until the handshake completes and the 101 response is received.

What headers are required in the handshake?

Required client headers: Upgrade, Connection, Sec-WebSocket-Key, Sec-WebSocket-Version. Required server headers: Upgrade, Connection, Sec-WebSocket-Accept.

How do proxies affect the handshake?

Proxies must support the Upgrade mechanism. Some proxies strip Upgrade headers or time out idle connections during the handshake.

Mini Project

Build a WebSocket handshake diagnostic tool that connects to any WebSocket endpoint, displays all handshake headers sent and received, verifies the Sec-WebSocket-Accept key, and reports any issues with the handshake Process.

What's Next

Learn about WebSocket frames and data transmission

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro