,{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Does HTTP/2 over TLS produce a 101 response?","acceptedAnswer":{"@type":"Answer","text":"No. HTTP/2 over TLS uses ALPN in the TLS handshake to negotiate HTTP/2 directly without a 101 response. Only h2c (cleartext HTTP/2) uses the Upgrade mechanism and produces 101."}},{"@type":"Question","name":"Can a single origin serve both HTTP and WebSocket on the same port?","acceptedAnswer":{"@type":"Answer","text":"Yes. The same server on port 443 handles regular HTTP requests with 200 and WebSocket upgrade requests with 101, distinguishing them by the presence of Upgrade: websocket in the request."}}]}

HTTP 101 Switching Protocols

Quick reference

Code101
NameSwitching Protocols
Category1xx Informational
SpecRFC 9110 §15.2.2
Common useWebSocket 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

CodeDirectionMeaning
101Server → ClientUpgrade accepted; switching now
426Server → ClientUpgrade 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.

Related guides

HTTP 426 · HTTP 200 · HTTP 100 · HTTP 103 · HTTP 400

Informational Codes Hub · All Guides · Home