Skip to main content
426

Upgrade Required

Active
RFC 9110 §15.5.22Since 2000WebSocket servers, TLS enforcement, protocol version gating

HTTP 426 Upgrade Required indicates the server refuses to perform the request using the current protocol but might after the client upgrades. Defined in RFC 9110 §15.5.22. The server MUST send an Upgrade header field indicating the required protocol(s). Used for TLS upgrades, WebSocket negotiation, and HTTP/2 transitions.

Description

The 426 Upgrade Required status code indicates that the server refuses to perform the request using the current protocol but might be willing to do so after the client upgrades to a different protocol. The server MUST include an Upgrade header field in the response that indicates which protocol(s) are acceptable for the client to switch to.

This is fundamentally different from a 301 or 302 redirect. Those codes change the URL — the destination. 426 changes the PROTOCOL — the transport mechanism. The resource is at the same address, but the server demands a different language of communication to serve it. Think of it as 'I understand what you want, and I could give it to you, but not over this wire.'

The canonical use case was HTTP-to-HTTPS upgrades via RFC 2817 (Upgrading to TLS Within HTTP/1.1). The idea: instead of redirecting, the server could tell the client inline to switch to TLS on the same connection. In practice, this never gained traction because HSTS and 301 redirects proved simpler and more universally supported. Load balancers and CDNs now force HTTPS at the infrastructure layer, making application-level 426 responses for TLS unnecessary.

Where 426 remains relevant today is WebSocket negotiation failures and protocol version enforcement. A server that only speaks HTTP/2 could theoretically return 426 to an HTTP/1.1 client, though in practice ALPN (Application-Layer Protocol Negotiation) handles this during the TLS handshake. The response SHOULD include both the Upgrade header and a Connection: Upgrade header to signal the protocol switch mechanism.

426 is one of the rarest status codes in production. Most protocol upgrades happen at layers below HTTP (TLS negotiation, ALPN, load balancer enforcement). When you do encounter it, it almost always means a misconfigured client is attempting a connection using a protocol version or mechanism the server has explicitly deprecated.

Examples

HTTP/1.1 request to a server requiring HTTP/2
http
GET /api/stream HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer token123
426 response — HTTP/2 upgrade required
http
HTTP/1.1 426 Upgrade Required
Upgrade: h2c
Connection: Upgrade
Content-Type: application/json
Content-Length: 143 
{"error": "upgrade_required", "message": "This endpoint requires HTTP/2. Please upgrade your client protocol.", "required_protocol": "h2c"}
Plain HTTP request to a TLS-required endpoint
http
GET /secure/account HTTP/1.1
Host: bank.example.com
Accept: text/html
426 response — TLS upgrade required (RFC 2817 style)
http
HTTP/1.1 426 Upgrade Required
Upgrade: TLS/1.3, HTTP/1.1
Connection: Upgrade
Content-Type: text/plain
Content-Length: 92

This service requires TLS. Please retry your request using HTTPS or upgrade the connection.
HTTP request to a WebSocket-only endpoint
http
GET /ws/chat HTTP/1.1
Host: realtime.example.com
Accept: application/json
426 response — WebSocket upgrade required
http
HTTP/1.1 426 Upgrade Required
Upgrade: websocket
Connection: Upgrade
Content-Type: application/json

{"error": "upgrade_required", "message": "This endpoint only accepts WebSocket connections. Include Upgrade: websocket and Connection: Upgrade headers in your request.", "required_headers": ["Upgrade: websocket", "Connection: Upgrade", "Sec-WebSocket-Key", "Sec-WebSocket-Version: 13"]}

Edge Cases

  • The Upgrade header in the 426 response is MANDATORY per the RFC — a 426 without an Upgrade header is technically malformed and leaves the client with no way to know what protocol to switch to.
  • 426 is NOT appropriate for URL-based redirects (HTTP→HTTPS on a different port). Use 301 with a Location header for that. 426 is for same-connection protocol upgrades where the URL stays identical.
  • Most browsers do NOT handle 426 gracefully — they'll display the response body as a page rather than automatically upgrading. This is why HSTS + 301 won the TLS upgrade war over RFC 2817's 426 approach.
  • A WebSocket server returning 426 instead of 400 when the Upgrade header is missing is semantically more correct — it tells the client exactly what's needed rather than just 'bad request'.
  • If a server supports multiple upgrade paths (e.g., both HTTP/2 and WebSocket), it can list multiple protocols in the Upgrade header, comma-separated, in preference order.
  • 426 should NOT be used when the server simply doesn't support the requested protocol version — that's closer to 505 HTTP Version Not Supported. 426 means 'I COULD serve this, but only over a different protocol.'
  • Proxies and load balancers may strip or modify Upgrade headers, causing 426 responses to become meaningless to the downstream client. Always verify that intermediaries pass Upgrade headers through.

When You'll See This

  • WebSocket server receiving a plain HTTP request without Upgrade headers
  • API gateway enforcing HTTP/2 minimum for streaming endpoints
  • Legacy server implementing RFC 2817 TLS upgrade negotiation
  • gRPC server rejecting HTTP/1.1 requests (gRPC requires HTTP/2)
  • IoT gateway requiring MQTT-over-WebSocket upgrade from plain HTTP
  • Server deprecating HTTP/1.1 entirely and requiring HTTP/2 or HTTP/3
  • Real-time collaboration server requiring WebSocket for bidirectional communication

Implementation References

LanguageConstant
Gohttp.StatusUpgradeRequired
Rusthttp::StatusCode::UPGRADE_REQUIRED
Pythonhttp.HTTPStatus.UPGRADE_REQUIRED
Node.jshttp.STATUS_CODES[426]
.NETHttpStatusCode.UpgradeRequired
Java426 (no built-in constant; use literal)
PHPResponse::HTTP_UPGRADE_REQUIRED (Symfony)
Ruby:upgrade_required (Rack)

History

First defined in RFC 2817 (May 2000) as part of the mechanism for upgrading HTTP/1.1 connections to TLS inline, providing an alternative to the separate-port HTTPS approach. Formalized in HTTP semantics through RFC 7231 (June 2014) §6.5.15, then carried forward into RFC 9110 (June 2022) §15.5.22. Despite being standardized for over two decades, it remains one of the least-used status codes because infrastructure-level protocol enforcement (HSTS, ALPN, load balancer redirects) proved more practical than application-level upgrade negotiation.

Related Status Codes

Related Headers

FAQ

Why is 426 Upgrade Required rarely seen in production?

Most protocol upgrades happen below the HTTP layer. TLS negotiation occurs during the handshake (ALPN), HTTPS enforcement uses HSTS headers or 301 redirects, and HTTP/2 is negotiated via ALPN during TLS setup. By the time an HTTP response could carry a 426, the protocol decision has usually already been made by infrastructure (load balancers, CDNs, reverse proxies). The original RFC 2817 vision of inline TLS upgrade via 426 lost to the simpler model of separate ports (80 vs 443) plus automatic redirects.

What is the difference between 426 Upgrade Required and 101 Switching Protocols?

101 is the SUCCESS response — it means the server accepted the client's Upgrade request and is switching protocols right now. 426 is the REQUIREMENT response — it means the server won't serve the request at all until the client upgrades. The flow is: client sends request → server returns 426 with Upgrade header → client retries with proper Upgrade headers → server returns 101 → protocol switch happens. 426 is the demand; 101 is the fulfillment.

Should I use 426 or 301 to enforce HTTPS?

Use 301 (plus HSTS). While RFC 2817 envisioned 426 for inline TLS upgrades, the industry standardized on 301 redirects from http:// to https:// URLs combined with Strict-Transport-Security headers. Browsers understand 301 redirects universally but handle 426 poorly (no automatic upgrade behavior). HSTS preloading eliminates even the first insecure request. The only scenario where 426 makes theoretical sense for TLS is same-port upgrade negotiation, which virtually no production system uses.