Skip to main content
AllDevToolsHub
2026-05-23
Last reviewed: Aug 2026
NETWORKING
Est Read: 11_MIN

How to Test WebSocket Connections — 2026 Developer Guide

How to Test WebSocket Connections — 2026 Developer Guide
Processing_Node: 01

#1How to test WebSocket connections

What we tested: We evaluated the tools and techniques described in this article using real developer workflows. All browser-based tools on this site run locally, your data never leaves your machine.

Testing a WebSocket is mostly about checking four things: the handshake, messages in both directions, close behavior, and the auth headers or cookies the client uses.

The test loop is straightforward: inspect the handshake, send a message, confirm the close code, and reproduce the same flow in a tool or script.

#2How WebSockets Actually Work (Two-Minute Recap)

A WebSocket starts life as an HTTP/1.1 request, an Upgrade: websocket header that, if the server accepts, switches the TCP connection from request/response to bidirectional framing. Once the handshake succeeds, the same socket carries discrete frames (text, binary, ping/pong, close) in either direction until one side initiates close.

The handshake request looks like this:

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

The server responds with HTTP 101 Switching Protocols:

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

After that, the wire speaks RFC 6455 frames, not HTTP. This split is why most HTTP-debugging tools (curl, browser address bar) cannot inspect a live WebSocket, by the time it is open, you are looking at framed binary, not text. You need a tool that speaks the protocol.

#2The Four Things Every Test Must Verify

Before reaching for any specific tool, pin down what you are actually trying to confirm:

  1. The handshake completes. The server returns 101, with Sec-WebSocket-Accept properly derived from Sec-WebSocket-Key, and any Sec-WebSocket-Protocol you requested is echoed back.
  2. Messages flow both directions. You can send a text frame and receive one back; binary frames round-trip without corruption; ping/pong heartbeats work if the server uses them.
  3. Close codes are correct. When the server (or client) closes cleanly, the WebSocket close code matches what the spec says it should be, 1000 for normal closure, 1011 for server error, 4xxx for application-level reasons.
  4. Auth and subprotocols negotiate. Whatever scheme you use, Cookies, query-string token, Authorization header via a custom upgrade, or Sec-WebSocket-Protocol-encoded JWT, actually gets to the server and is honored.

Every tool below is good at some subset of these. Match the tool to the question you are trying to answer.

#2Tool 1, Browser DevTools Network Tab

Built into Chrome, Firefox, Edge, and Safari. Best for: debugging a WebSocket from inside the page that opens it.

How to use it:

  1. Open DevTools (F12 or Cmd+Option+I), go to the Network tab.
  2. Filter by WS.
  3. Reload the page. Each WebSocket appears as a row.
  4. Click the row, then the Messages (Chrome) or Response (Firefox) sub-tab to see live frames flowing both directions, colour-coded by sender.
  5. The Headers sub-tab shows the upgrade request/response so you can confirm 101, Sec-WebSocket-Accept, subprotocol echo, and cookies sent.

What it shows well: real production traffic exactly as the browser sees it, including frame payloads, sizes, and timestamps. What it does not show: the close code is sometimes hidden behind a generic "Closed" entry; you may need a custom onclose handler logging event.code and event.reason to see the truth.

Use this when your client-side code already opens the socket and you just need to see what is happening. For testing an endpoint without a client, skip ahead.

#2Tool 2, Browser-Based WebSocket Tester (No Install)

When you want to hit an endpoint without writing any code, the AllDevToolsHub WebSocket Tester is the fastest path.

The flow:

  1. Paste a ws:// or wss:// URL.
  2. (Optional) Add a subprotocol, query-string auth token, or Origin override.
  3. Click Connect. The handshake details appear in the log.
  4. Type a message and click Send. Every inbound frame appears in the log, decoded as text or rendered as a hex dump for binary.
  5. Click Close and watch the close code and reason print, with the canonical RFC 6455 name resolved automatically.

Strengths: zero install, no telemetry (everything runs in your browser tab), full bidirectional messaging, JSON pretty-printing, named close codes. Limitations: cannot set arbitrary HTTP headers (browsers forbid this on new WebSocket()), so for header-based auth you need a Node client. The language-specific guide for Node.js testing covers the workaround.

Use this for: smoke-testing a deployed endpoint, demoing a flow to a teammate, exercising message handlers, and verifying close codes.

#2Tool 3, wscat (Command Line)

wscat is the WebSocket equivalent of curl, a single binary, scriptable, perfect for CI and quick CLI sanity checks.

Install:

bash
npm install -g wscat

Basic connect:

bash
wscat -c wss://echo.websocket.org

With a subprotocol:

bash
wscat -c wss://api.example.com/ws -s "graphql-transport-ws"

With a custom header (most common: auth):

bash
wscat -c wss://api.example.com/ws -H "Authorization: Bearer eyJhbGc..."

Inside the interactive prompt, type a message and press enter to send; inbound frames print as they arrive. Ctrl+C closes cleanly with code 1000.

Use this when: you need to script tests, you need custom headers, you are SSH'd into a server and have no browser, or you want a hands-free repro for a bug report.

#2Tool 4. A Tiny Node.js Client (Full Control)

When wscat is not enough, you need fine-grained header control, binary payloads, reconnect logic, or repeatable assertions, drop into Node:

javascript
import WebSocket from "ws";

const ws = new WebSocket("wss://api.example.com/ws", "graphql-transport-ws", {
  headers: {
    Authorization: `Bearer ${process.env.TOKEN}`,
    Origin: "https://app.example.com",
  },
  perMessageDeflate: true,
});

ws.on("open", () => {
  console.log("✓ connected, subprotocol:", ws.protocol);
  ws.send(JSON.stringify({ type: "connection_init", payload: {} }));
});

ws.on("message", (data, isBinary) => {
  console.log(isBinary ? `<bin ${data.length}B>` : data.toString());
});

ws.on("close", (code, reason) => {
  console.log(`closed: ${code} ${reason.toString() || "(no reason)"}`);
});

ws.on("error", (err) => {
  console.error("error:", err.message);
});

This pattern gives you everything: arbitrary headers, raw binary, ping/pong via ws.ping(), and a place to put assertions for automated tests. The ws library is the de-facto standard server and client implementation in Node.

Use this when: you need scripted CI tests, you are debugging a binary protocol (Protobuf, MessagePack, FlatBuffers over WS), or you are stress-testing reconnect logic with controlled disconnects.

#2Tool 5, Postman, Insomnia, and Friends

Postman added native WebSocket support in 2021; Insomnia followed. Both give you a saved-request UX over WebSockets, with workspaces, environment variables, and collections.

Use these when your team already lives in Postman or Insomnia and you want WebSocket tests sitting next to your REST tests. For a quick one-off, the browser-based tester is faster (no app launch, no auth, no workspace setup).

#2Debugging the Most Common Failures

These are the WebSocket bugs that account for the majority of "it works locally, breaks in staging" tickets.

#31. Handshake returns 200, not 101

The server's HTTP layer answered the request without ever upgrading the connection, usually because the upgrade was stripped at a proxy or load balancer.

Fix: check that the reverse proxy (NGINX, ALB, Cloudflare, Caddy) is configured to forward Upgrade and Connection headers. For NGINX:

nginx
location /ws {
  proxy_pass http://upstream;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_read_timeout 86400;
}

For AWS Application Load Balancer, WebSockets work out of the box but idle timeout defaults to 60 seconds, see the heartbeat section below.

#32. Connection closes with code 1006 (Abnormal Closure)

Close code 1006 means the connection died without a close frame. The wire was simply cut. It is the most common close code in production and the least useful, because it tells you nothing about why.

Likely causes, ranked: idle timeout at a proxy or load balancer; client lost network; server crashed mid-frame; firewall killed the socket; TLS hiccup. Defence: ping/pong heartbeats every 20–30 seconds keep the socket "active" through middleboxes, and an onclose(1006) handler should trigger reconnect with exponential backoff, not surface a real error to the user.

#33. CORS-style failures despite a clean handshake

WebSockets do not use CORS, the upgrade succeeds regardless of Origin. But many servers (Socket.IO, ASP.NET, application gateways) check Origin server-side and reject mismatches with 403 before responding with 101.

Fix: if you see the upgrade request reach the server but the response is 403, log the Origin header on the server side and confirm it matches your allowlist. A common slip is forgetting https:// versus http:// or trailing slashes.

#34. Auth token in query string ends up in logs

A frequent shortcut is wss://api.example.com/ws?token=eyJhbGc.... This works, but the token gets written into every access log of every proxy on the path. The same risk applies to client-side error reporters and any monitoring that captures URLs.

Better patterns: put the token in a cookie (works automatically for same-site), encode it into Sec-WebSocket-Protocol (servers can read it from the handshake), or use a short-lived ticket fetched over HTTPS just before the upgrade. The JWT Claims Reference covers what to put in the payload and how to scope aud for a WebSocket gateway.

#35. The socket reconnects in a tight loop

A common bug pattern: the client treats every close as "retry immediately." That is fine when the network blips for a second, but if the server is rejecting auth, the client hammers it forever.

Fix: check the close code. Codes in the 4000–4999 range are application-defined and almost always mean "do not retry" (auth failed, banned, replaced by newer session). Codes in the 1001, 1006, 1012, 1013 range mean "try again, but back off." A correct reconnect strategy keys off the code, not just the event.

#36. Idle disconnects every 60 seconds on AWS / 30 seconds on Heroku

Most cloud load balancers have idle-connection timeouts. AWS ALB defaults to 60 s, Heroku to 30 s, Cloudflare to 100 s, Azure App Service to ~240 s. If your protocol does not send anything for that interval, the LB kills the socket and your client sees 1006.

Fix: send ping frames (or application-level heartbeats) from the server at half the idle timeout. The ws library has ws.ping(); browsers do not expose ping() but the server-initiated pong is enough to reset the LB timer.

#2A Quick Mental Model: When to Use Which Tool

  • You wrote the page that opens the socket and you want to see what is happening.Browser DevTools Network tab.
  • You have a wss:// URL and want to bang on it for five minutes.Browser WebSocket Tester.
  • You are on a server, in CI, or in a Dockerfile.wscat.
  • You need custom headers, binary payloads, or scripted assertions.Node.js client.
  • Your team lives in Postman or Insomnia already. → use what is already there.

#2Frequently Asked Questions

#3How do I test a WebSocket connection without writing code?

Open the AllDevToolsHub WebSocket Tester, paste your ws:// or wss:// URL, click Connect. You get the full handshake log, send/receive text and binary frames, and see decoded close codes, no install, nothing leaves the browser tab. For endpoints that require custom HTTP headers, you will need wscat or a Node client because the browser WebSocket API does not allow setting headers.

#3What does close code 1006 mean and how do I fix it?

Close code 1006 means "abnormal closure", the WebSocket died without a proper close handshake. The wire was cut without warning. In practice it is almost always one of: an idle timeout at a proxy or load balancer, a transient network failure, a server crash, or a firewall killing the socket. The full list of standard close codes is in the WebSocket Close Codes Reference. Defence is heartbeats every 20–30 seconds plus reconnect logic that backs off exponentially on 1006 instead of retrying immediately.

#3Can I use curl to test a WebSocket?

Only the handshake, not the framed phase. curl -v -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: $(openssl rand -base64 16)" http://example.com/ws will show you whether the server returns 101 Switching Protocols, but the moment the upgrade completes you are looking at framed binary that curl cannot decode. For anything beyond the handshake, use wscat or the browser tester.

#3Why does my WebSocket work in ws:// but break in wss://?

Three usual suspects. (1) TLS termination: the reverse proxy is terminating TLS but forwarding plain HTTP/1.0 without Upgrade, so the upgrade dies at the proxy. (2) Mixed content: a page served from HTTPS cannot open a ws:// socket, browsers block it. (3) Self-signed cert: the browser silently rejects wss:// to a host with a bad certificate, while Node's ws may accept it. Check the network panel for the actual 4xx/5xx, and verify the proxy is forwarding Upgrade and Connection headers verbatim.

#3How do I authenticate a WebSocket connection securely?

In order of preference: (1) cookie-based auth, because cookies attach automatically to the upgrade request and never appear in URLs or logs, best for same-site. (2) Sec-WebSocket-Protocol carrying a token, decoded server-side at the handshake, supported by browsers because the WebSocket API exposes the subprotocols argument. (3) A short-lived ticket: fetch a one-time token over HTTPS, pass it in the query string, the server consumes it on the first message and rejects it for any future connection. Avoid putting long-lived JWTs in the query string, since they end up in access logs across every proxy on the path.


WebSocket testing is one of those skills where the right tool for the job changes every few minutes, a quick connect check in the browser, a scripted assertion in CI, a headers-only repro in wscat. Bookmark the WebSocket Tester for the cases where you just need to see what the server is actually doing, then keep this page next to your terminal for everything else.

Test your endpoint live now at the AllDevToolsHub WebSocket Tester, zero install, no telemetry, decoded close codes. For Node.js-specific assertions and CI patterns, see the Node.js WebSocket testing guide.

Written by Rahul Jalavadiya, founder of AllDevToolsHub. All tools run locally in your browser.

#2Sources / Further reading

#2Try These Tools

Quick Summary

>- A complete, practical guide to testing WebSocket connections in 2026 — from the browser DevTools Network tab and wscat in the terminal to in-browser testers, Node.js clients, and Postman. Covers the handshake, close codes, debugging reconnect logic, auth, and the production gotchas that catch teams in staging.

Key Takeaways

Key Takeaways

  • WebSocket testing requires verifying the full lifecycle: connection handshake, message exchange, ping/pong keepalive, and clean close.
  • Browser-based WebSocket testers are essential for testing ws:// and wss:// endpoints without writing custom client code.
  • Close codes (1000-4999) carry semantic meaning — 1000 is normal closure, 1006 means abnormal closure (network failure), 1011 means server error.
Use Cases

When to use it

  • Testing a real-time chat application's WebSocket connection for message delivery and reconnection behavior.
  • Verifying that a WebSocket server properly handles ping/pong frames and connection timeouts.
  • Debugging why a WebSocket connection drops unexpectedly in production.
Watch out

Common Mistakes

  • Testing WebSockets only in Chrome — Safari and Firefox have different close-code behavior and reconnection timing.
  • Not testing reconnection logic — WebSocket connections drop in production due to network changes, proxies, and load balancers.
  • Ignoring the difference between ws:// and wss:// — production should always use wss:// (TLS), and some proxies strip non-TLS WebSocket traffic.
FAQ

How to Test WebSocket Connections — 2026 Developer Guide, Frequently Asked

How do I test WebSocket connections?

Use a browser-based WebSocket Tester that supports ws:// and wss:// connections. Connect to your endpoint, send test messages, inspect frames, and verify close codes. For automated testing, use libraries like ws (Node.js) or websockets (Python).

What does WebSocket close code 1006 mean?

Close code 1006 means the connection was closed abnormally — no close frame was received. This typically indicates a network failure, proxy timeout, or server crash. It is not sent by either peer; the browser generates it when the connection drops.

RJRahul JalavadiyaFounder & Lead Engineer
Published 2026-05-23Last reviewed 2026-08-23

Tools Mentioned in This Article

Tools, tactics, and toughened-up tips, once a week

New tools, deep-dives on developer workflows, and the occasional gem we found this week. No spam, no tracking. Unsubscribe anytime.

Found an error or have feedback?

We correct errors quickly and document changes in our changelog. Report issues at support@alldevtoolshub.com.

Last reviewed: 2026-08-23
Security Memo
AT

Rahul Jalavadiya

Engineering Protocol V1

Specializing in local-first architecture and Zero-Trust developer workflows. No data leaves the machine.