HTTP 101 Switching Protocols
Quick reference
| Code | 101 |
|---|---|
| Name | Switching Protocols |
| Category | 1xx Informational |
| Spec | RFC 9110 §15.2.2 |
| Common use | WebSocket handshake, HTTP/2 cleartext upgrade |
What 101 means
HTTP 101 Switching Protocols is sent by the server when it agrees to change the protocol being used on the connection. The client requests the switch by sending an Upgrade: header and a Connection: Upgrade header in its request. If the server accepts, it responds with 101, the same Upgrade: and Connection: Upgrade headers, and immediately switches the connection to the new protocol.
After the 101 response, the TCP connection is no longer HTTP. The client and server communicate using the new protocol's framing, messages, and semantics. There is no further HTTP traffic on that connection — it has been permanently upgraded.
RFC 9110 requires the server's 101 response to include an Upgrade: header identifying the protocol being switched to. A 101 without an Upgrade: header would violate the spec.
WebSocket upgrade: complete handshake
WebSocket is the dominant real-world use of 101. Every WebSocket connection begins as an HTTP/1.1 request and transitions to the WebSocket protocol via a 101 upgrade:
# Client request GET /ws/feed HTTP/1.1 Host: api.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Version: 13 Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits Origin: https://app.example.com # Server accepts the upgrade HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Extensions: permessage-deflate
The Sec-WebSocket-Accept value is derived by the server: it concatenates the client's Sec-WebSocket-Key with the magic GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, computes the SHA-1 hash, and base64-encodes it. This proves to the client that the server genuinely supports WebSocket and understood the upgrade request.
After the 101, both sides switch to WebSocket framing. The client can now send text frames, binary frames, and ping/pong control frames. The server can push data to the client at any time without the client polling.
HTTP/2 cleartext (h2c) upgrade
HTTP/2 over TLS uses ALPN negotiation and never produces a 101. But HTTP/2 over cleartext (h2c) does use the Upgrade mechanism for connections that start as HTTP/1.1:
GET / HTTP/1.1 Host: example.com Connection: Upgrade, HTTP2-Settings Upgrade: h2c HTTP2-Settings: AAMAAABkAAQAAP__ HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: h2c [HTTP/2 binary frames follow]
In practice, h2c upgrade is rarely used. Most HTTP/2 deployments run over TLS and use ALPN to negotiate the protocol during the TLS handshake, producing no 101. h2c is primarily used in internal service mesh communication where TLS is handled at the infrastructure layer.
nginx proxy configuration for WebSocket
When proxying WebSocket connections through nginx, explicit upgrade header forwarding is required. Without it, nginx strips the Connection: Upgrade and Upgrade: headers, and the WebSocket handshake fails:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name api.example.com;
location /ws/ {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 86400s; # keep alive for long-lived connections
}
}
}
The map directive ensures Connection: upgrade is set when an Upgrade: header is present, and Connection: close is set for regular HTTP requests. The long proxy_read_timeout prevents nginx from closing idle WebSocket connections.
101 vs 426
| Code | Direction | Meaning |
|---|---|---|
| 101 | Server → Client | Upgrade accepted; switching now |
| 426 | Server → Client | Upgrade required but not yet requested by client |
426 is the server telling the client it must upgrade. 101 is the server confirming the client's upgrade request was accepted. A well-designed endpoint returns 426 when receiving a plain HTTP request, and 101 when receiving a proper upgrade request.
Frequently asked questions
Does HTTP/2 over TLS produce a 101 response?
No. HTTP/2 over TLS (the standard deployment) uses ALPN (Application-Layer Protocol Negotiation) in the TLS handshake to negotiate HTTP/2 directly. There is no HTTP upgrade request and no 101 response. The connection starts as HTTP/2 from the first request. Only h2c (cleartext HTTP/2) uses 101.
Can WebSocket connections pass through HTTP/2?
Yes, via RFC 8441 (Bootstrapping WebSockets with HTTP/2). Instead of HTTP/1.1 Upgrade, the client opens an HTTP/2 stream using an extended CONNECT method. The 101 mechanism is not used; instead, HTTP/2 stream management handles the WebSocket tunnel.
What is the Sec-WebSocket-Key used for?
The Sec-WebSocket-Key is a randomly generated 16-byte value base64-encoded by the client. The server uses it to compute Sec-WebSocket-Accept, which proves the server intentionally accepted the WebSocket upgrade and prevents accidental protocol tunneling through naïve HTTP servers.
Can a single origin serve both HTTP and WebSocket on the same port?
Yes, and this is standard practice. The same server listens on port 443 (HTTPS). Regular HTTP requests get 200 responses. WebSocket upgrade requests get 101 responses. The protocol distinction happens at the application level based on the presence of Upgrade: websocket in the request.