Skip to content
RU

ERR_HTTP2_PROTOCOL_ERROR: How to Fix the HTTP/2 Protocol Error

Monitor with a blank grey browser error page beside a console full of red errors

What it means: Chrome received an HTTP/2 response that broke the protocol rules, usually a malformed header or a truncated body.

  1. Reload in an incognito window without extensions
  2. Try another network; pause antivirus HTTPS scanning
  3. If it fails everywhere: check the server error log
  4. Compare curl --http2 with curl --http1.1
  5. Fix the bad header, length or buffering

Test your URL now

Tests which of HTTP/1.1, HTTP/2 and HTTP/3 your server actually negotiates.

Test HTTP/2 and HTTP/3 →

What ERR_HTTP2_PROTOCOL_ERROR means

ERR_HTTP2_PROTOCOL_ERROR is Chromium net error -337, described in the source as "There is an HTTP/2 protocol error." By the time it appears, DNS, TCP and the TLS handshake have all succeeded and the browser negotiated HTTP/2 through ALPN (h2). The failure is inside the HTTP/2 conversation: Chrome received a frame or a header block that violates RFC 9113, or the server (or a proxy in front of it) reset the stream or closed the connection with a protocol error.

It is not a certificate problem (those are ERR_CERT_* codes) and not an HTTP status error: a 400 or 500 response is a valid HTTP/2 message and renders normally. Chrome shows the generic "This site can't be reached" page with the code underneath, and in DevTools > Network the request is marked (failed) net::ERR_HTTP2_PROTOCOL_ERROR. Often only one resource fails, such as an API call or a large script, while the rest of the page loads.

Causes in Chrome, Edge, Firefox and Safari

BrowserWhat you seeMost common trigger
Chrome"This site can't be reached" with ERR_HTTP2_PROTOCOL_ERROR, or one failed request in DevToolsMalformed response header, Content-Length mismatch, response cut off by a proxy
EdgeThe same Chromium code and pageSame as Chrome
FirefoxIts own connection-failure wording, not this codeThe same server-side faults
SafariIts own wording, not this codeThe same server-side faults

RFC 9113 lists what makes an HTTP/2 message malformed, and a client must reject it. The rules that break real sites most often: field names must be lowercase; connection-specific headers (Connection, Keep-Alive, Proxy-Connection, Transfer-Encoding, Upgrade) are forbidden; and a content-length value must equal the bytes actually sent in DATA frames. An application that sets Transfer-Encoding itself, a header value containing a newline or control character, or a body that is gzip-compressed after Content-Length was calculated all produce this error. These rules do not exist in HTTP/1.1, which is why the same URL often works with curl --http1.1.

The second big group is truncated responses. If nginx cannot buffer an upstream response to disk because the temp directory is full or not writable, the stream ends early and Chrome reports a protocol error instead of a partial page. On the visitor side, antivirus HTTPS scanning and corporate TLS-inspecting proxies re-encode HTTP/2 traffic and can break it in the same way.

Large cookies are often blamed, but nginx answers an oversized request header with 400 Bad Request ("Request Header Or Cookie Too Large"), which is a normal response. Check the header size only after the response-side causes are ruled out.

Behind Cloudflare, nginx or another proxy

Cloudflare documents that ERR_HTTP2_PROTOCOL_ERROR on proxied requests is usually caused by the origin: malformed response headers or compression problems (gzip content with a stale Content-Length, or broken gzip). Request the origin directly, bypassing Cloudflare, and inspect the raw headers. As an isolation test, Speed > Settings > Protocol Optimization has an HTTP/2 to Origin toggle; Free plans cannot disable HTTP/2 towards visitors.

On nginx, enable HTTP/2 with the http2 directive (1.25.1 and later) and make sure response buffering has room to work:

server {
    listen 443 ssl;
    http2 on;                      # nginx < 1.25.1: listen 443 ssl http2;
    server_name example.com;

    # Temp files for buffered upstream responses: must exist,
    # be writable by the worker user and have free disk space
    proxy_temp_path /var/cache/nginx/proxy_temp;

    # Request header limits (http2_max_header_size is obsolete since 1.19.7)
    large_client_header_buffers 4 16k;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

With HAProxy, HTTP/2 is offered through ALPN on the bind line (bind :443 ssl crt /etc/haproxy/certs/example.pem alpn h2,http/1.1). Temporarily setting alpn http/1.1 tells you whether the HTTP/2 layer is at fault, but it is a diagnostic, not a fix.

If you own the site

  1. Reproduce outside the browser. curl -sv --http2 -o /dev/null https://example.com/failing/path. A protocol failure typically ends with curl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR.
  2. Compare with HTTP/1.1. curl -sv --http1.1 -o /dev/null https://example.com/failing/path. If this works, the problem is a rule that only HTTP/2 enforces.
  3. Read the response headers. curl -sI --http1.1 https://example.com/failing/path and look for Transfer-Encoding, Connection, Upgrade or Keep-Alive set by the application, duplicate Content-Length values, and values with stray characters.
  4. Check the proxy error log. grep -E 'No space left|Permission denied' /var/log/nginx/error.log and df -h /var/cache/nginx. Fix the disk or the directory ownership, or set proxy_buffering off only for streaming endpoints.
  5. Fix compression in one place. Compress either in the application or in the proxy, not both, and never send a precomputed Content-Length for a body that is compressed later.
  6. Capture Chrome's view. Record the failure in chrome://net-export, open the log in the NetLog viewer and read the events for the failing stream: HTTP2_SESSION_RECV_RST_STREAM or HTTP2_SESSION_RECV_GOAWAY means the server ended it, HTTP2_SESSION_SEND_RST_STREAM means Chrome rejected what it received.

Turning HTTP/2 off (http2 off; in nginx, Protocols http/1.1 in Apache) makes the error disappear but leaves the broken header or truncated body in place.

If you are a visitor

Reload in an incognito window with extensions disabled. If that works, an extension that rewrites requests is involved. Next, try another network (mobile data instead of office Wi-Fi) and temporarily turn off the HTTPS or web-scanning feature of your antivirus, or disconnect from the VPN or corporate proxy: these products sit in the middle of the HTTP/2 connection. Updating Chrome rules out old bugs.

Clearing the cache rarely helps, because the error is not stored. What can persist is an open connection; chrome://net-internals/#sockets > Flush socket pools closes it. If the page fails on every browser, device and network, the fault is on the server and only the site owner can fix it.

How to confirm the fix

curl -sv --http2 -o /dev/null https://example.com/failing/path
# expect: < HTTP/2 200  and no "not closed cleanly" line
curl -sI --http2 https://example.com/failing/path | grep -iE 'content-length|transfer-encoding|connection'

Then reload with DevTools open and confirm the request shows a status code instead of (failed). To check HTTP/2 and HTTP/3 negotiation from outside your network, run the URL through the HTTP/2 and HTTP/3 protocol test.

Related errors

TLS 1.2 / 1.3Supported protocol versions
Cipher SuitesCryptographic algorithms and security
HTTP/2 + HTTP/3Support for modern protocols
Legacy TLSSSL 2.0/3.0 and TLS 1.0/1.1 vulnerabilities

Why teams trust us

TLS 1.3
supported
HTTP/2
ALPN check
BEAST
vulnerability detection
Free
no limits

How it works

1

Enter domain

2

Test TLS/HTTP versions

3

Get protocol report

Why test protocols?

Protocol testing checks which TLS versions the server supports. Legacy versions (TLS 1.0, SSL 3.0) have known vulnerabilities and must be disabled.

TLS Versions

Check TLS 1.0, 1.1, 1.2, 1.3 support — with security rating for each.

Cipher Suites

List of supported cipher algorithms with strength rating for each.

HTTP/2 Support

ALPN negotiation check for HTTP/2 (h2) and HTTP/3 (h3) via QUIC.

Vulnerabilities

Detection of BEAST, POODLE, DROWN, and other TLS/SSL attacks.

Who uses this

DevOps

TLS configuration check

Security

protocol and cipher audit

Developers

HTTP/2 compatibility

SEO

HTTPS ranking signal

Common Mistakes

Leaving TLS 1.0 and 1.1Both are deprecated and vulnerable to BEAST, POODLE attacks. Browsers dropped support in 2020.
Weak cipher suitesRC4, DES, and 3DES must be disabled. Use AES-GCM and ChaCha20.
Not supporting TLS 1.3TLS 1.3 is faster and more secure. All modern servers should support it.
Ignoring HSTSWithout HSTS, the browser may attempt HTTP connection. HSTS forces HTTPS.

Best Practices

Enable only TLS 1.2 and 1.3This covers 99%+ of users and provides modern security levels.
Use PFS ciphersPerfect Forward Secrecy (ECDHE) protects past sessions even if the key is compromised.
Check after nginx/Apache updateUpdates can change default ciphers. Always check after updating.
Test with different clientsEnsure old mobile devices and IE11 can connect if needed.

Monitor SSL certificate automatically

SSL monitor alerts 30 days before expiry and on TLS version changes.

Sign up free

Learn more

Sources

Frequently Asked Questions

How do I see whether Chrome or the server ended the stream?

Record the failure in chrome://net-export and read the failing stream in the NetLog viewer. HTTP2_SESSION_RECV_RST_STREAM or HTTP2_SESSION_RECV_GOAWAY means the server ended it; HTTP2_SESSION_SEND_RST_STREAM means Chrome rejected what it received.

Why does the site work in Firefox but not in Chrome?

Browsers do not react identically to every malformed HTTP/2 response, and Chrome enforces the RFC 9113 rules strictly. The fix is still on the server: remove the invalid header or length mismatch.

Why does only one file or API request fail?

The error is per stream, so only the response that breaks the rules fails. Look for what is special about it: a header set by that endpoint, a compressed download, or a large body that the proxy buffers to disk.

Should I disable HTTP/2 to make the error go away?

Only as a short test. Falling back to HTTP/1.1 hides the malformed header or truncated body, and it costs performance for every visitor.

Can a large cookie cause ERR_HTTP2_PROTOCOL_ERROR?

It is possible on some servers, but nginx answers oversized request headers with 400 Bad Request instead. Rule out response headers, compression and proxy buffering first.

Try the live tool that powered this guide

Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.