Skip to content

HTTP status code · Client errors (4xx)

426 Upgrade Required

426 Upgrade Required means the server refuses to handle the request over the current protocol but will after the client switches to the one listed in the Upgrade header. The most common cause is opening a WebSocket URL with a normal HTTP request, or a proxy that drops the Upgrade headers.

Facts about this status code
Class4xx, Client errors
Defined inRFC 9110 §15.5.22
Cacheable by defaultOnly with explicit Cache-Control or Expires
Safe to retryYes, over the protocol named in the Upgrade header
Relevant headers
  • Upgrade: required in a 426; names the protocol the server wants, such as websocket
  • Connection: Connection: Upgrade marks the Upgrade header as hop-by-hop

What 426 means

RFC 9110, section 15.5.22, requires a 426 response to include an Upgrade header listing the acceptable protocols, and its own example asks for HTTP/3.0. In real traffic the protocol is almost always websocket: the Node.js ws library, for instance, answers a plain HTTP request to its standalone server with 426.

A WebSocket connection starts as an HTTP/1.1 GET with Upgrade: websocket and Connection: Upgrade. If you paste the endpoint into a browser tab, or a reverse proxy forwards the request without those two headers, the server sees ordinary HTTP and replies 426.

Common causes

If you are visiting the site

  • You opened a WebSocket address (often something like /ws or /socket) directly in the browser address bar.
  • A corporate proxy or antivirus strips the Upgrade header from outgoing requests.

If you run the server

  • nginx in front of the app proxies /ws without proxy_http_version 1.1 and the Upgrade and Connection headers, so the backend never sees the handshake.
  • A load balancer or platform with WebSocket support disabled for that route.
  • A health check or monitoring probe that sends plain GET to the WebSocket port.

How to fix it

If you are visiting the site

  • Open the page that uses the socket, not the socket URL itself; the page opens the connection for you.
  • If a web app fails only on one network, try another network or disable the filtering proxy.

If you run the server

  • In nginx, add proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; to the WebSocket location.
  • Point health checks at a normal HTTP route instead of the socket endpoint.
  • Test the handshake directly: curl -i -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" https://example.com/ws should return 101.

How to send 426

Express (Node.js)
app.get('/ws', (req, res) => {
  res.set('Upgrade', 'websocket');
  res.set('Connection', 'Upgrade');
  res.status(426).json({ error: 'This endpoint only accepts WebSocket connections' });
});
Next.js App Router route handler
// app/ws/route.ts
export async function GET() {
  return Response.json(
    { error: 'This endpoint only accepts WebSocket connections' },
    { status: 426, headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade' } }
  );
}
Go net/http
mux.HandleFunc("GET /ws", func(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Upgrade", "websocket")
	w.Header().Set("Connection", "Upgrade")
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusUpgradeRequired) // 426
	w.Write([]byte(`{"error":"This endpoint only accepts WebSocket connections"}`))
})
Python FastAPI
from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.get("/ws")
def websocket_only():
    raise HTTPException(status_code=426, detail="This endpoint only accepts WebSocket connections", headers={"Upgrade": "websocket", "Connection": "Upgrade"})
Nginx
location /ws {
  if ($http_upgrade !~* ^websocket$) {
    add_header Upgrade websocket always;
    return 426;
  }
  proxy_pass http://app;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

Commonly confused with

426 vs 101
101 Switching Protocols is the success answer to an upgrade request; 426 is the refusal you get when you did not ask for the upgrade.
426 vs 505
505 rejects the HTTP version in the request line; 426 accepts the request but wants a different protocol named in Upgrade.

Frequently asked questions

Why do I get 426 Upgrade Required from a WebSocket server?
The request reached the server without the Upgrade: websocket and Connection: Upgrade headers, so it looked like plain HTTP. Either something opened the URL as a web page, or a proxy in between removed those headers.
Can 426 be used to force HTTPS?
RFC 2817 described upgrading HTTP to TLS with Upgrade and 426, but browsers never implemented it. To move visitors to HTTPS, use a 301 or 308 redirect and an HSTS header.
What header must a 426 response include?
Upgrade, listing the protocol or protocols the server will accept, for example Upgrade: websocket. RFC 9110 makes it mandatory, and it usually goes with Connection: Upgrade.

Last reviewed by Arielton Oberek.