HTTP

Header

Sec-WebSocket-Key

Learn how the Sec-WebSocket-Key header provides a random key for WebSocket handshake validation. Understand the upgrade process and security implications.

2 min read advanced Try in Playground

TL;DR: Random key sent by clients during WebSocket handshake. Server uses it to prove it received the upgrade request and understands WebSocket protocol.

What is Sec-WebSocket-Key?

The Sec-WebSocket-Key header provides a nonce that the server uses to prove it received a valid WebSocket request, preventing cache poisoning attacks.

Example

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
```javascript

Browsers generate this automatically as a Base64 value derived from 16 random bytes.

## How the Handshake Uses It

The server does not echo this key directly. Instead, it:

1. appends the fixed GUID `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`
2. computes SHA-1
3. Base64-encodes the result
4. returns it in `Sec-WebSocket-Accept`

This confirms the server understands the WebSocket upgrade protocol.

## Server-Side Validation Example

```javascript
import crypto from 'node:crypto'

function computeAccept(key) {
  const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
  return crypto.createHash('sha1').update(key + GUID).digest('base64')
}

Common Mistakes

  • Treating WebSocket upgrade as plain HTTP 101 without validating key/version
  • Accepting malformed or missing Sec-WebSocket-Key
  • Trying to set this header manually from browser JavaScript

Why the Key Exists: Cache Poisoning Prevention

The Sec-WebSocket-Key is not a security credential — it does not authenticate the client or protect the connection from eavesdropping. Its purpose is narrower and more specific: preventing HTTP caching infrastructure from interfering with WebSocket upgrades.

Before WebSocket was standardized, some HTTP proxies and caches would intercept upgrade requests and serve cached responses. A random nonce that the server must transform and echo back makes it impossible for a cache to replay an old response, because the expected Sec-WebSocket-Accept value changes with every connection attempt.

The key is generated by the browser from 16 random bytes, base64-encoded to produce a 24-character string. Browsers set this header automatically and prevent JavaScript from reading or modifying it, which is why you cannot initiate a WebSocket upgrade manually from fetch() or XMLHttpRequest. The WebSocket constructor is the only browser API that can trigger the upgrade.

On the server side, libraries like ws (Node.js), gorilla/websocket (Go), and Django Channels handle the key validation automatically. You only need to implement it manually if you are building a raw WebSocket server from scratch. In that case, the algorithm is: base64(sha1(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")). Getting this wrong causes the browser to reject the connection with a clear error in the developer console.

Frequently Asked Questions

What is Sec-WebSocket-Key?

Sec-WebSocket-Key is a random base64-encoded value sent by clients during WebSocket handshake. The server uses it to prove it received the upgrade request.

How does the server respond to Sec-WebSocket-Key?

Server concatenates the key with a magic GUID, computes SHA-1 hash, base64 encodes it, and returns as Sec-WebSocket-Accept. This proves the server understands WebSocket.

Why is Sec-WebSocket-Key needed?

It prevents caching proxies from replaying old WebSocket responses and ensures the server intentionally accepts WebSocket connections, not just any HTTP upgrade.

Can I set Sec-WebSocket-Key manually?

Browsers set it automatically and prevent JavaScript from modifying it. This is a security measure to prevent cross-protocol attacks.

Keep Learning