- Home
- HTTP Headers
- Sec-WebSocket-Key
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.
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
Related Headers
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.