You open your site and Chrome shows a blank page with ERR_HTTP2_PROTOCOL_ERROR. Refresh, and it sometimes loads. Open it in Firefox and it's fine. Annoying, and it makes you doubt your hosting. The good news: this error is almost always about one specific request breaking the HTTP/2 connection, not your whole server being down. Here's how we track it down on cPanel and VPS setups.

What the error actually means

HTTP/2 packs many requests into one connection. If the server sends something that breaks the protocol rules, such as a malformed header, a response whose size doesn't match its Content-Length, or a connection that gets cut mid-stream, Chrome drops the whole connection and shows this error. Other browsers are sometimes more forgiving, which is why the page may load elsewhere.

Symptoms you'll typically see

  • The page fails in Chrome/Edge but loads in Firefox or Safari.
  • It fails only on certain pages, usually big downloads, uploads or admin screens.
  • It started right after enabling Cloudflare, a new SSL, a plugin, or a PHP/Apache change.
  • The browser console (F12 → Network) shows one request as (failed) net::ERR_HTTP2_PROTOCOL_ERROR.

Step 1: Confirm it's HTTP/2 and find the failing request

Force HTTP/1.1 and compare:

curl -sI --http1.1 https://example.com/ | head -n 5
curl -sI --http2 https://example.com/ | head -n 5

If HTTP/1.1 works and HTTP/2 doesn't, the problem is in the HTTP/2 layer or something feeding it. Next, open DevTools → Network, reload, and note which file is red. That single URL is your real suspect.

Common causes and fixes

1. A PHP script sending a wrong Content-Length or stray output

This is the number one cause on shared hosting. A plugin that echoes whitespace before headers, or output buffering plus gzip fighting each other, produces a response whose declared length doesn't match the body. HTTP/1.1 tolerates it; HTTP/2 doesn't.

  • Check the PHP error log in cPanel → Errors or error_log in the site folder.
  • Disable plugins one by one (or rename wp-content/plugins temporarily) and retest.
  • Look for double compression: PHP's zlib.output_compression = On together with Apache/LiteSpeed gzip. Keep only one.

2. Oversized or duplicate headers

Huge cookies or repeated Set-Cookie and Link headers can break HTTP/2 framing. On Nginx you might also see "upstream sent too big header" in the log. Clear site cookies first. If it's your app, trim what it sets. On Nginx you can raise the buffers:

fastcgi_buffer_size 32k;
fastcgi_buffers 16 16k;
proxy_buffer_size 32k;

3. Cloudflare or a proxy in front

If you recently turned on the orange cloud, test by pausing Cloudflare for the site (or using a grey-cloud DNS record temporarily). If the error disappears, check these:

  • SSL mode should be Full (strict) with a valid certificate on the origin.
  • Disable Rocket Loader and Auto Minify for the failing path as a test.
  • Look for a Cloudflare Transform Rule or Worker that edits response headers.

4. Antivirus or "HTTPS scanning" on the visitor's PC

Some security software intercepts HTTPS and mishandles HTTP/2. If only one person sees the error, ask them to turn off HTTPS scanning briefly, or test from mobile data. Also try an Incognito window with extensions disabled.

5. Server timeouts killing long requests

If the failing request is a big upload, export or slow report, the server may close the connection before it finishes. Check these on your VPS:

SettingWhereTry
Nginx keepalive/timeoutsnginx.confkeepalive_timeout 65; and proxy_read_timeout 120s;
Apache Timeouthttpd.conf / WHM Tweak SettingsRaise from 60 to 120 if needed
PHP limitscPanel → MultiPHP INI Editormax_execution_time, upload_max_filesize
ModSecuritycPanel → ModSecurityCheck the log for rule hits on that URL

6. Apache HTTP/2 module quirks

On older EasyApache 4 builds, mod_http2 combined with the prefork MPM or an outdated Apache version can cause random resets. In WHM, open EasyApache 4, confirm you're on the current profile, and use an MPM that suits HTTP/2 (event with PHP-FPM is the usual choice). As a stopgap, you can disable HTTP/2 only:

# Apache
Protocols http/1.1

# Nginx - remove "http2" from the listen line
listen 443 ssl;

That's a workaround, not a fix. You lose multiplexing, so find the root cause when you can.

Quick diagnosis path

  1. Test with curl --http1.1 vs --http2.
  2. Identify the one failing URL in DevTools.
  3. Request that URL directly with curl -v and read the headers for oddities.
  4. Check the Apache/Nginx error log and PHP error log at the time of failure.
  5. Pause Cloudflare and disable plugins to isolate.
tail -f /var/log/nginx/error.log
tail -f /usr/local/apache/logs/error_log

Prevention

  • Test after every plugin, PHP version or CDN change using Chrome, not just your usual browser.
  • Keep one compression layer only.
  • Keep cookies small and avoid echoing output before headers.
  • Keep EasyApache, Nginx and your SSL certificates updated.

Still stuck? Open a ticket with the exact failing URL and the time you saw the error. With that, we can pull the matching log lines quickly.

Frequently Asked Questions

Is ERR_HTTP2_PROTOCOL_ERROR a problem with my browser?

Rarely. Clearing cookies and trying Incognito are good first checks, but if other devices also see it, the cause is on the server, proxy or CDN side.

Should I just disable HTTP/2?

Only as a temporary workaround to confirm the diagnosis. HTTP/2 gives real speed benefits, so fix the underlying header or output problem and turn it back on.

Why does it happen only on one page?

Because one script or plugin is producing the bad response. Find that URL in the Network tab and investigate it alone.

Can Cloudflare cause this error?

Yes, usually through SSL mode mismatches, header-modifying rules or optimisation features. Pausing Cloudflare for a quick test tells you straight away.

Will clearing cache fix it?

Sometimes, if a bad response was cached. Purge your site cache and CDN cache, but if the error returns, the origin is still sending the broken response.