101 Switching Protocols
The server accepts the request to upgrade the connection to a different protocol.
Meaning & Description
The server will generate this response only when it is advantageous to do so, such as switching to a newer, incompatible version of HTTP (like HTTP/2) or switching to a synchronous/real-time protocol like WebSockets.
Common Causes
- A client explicitly requested an `Upgrade` to `websocket`.
- A client requested an `Upgrade` to `h2c` (HTTP/2 cleartext).
How to fix a 101 error
- Ensure the client sent the `Connection: Upgrade` and `Upgrade: <protocol>` headers.
- For WebSockets, verify the `Sec-WebSocket-Key` in the request and the `Sec-WebSocket-Accept` in the response match correctly.
- Check if an intermediate proxy or load balancer is stripping the `Upgrade` headers, which will cause the connection to fail.
- If the upgrade fails, ensure the server supports the requested protocol.
Browser & SEO Behaviour
Browser Behavior
The browser exposes the upgraded connection to JavaScript (e.g., via the WebSocket API) rather than treating it as a standard HTTP document response.
SEO Impact
No direct SEO impact. Search engine crawlers do not upgrade connections to WebSockets.
CDN Behavior
Many CDNs support proxying WebSocket connections. They will pass the 101 response through and hold the long-lived TCP connection open.
Code Examples
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=const WebSocket = require('ws');
const http = require('http');
const server = http.createServer();
const wss = new WebSocket.Server({ noServer: true });
server.on('upgrade', (request, socket, head) => {
// Handle the upgrade request manually
wss.handleUpgrade(request, socket, head, (ws) => {
// The server has sent the 101 Switching Protocols response
wss.emit('connection', ws, request);
});
});from fastapi import FastAPI, WebSocket
app = FastAPI()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
# FastAPI automatically handles the 101 Switching Protocols handshake
await websocket.accept()
await websocket.send_text("Hello WebSocket!")
await websocket.close()package main
import (
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{}
func echo(w http.ResponseWriter, r *http.Request) {
// Upgrade automatically sends the 101 status code
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
defer c.Close()
for {
mt, message, _ := c.ReadMessage()
c.WriteMessage(mt, message)
}
}# Testing a WebSocket upgrade requires specific headers.
# (Note: curl natively supports WebSockets in newer versions with --include)
curl -i -N \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
http://example.com/chatRaw HTTP Response Example
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
[...WebSocket binary stream begins...]Real-world Examples
Frequently Asked Questions
What happens if the server refuses the upgrade?
If the server does not support the requested protocol or refuses the upgrade, it will typically return a standard HTTP response like 200 OK (ignoring the upgrade) or a 400 Bad Request / 426 Upgrade Required error.
Is 101 Switching Protocols only used for WebSockets?
No, while WebSockets are the most common use case today, it is also used to upgrade from HTTP/1.1 to HTTP/2 over cleartext (h2c), or to other custom application protocols.
How is the Sec-WebSocket-Accept header calculated?
The server takes the client's `Sec-WebSocket-Key`, concatenates it with a globally unique identifier (GUID) defined by the RFC, computes the SHA-1 hash of the result, and Base64-encodes it.
Can an API gateway block a 101 response?
Yes. If a load balancer or proxy is not configured to support WebSockets, it may strip the `Upgrade` header or drop the 101 response, causing the connection to fail.
Does a 101 response have a body?
The HTTP 101 response itself does not have an HTTP body. Immediately after the empty line concluding the headers, the connection transitions to the new protocol's binary framing format.
Did You Know?
The magic string used in the WebSocket handshake calculation (`258EAFA5-E914-47DA-95CA-C5AB0DC85B11`) was hardcoded into RFC 6455 and must be used exactly by every WebSocket server in the world.
HTTP/2 generally deprecated the HTTP/1.1 Upgrade mechanism in favor of ALPN (Application-Layer Protocol Negotiation) at the TLS layer.
A 101 response is the only HTTP response where the TCP connection remains intentionally open and active indefinitely after the response finishes.
Developer Tips
- Always validate the `Origin` header during the HTTP handshake before issuing a 101 response to prevent Cross-Site WebSocket Hijacking.
- If your WebSocket connection fails in production but works locally, check your Nginx/HAProxy configuration. You often need explicit directives (like Nginx's `proxy_set_header Upgrade $http_upgrade;`) to allow 101 responses through.
- Remember to implement heartbeat mechanisms (ping/pong) over the established connection, as TCP keep-alives are often not sufficient to prevent load balancers from closing idle connections.
Interview Questions
These are questions you might face in a backend or API design interview that touch on HTTP 101.
Explain the handshake process for establishing a WebSocket connection.
The client sends an HTTP GET request with `Upgrade: websocket` and a `Sec-WebSocket-Key`. The server calculates a hash based on that key and responds with `101 Switching Protocols` and a `Sec-WebSocket-Accept` header. Once received, the TCP connection switches from HTTP to the WebSocket protocol.
Why do we need the Sec-WebSocket-Key in the upgrade request?
It proves to the server that the client actually understands the WebSocket protocol and isn't just sending random data. It also prevents caching proxies from mistakenly returning a cached 101 response.
What status code should a server return if it requires a client to upgrade to TLS/HTTPS?
The server should return `426 Upgrade Required` indicating that the client needs to use a different protocol (like TLS) to proceed.
Common Interview Mistakes
- Thinking that a 101 response contains the first WebSocket message in its HTTP body. The HTTP response ends at the double newline, and subsequent bytes are WebSocket frames.
- Confusing `101 Switching Protocols` with a 301/302 Redirect. A redirect asks the client to make a new request to a different URL, whereas 101 changes the protocol of the *current* underlying TCP connection.
- Assuming CORS automatically protects WebSocket endpoints. WebSocket handshakes bypass standard CORS preflight checks.