skip to content

HTTP Upgrade Handshake

The upgrade that turns an ordinary request into a socket: the Sec-WebSocket-Key and Accept digest, version checks, and the 101 response. Interviewers use it to see how the protocol reuses HTTP.

part ofWebSocketsoverview, primer and where to startread it →
on this pageshow

questions

4

What does a WebSocket client send in its HTTP/1.1 upgrade request, and which response means the socket is open?

level: juniorimportance: must knowfreq 84%

answer

  1. ordinary request, extraordinary answer
  2. GET with two switch fields
  3. key from client, accept from server
  4. status line 101, never 200
  5. blank line ends HTTP forever

basics

~20 s

A WebSocket client opens with an ordinary HTTP/1.1 GET carrying Host, Upgrade: websocket, Connection: Upgrade, a random Sec-WebSocket-Key and Sec-WebSocket-Version: 13. A 101 Switching Protocols response with a matching Sec-WebSocket-Accept means the socket is open.

solid answer

~40 s

The opening handshake is one ordinary HTTP/1.1 request. The client sends `GET` on a normal path with a `Host` field, plus `Upgrade: websocket` and a `Connection` field containing the token `Upgrade`, a `Sec-WebSocket-Key` whose base64 value decodes to 16 freshly random bytes, and `Sec-WebSocket-Version: 13`. If the server agrees it replies with the status line `101 Switching Protocols`, echoes `Upgrade: websocket` and `Connection: Upgrade`, and returns `Sec-WebSocket-Accept`, a digest computed from the key the client sent. The 101 has no body: everything after the blank line that ends its header block is WebSocket protocol data, not HTTP. Anything other than a validated 101 means no socket exists.

code

http · 6 lines
http
GET /locks/gate-3/telemetry HTTP/1.1
Host: locks.example.net
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

go deeper

for a junior

Recall the shape: a GET with Host, Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Key and Sec-WebSocket-Version: 13, answered by 101 Switching Protocols with Sec-WebSocket-Accept.

for a middle

Explain why each field is there: the Connection token marks Upgrade as applying to this one connection, the key is a fresh random nonce, and the blank line after the 101 is the last HTTP byte.

for a senior

Show that you read the actual status line before believing a socket exists, and that you know a 200 on an upgrade request means something answered that never switched protocols.

for a principal

The point worth owning is that this exchange is the only moment a socket is visible to ordinary HTTP routing and diagnostics, which shapes how a whole estate is addressed and observed.

## An HTTP request that is meant to stop being one A WebSocket connection does not begin with a client dialling a port of its own. It begins with **one ordinary HTTP/1.1 request**, sent to a normal web endpoint, asking the server to stop speaking HTTP on this connection and speak the WebSocket protocol instead. RFC 6455 calls this the **opening handshake**, and in its HTTP/1.1 form it happens exactly once per connection. If the server agrees, the request is never answered in the usual sense. There is no response body, no `Content-Length` to read, and nothing more to parse as HTTP: the blank line that terminates the response header block is the last HTTP byte on that connection, and every byte after it belongs to the WebSocket protocol. Reusing HTTP this way buys three things that matter in practice: - the request travels to the same ports and through the same request path as any other web traffic (`ws:` defaults to port 80, `wss:` to port 443); - it carries a mandatory `Host` field, so name-based virtual hosting works exactly as it does for pages; - the request line still names **an ordinary path**, so one host can expose many distinct WebSocket endpoints and route them the way it routes anything else. ## What the client MUST send 1. **The method `GET`**, on **HTTP/1.1 or higher**. No other method opens a socket in this form. 2. **`Host`** — the authority being addressed, as on any HTTP/1.1 request. 3. **`Upgrade: websocket`** — the protocol the client wants to switch to. The token is matched case-insensitively. 4. **A `Connection` field containing the token `Upgrade`** — this is what marks the `Upgrade` field as hop-by-hop, meaning it applies to this connection and not end to end. 5. **`Sec-WebSocket-Key`** — base64 text whose decoded form is **16 bytes**, chosen randomly and **freshly for every connection**. 6. **`Sec-WebSocket-Version: 13`** — the protocol version the client speaks. Optional fields may also ride along — `Origin`, `Sec-WebSocket-Protocol`, `Sec-WebSocket-Extensions` — but what they negotiate and what a negotiated value then means are separate subjects and none of them is required to open a socket. ## The response that ends the HTTP conversation | Element | Sent by | What it does | |---|---|---| | `101 Switching Protocols` | server | The status line that accepts the switch. Not `200`, not `204`. | | `Upgrade: websocket` | server | Names the protocol now in force on this connection. | | `Connection: Upgrade` | server | Confirms the switch applies to this connection. | | `Sec-WebSocket-Accept` | server | A digest derived from the client's `Sec-WebSocket-Key`, proving the peer implements this handshake. | | `Sec-WebSocket-Key` | client | The per-connection random nonce the digest is computed from. | | `Sec-WebSocket-Version` | client | The version the client speaks; the server refuses if it cannot. | Note the direction carefully, because it reverses easily under pressure: **the client sends the key, the server answers with the accept digest.** Never the other way round. ## After the blank line Once the client has validated the 101, the HTTP layer is finished with this connection. The bytes flowing in both directions from that point are WebSocket frames, whose bit layout, opcodes and length encoding are a separate subject; HTTP's message-framing rules no longer apply, and neither side is obliged to send anything at all. The connection then simply lives until one side closes it. This is also why the handshake is worth knowing precisely: it is the **only** moment in a socket's life when ordinary HTTP tooling, routing and diagnostics apply. Everything a candidate can say about the connection afterwards depends on having got this exchange right. ## What candidates get wrong - Describing the client as opening a raw connection and "then doing WebSocket", with no HTTP request in the story at all. - Answering `200 OK` as the success status. A `200` on an upgrade request means the request reached something that did not switch protocols, so no socket exists. - Treating the 101 as a normal response with a body to read. - Calling `Sec-WebSocket-Key` a credential the server checks to decide who may connect. It authorises nobody. - Believing a WebSocket URL cannot carry a path, and therefore that a host serves exactly one socket endpoint.

  • What do the `ws:` and `wss:` URI schemes change about the request itself?
    Very little. `ws:` defaults to port 80 and `wss:` to port 443, and `wss:` runs the identical handshake inside a TLS connection. The request line still names an ordinary path, so one host can serve many socket endpoints on the same port.
  • Does the upgrade request have a body, and does the 101 response have one?
    Neither does. The request is a plain `GET` with no body, and the 101 carries no body and no `Content-Length`. The blank line ending the 101's header block is the last HTTP byte on the connection; everything after it is WebSocket protocol data.
  • Why does the specification insist the method is `GET` and the version at least HTTP/1.1?
    Because the handshake must be a request any HTTP/1.1 participant can parse and route, and because protocol switching is defined for HTTP/1.1's `Upgrade` mechanism. A server that receives another method on that path answers as it would for any wrong method, and no socket opens.

saying these in an interview costs you the question

  • Describes the client as opening a raw socket with no HTTP request at all
  • Answers 200 OK as the status that accepts the upgrade
  • Reads the 101 response as having a body to parse
  • Calls Sec-WebSocket-Key a credential that authorises the client
  • Thinks a WebSocket URL cannot carry a path, so one host serves one socket
  • Has the server sending the key and the client answering the digest
open as a page

In a WebSocket opening handshake, how does the server compute Sec-WebSocket-Accept, and what does that value prove?

level: middleimportance: must knowfreq 66%

basics

~10 s

The server appends the fixed GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 to the client's Sec-WebSocket-Key text, SHA-1 hashes the result and base64-encodes the digest. It proves the peer implements the WebSocket handshake - not authentication, privacy or integrity.

open as a page

What must a WebSocket client do when a 101 response arrives whose Sec-WebSocket-Accept does not match the key it sent?

level: seniorimportance: should knowfreq 48%

basics

~20 s

It must fail the WebSocket connection: stop, close the underlying connection, and never read the following bytes as protocol data. A wrong or absent digest means whatever answered did not perform this handshake for this connection.

open as a page

What does a server send when a WebSocket upgrade request names a Sec-WebSocket-Version it does not support?

level: middleimportance: nice to knowfreq 31%

basics

~20 s

It aborts the handshake and returns an ordinary HTTP error response - the specification names 426 Upgrade Required - carrying a Sec-WebSocket-Version field that lists every version it is willing to speak. The client may retry with one of them.

open as a page