🔥 LAUNCH SALE — up to +60% bonus traffic · Residential from $0.67/GB · code BACK15 Claim →
Log in Get proxies
PyProxy is back — buy residential, ISP, mobile & datacenter proxies directly, from $0.67/GB. Launch bonus up to +60%.
Guide · WebSocket vs HTTP

What is the difference between WebSocket and HTTP?

One is a conversation where the client always speaks first and the server answers. The other is an open line where either side talks whenever it likes. Everything else — the handshake, the proxy requirements, the way IP rotation behaves — follows from that one difference.

The short answer

HTTP is a request-response protocol: the client asks, the server answers, and the exchange is finished. WebSocket is a persistent, full-duplex connection: once it is open, either side can send a message at any moment without being asked. They are not competitors so much as different shapes. A WebSocket connection even begins its life as an HTTP request — which is the detail that decides whether it survives a proxy, a load balancer or a corporate firewall.

HTTP: one request, one answer

Every HTTP exchange is initiated by the client. The server has no way to speak first. Keep-alive lets several requests reuse the same TCP connection, and HTTP/2 multiplexes them onto one, but the shape never changes: everything the server sends is a response to something the client asked for.

That constraint is what makes HTTP easy to operate. Requests are independent, so any server in a pool can handle any of them; responses can be cached by a CDN; a failed request can simply be retried. It is also why real-time features feel awkward on HTTP. To learn that a new chat message exists, the client has to ask again, and asking repeatedly is polling: a request every few seconds, each one carrying a full set of headers and cookies, most of them returning nothing new.

Long polling improves on that by holding the request open until there is something to say, and Server-Sent Events gives you a proper one-way stream from server to client over plain HTTP. Both are worth knowing. Neither gives the client a cheap way to send upward.

WebSocket: one connection, both directions

A WebSocket is a single TCP connection that stays open for as long as both sides want it, carrying discrete messages in either direction. There are no headers per message and no cookies per message; the framing overhead is a handful of bytes. There is no request the server is answering, so the server can push the moment it has something.

The cost is state. Every open socket is memory and a file descriptor on your server, and because the connection is long-lived it is pinned to one backend instance for its whole life, which makes deploys and scaling more interesting than they are with stateless requests. You also have to write the parts HTTP gave you for free: reconnection, heartbeats, resuming after a gap, and deciding what happens to messages sent while the client was away.

ws:// is the plaintext scheme and wss:// is the same thing inside TLS, normally on port 443. Use wss:// in practice; it is not just about privacy, it is the form most likely to pass through intermediaries untouched.

The handshake: every WebSocket starts as HTTP

A client opens a WebSocket by sending an ordinary HTTP/1.1 GET with upgrade headers:

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://example.com

If the server agrees, it answers with status 101 and proves it understood the handshake by hashing the key with a fixed GUID:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

After that 101, nothing further on that connection is HTTP. The same socket now carries WebSocket frames. This is why the handshake is the fragile part: any intermediary in the path that only understands request-response — an old forward proxy, a filtering appliance, a load balancer that has not been told about upgrades — will drop, buffer or strip the upgrade and your connection will die at exactly this point, usually with a confusing error about an unexpected response code.

Choosing between them

 HTTPWebSocket
Who speaks firstAlways the clientEither side, at any time
Connection lifeShort; reused at bestMinutes to hours
Per-message costFull headers and cookiesA few bytes of framing
Caching and CDNNativeNone
Server stateStateless, any instancePinned to one instance
Natural fitPages, APIs, downloads, scrapingChat, live prices, multiplayer, collaborative editing, dashboards

The practical rule: if the client always knows when it wants something, use HTTP. If the server knows things the client has no way to predict, and delay matters, use WebSocket. If updates only ever flow one way, from server to client, Server-Sent Events sits neatly between the two and keeps all of HTTP's operational simplicity.

WebSocket through a proxy: CONNECT is not optional

Because the handshake is HTTP, it is tempting to assume any HTTP proxy will carry a WebSocket. It will not. A forward proxy in its ordinary mode parses each request, makes its own request upstream and returns the response — it never hands the socket over, which is precisely what a WebSocket needs after the 101. Worse, Connection is a hop-by-hop header, so a strict proxy is entitled to strip the very header that requests the upgrade.

The mechanism that does work is CONNECT tunnelling. The client asks the proxy for a raw pipe to the destination, and after the proxy answers, bytes pass through in both directions untouched:

CONNECT example.com:443 HTTP/1.1
Host: example.com:443
Proxy-Authorization: Basic dXNlcjpwYXNz

HTTP/1.1 200 Connection established

With wss:// the TLS handshake happens inside that tunnel, and the WebSocket upgrade happens inside the TLS session, so the proxy sees nothing but encrypted bytes and has no opportunity to mangle anything. This is why a proxy that supports CONNECT carries WebSocket traffic perfectly well while one that does not fails immediately.

Most client libraries handle it for you once you point them at the proxy. In Python:

# pip install websocket-client
import websocket

ws = websocket.WebSocket()
ws.connect(
    "wss://echo.websocket.events",
    http_proxy_host="gw.pyproxy.com",
    http_proxy_port=1111,
    http_proxy_auth=("USERNAME-country-us", "PASSWORD"),
    proxy_type="http",
)
ws.send("hello through the tunnel")
print(ws.recv())
ws.close()

The Node equivalent passes an agent to the ws client, which performs the same CONNECT before the upgrade:

// npm i ws https-proxy-agent
import WebSocket from "ws";
import { HttpsProxyAgent } from "https-proxy-agent";

const agent = new HttpsProxyAgent(
  "http://USERNAME-country-us:PASSWORD@gw.pyproxy.com:1111"
);
const ws = new WebSocket("wss://echo.websocket.events", { agent });

ws.on("open", () => ws.send("hello through the tunnel"));
ws.on("message", (m) => console.log(m.toString()));

Two things are worth checking before you blame your code. First, whether the proxy allows CONNECT to the port you need — many allow 443 and refuse everything else, which breaks a WebSocket service on a non-standard port. Second, whether your library actually routes WebSocket traffic through the proxy at all; several popular clients ignore HTTP_PROXY environment variables and need the proxy passed explicitly, as above.

Rotation behaves differently on a long-lived connection

This is the part that surprises people who move from scraping pages to streaming data. With a rotating gateway, the exit address is chosen when the connection is established. A short HTTP request opens a connection, uses it and closes it, so the next request can quite reasonably come from a different address — that is what rotation means.

A WebSocket connects once and stays. Rotation does not reach inside an established connection and move it; nothing exists that could migrate a live TCP session to a different exit without breaking it. So for as long as your socket is up, your traffic leaves from the same address. Rotation only takes effect the next time you connect.

Which is exactly where the problem hides. Sockets drop — a network blip, an idle timeout, a server deploy — and your client reconnects. That reconnect is a new connection, so it lands on a new exit address. If the service you are talking to ties its session to the client's IP, it will see someone else arriving with your token, and you get an unexplained re-authentication or a hard disconnect loop that only ever happens after a drop.

The fix is to pin the exit for the whole time you need it. On a gateway that takes options in the username, a session token holds one address for about thirty minutes:

curl -x http://USERNAME-country-us-session-feed01:PASSWORD@gw.pyproxy.com:1111 \
     https://httpbin.org/ip

Use the same credentials for the WebSocket client and your reconnects stay on the same address for that window. Beyond it, plan for the address to change: keep the reconnect logic idempotent, re-send your authentication after every reconnect rather than assuming the server still knows you, and never build a design that depends on the client IP staying constant for hours. Note also that billing is by traffic, not by connection time, so an idle socket costs you almost nothing — only the heartbeat frames and whatever data actually flows.

PyProxy residential starts at $0.67/GB with traffic that never expires. Link Telegram to a new account and the first gigabyte is free — no card, no deposit.
See proxy plans Get 1 GB free

Questions people ask

Is a WebSocket just an HTTP connection held open?

No. It begins as an HTTP request carrying an Upgrade header, but once the server answers 101 Switching Protocols the connection stops speaking HTTP entirely and starts exchanging WebSocket frames in both directions. Only the first few hundred bytes on the wire are HTTP.

Does WebSocket work through an HTTP proxy?

Yes, provided the proxy supports CONNECT tunnelling. The client sends CONNECT host:443, the proxy opens a raw pipe, and the TLS handshake and the WebSocket upgrade both happen inside that tunnel. A proxy that only rewrites ordinary requests, or one that blocks CONNECT to non-443 ports, will break the connection at the upgrade.

Will a rotating proxy change my IP in the middle of a WebSocket session?

No. The exit address is chosen when the connection is established and is held for the life of that connection. Rotation applies to new connections, so a reconnect after a drop normally lands on a different address unless you pin one with a session token, which holds a single exit for about thirty minutes.

When should I use HTTP instead of WebSocket?

Whenever the client asks and the server answers: page loads, REST calls, file downloads, scraping. HTTP is cacheable, stateless and trivial to scale and retry. Reach for WebSocket only when the server needs to push data the client did not ask for, or when message latency matters more than simplicity.