WebSocket and gRPC through proxies: protocol upgrade, CONNECT, and debugging long-lived connections
Sound familiar? REST requests through a corporate or cloud proxy fly by without a hitch, but as soon as you open a WebSocket or call a gRPC method, the connection either never establishes or lives for about thirty seconds and then silently dies. Meanwhile, in the browser or app logs you see mysterious 101, 502, 504, or just a sudden connection reset. This isn't mysticism or karma. It's a fundamental difference between how a proxy handles short request-response transactions and how it must behave with long-lived bidirectional streams.
This article is an exhaustive guide to how protocols living on top of TCP—WebSocket, gRPC, and everything that requires a protocol upgrade or an end-to-end tunnel—get through proxies. We'll break down the mechanics down to the last header, show the difference between ws:// through an HTTP proxy and wss:// via the CONNECT method, explain why SOCKS5 is often simpler, what to do with gRPC over HTTP/2, how to beat idle timeouts, and, most importantly, how to debug all of it when nothing works. At the end—working code in Python and Node, checklists, and FAQ.
One quick scope note: we intentionally won't touch the mechanics of UDP ASSOCIATE in SOCKS5 here—that's a whole separate conversation about datagrams, and it has its own dedicated article. Here we focus exclusively on TCP protocols over HTTP and SOCKS.