Problem
Chrome fails to load a page with ERR_SPDY_PROTOCOL_ERROR. The same site works in Firefox, or on your phone, or in an incognito window — but this Chrome, on this page, keeps dying. And the error names a protocol, SPDY, that Chrome stopped supporting a decade ago, which makes it read like a message from a ghost.
It isn’t a ghost. It’s HTTP/2 wearing an old name.
Symptoms
- Chrome shows
ERR_SPDY_PROTOCOL_ERROR; the page is blank or half-rendered. - The same URL loads in Firefox or Safari, or in Chrome on another machine or network.
- It sometimes clears after a cache flush or a browser restart, then comes back.
- On some setups it’s intermittent — most pages on the site load, one endpoint reliably fails.
What This Error Actually Means
SPDY was an experimental protocol Google built to speed up HTTP. Most of it was folded into HTTP/2, which the IETF standardized as RFC 7540 in May 2015 (now updated by RFC 9113). Google removed SPDY from Chrome in version 51 in May 2016 — exactly one year after HTTP/2 shipped. But Chrome’s network stack never renamed the internals; the code that now speaks HTTP/2 still carries SPDY-derived labels, so a failure in an HTTP/2 session surfaces as ERR_SPDY_PROTOCOL_ERROR. For practical purposes it’s the same thing as ERR_HTTP2_PROTOCOL_ERROR: Chrome and the server agreed to speak HTTP/2, and then the conversation broke down.
The reason this matters for diagnosis is that HTTP/2 is far stricter than HTTP/1.1. HTTP/1.1 is a text protocol that tolerates a lot of sloppiness — odd whitespace, unusual characters in a header, casing quirks. HTTP/2 is binary and rigorous: RFC 9113 §8.2 requires header field names to be lowercase and forbids invalid octets in fields, and a violation is a connection error, not a warning. So a response header that limped through for years over HTTP/1.1 can make Chrome tear down the entire HTTP/2 connection the moment the site is served over HTTP/2. That’s why “works in an old browser, breaks in Chrome” is such a strong clue: Chrome is enforcing the rules the header was quietly breaking.
Top 3 Causes
- The server sends a header HTTP/2 rejects - A malformed or non-compliant response header — an invalid character, an uppercase field name, a bad byte injected by an application framework or a custom module — is legal-ish under HTTP/1.1 and fatal under HTTP/2. Chrome aborts the stream. This is the classic cause of a specific endpoint failing while the rest of the site works: only the response with the bad header breaks.
- A middlebox rewrites or mangles the traffic - VPNs, corporate proxies, and TLS-inspecting antivirus (“HTTPS scanning,” “Web Shield”) decrypt and re-encrypt your HTTPS, and in doing so can corrupt HTTP/2 framing or downgrade the connection badly. The tell is a failure that follows the network or the machine with the security software, not the site.
- Stale local state in Chrome - A wedged socket or a corrupted cache entry can leave Chrome’s HTTP/2 state for one origin in a bad spot. This is the one that “fixes itself” after a restart or a cache clear — and the one worth ruling out first because it costs nothing.
Diagnose with DechoNet
- HTTP Check reads the raw response headers from outside your browser and network. If a header is malformed or a field is non-compliant, this is where you’ll see it — and a clean external fetch that Chrome still can’t load points the finger squarely at your local network or profile.
- SSL Check confirms the certificate and TLS handshake are healthy, so you can rule the crypto layer out.
ERR_SPDY_PROTOCOL_ERRORis an HTTP/2 transport failure, not a certificate error — but a TLS-inspecting middlebox breaks both at once, and this helps you spot one. - Port Check verifies 443 is open and the server is reachable, separating a real connectivity problem from a protocol-specific one.
Resolution Checklist
- Rule out local state first: open
chrome://net-internals/#sockets, click Flush socket pools, then clear cached data and reload. Free, and it fixes the “stale socket” case. - Test in an incognito window with extensions disabled, or a fresh profile. If it works there, an extension or cached data was the cause.
- Test a different network and, if you can, a machine without TLS-inspecting antivirus or a VPN. If the error tracks the network or that software, a middlebox is mangling HTTP/2.
- Run HTTP Check on the failing URL and inspect the response headers for anything malformed — invalid characters, uppercase field names, duplicated or oversized fields.
- If you run the server: look at the exact endpoint that fails and the headers it emits. Fix the non-compliant header at the source. As a temporary measure you can disable HTTP/2 at the origin or CDN to force HTTP/1.1, which makes the error vanish while you find the bad header — but that’s a workaround, not the fix.
When to Escalate
- If HTTP Check shows a clean, compliant response over TCP but Chrome still fails, and the problem follows one network, escalate to the network team: a proxy or inspection appliance is breaking HTTP/2, and the durable fix is there, not on every desktop.
- If the failure is confined to one endpoint served through your CDN, escalate to the CDN or the application team — a response header emitted on that route violates HTTP/2 and needs correcting at the origin.
- Disabling HTTP/2 to make the error disappear hides a header your server should not be sending. Find and fix the header rather than living on HTTP/1.1 to avoid it.
Check your own domain now
Free, no sign-up. Runs the exact check this guide describes and shows what to fix.