How to Test WebSocket Connections With curl and Other Tools

A practical guide to testing WebSocket connections, covering curl's experimental ws support, websocat, and GUI tools, with real command examples.

INEZA Felin-Michel

INEZA Felin-Michel

22 May 2026

How to Test WebSocket Connections With curl and Other Tools

Apidog for Enterprise

On-Premises Deploy

SSO & RBAC

SOC 2 Compliant

Explore Apidog Enterprise

WebSocket gives you a persistent, two-way channel between client and server over a single TCP connection. Once the connection is open, either side can send a message at any time, which is what makes it the backbone of live chat, trading feeds, multiplayer games, and dashboards. Testing it is a different exercise from testing a request-response API, because there is no single response to inspect. There is a stream.

This guide is practical. It covers what curl can and cannot do with WebSocket, how to use the dedicated tool websocat, and when a GUI client is the better choice. Every command here is real and copy-ready.

Why WebSocket testing is not like REST testing

A REST test is a transaction. You send one request, you get one response, you assert on it, you are done. A WebSocket test is a conversation. You open a connection once, then exchange many messages over its lifetime, and messages can arrive unprompted.

That changes what you check. You confirm the connection upgrades correctly from HTTP. You confirm the server accepts your first message and replies as expected. You confirm that server-pushed messages arrive without you asking. You watch how the connection closes, and with what close code. A tool built for one-shot requests struggles with all of this, which is why curl, the universal HTTP tool, is only a partial fit. For the wider testing picture, the difference between a test scenario and a test case maps neatly onto a WebSocket conversation versus a single message check.

The WebSocket handshake

Every WebSocket connection starts as an HTTP request that asks to be upgraded. The client sends Upgrade: websocket and Connection: Upgrade headers plus a Sec-WebSocket-Key, and the server answers with HTTP 101 Switching Protocols. After that, the connection is no longer HTTP. It speaks the WebSocket frame protocol defined in RFC 6455.

This is the root of curl’s limitation. Classic curl speaks HTTP. It can send the upgrade headers, but it cannot frame and unframe WebSocket messages after the handshake. Trying to fake a full WebSocket session with raw header flags does not work past the handshake itself. You need a tool that understands frames.

Testing WebSocket with curl

Modern curl, version 7.86 and later, added experimental native WebSocket support. It is genuinely usable for simple checks, with the caveat that it is still marked experimental.

First confirm your version:

curl --version

If you are on 7.86 or newer, you can connect to a WebSocket endpoint directly. Here is a connection to a public echo server, which replies with whatever you send:

curl --include --no-buffer \
  --header "Connection: Upgrade" \
  --header "Upgrade: websocket" \
  --header "Sec-WebSocket-Version: 13" \
  --header "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  https://echo.websocket.org

The --include flag shows the response headers so you can confirm the 101 status, and --no-buffer stops curl from holding output back, which matters for a stream. For secure connections, use a wss:// URL exactly as you would https://.

curl’s WebSocket support shines for one thing: confirming an endpoint is reachable and completes the upgrade. It is awkward for an interactive session where you send several messages and read replies, because curl is not built around a message loop. For a quick “is this endpoint alive” check in a script, it is fine. For real interactive testing, reach for a dedicated tool. If you are scripting these checks into a pipeline, our guide on automating API tests in CI/CD covers wiring command-line checks into a build.

Testing WebSocket with websocat

websocat is the command-line tool most people actually want for WebSocket work. It is purpose-built, understands frames properly, and behaves like a netcat for WebSocket.

Install it with your package manager, for example brew install websocat on macOS or via cargo install websocat. Then connecting and chatting is one command:

websocat wss://echo.websocket.org

That opens an interactive session. Type a line, press enter, and it is sent as a message. The server’s replies print as they arrive. To send a single message and exit, pipe it in:

echo '{"action":"subscribe","channel":"prices"}' | websocat wss://stream.example.com/feed

websocat also handles useful extras. You can pass headers for authenticated endpoints:

websocat --header "Authorization: Bearer your-token-here" wss://api.example.com/socket

And you can run it as a local server to test a client, or bridge a WebSocket to a plain TCP port. For command-line WebSocket testing, websocat covers almost everything curl cannot. Treat assertions the same way you would elsewhere; our notes on writing useful API assertions apply to checking message payloads too.

Testing WebSocket with a GUI tool

Command-line tools are great for scripts and quick checks. They are tiring for exploratory testing, where you want to see the message timeline, send structured JSON comfortably, and keep a connection open while you poke at it.

Apidog has a dedicated WebSocket client built for this. You enter a ws:// or wss:// URL, connect, and see every sent and received message in a timeline view with JSON syntax highlighting. You can save connections, set headers and query parameters for authentication, and keep the connection live while you experiment. It handles REST, GraphQL, and SOAP in the same application, so WebSocket testing sits alongside the rest of your API work rather than in a separate tool. Download Apidog to test WebSocket endpoints with a visual timeline.

A GUI is the right call when you are exploring an unfamiliar WebSocket API, debugging why messages are not arriving, or sharing a reproducible test with a teammate. The command line is the right call when you want the check to run unattended. Most engineers use both, picking by task. If you want a broader view of GUI options, our roundup of free online API testing tools includes several that handle WebSocket.

A simple WebSocket test checklist

  1. Confirm the upgrade. The connection should return HTTP 101. If it does not, the endpoint, the path, or your headers are wrong.
  2. Check authentication. Many WebSocket servers expect a token in a header or query parameter. A connection that opens then immediately closes often means a rejected token.
  3. Send a known message and verify the reply. Use a real payload your API understands and confirm the response shape.
  4. Verify server-pushed messages. Subscribe to a channel and confirm that updates arrive without further requests from you.
  5. Test the close. Close the connection and check the close code. A clean close is 1000; other codes signal specific problems.
  6. Test failure paths. Send a malformed message and confirm the server responds sensibly rather than dropping silently.

For organizing these into a repeatable set, our guide on building API test suites applies to WebSocket flows as much as to REST.

Debugging a WebSocket connection that will not work

When a WebSocket connection fails, the cause is almost always one of a small set of problems. Work through them in order.

Start with the URL scheme. A connection to wss:// from a page or context that expects ws://, or the reverse, fails immediately. Browsers also block a ws:// connection from a page served over HTTPS, since that mixes secure and insecure content. Confirm the scheme matches the environment.

Next, check the handshake response. If you do not see HTTP 101, the server never agreed to upgrade. A 404 means the path is wrong. A 401 or 403 means authentication failed before the upgrade. A 400 often means a missing or malformed upgrade header. curl’s --include flag and websocat’s verbose mode both show you this response, so you can tell a handshake failure from a later problem.

If the handshake succeeds but the connection drops seconds later, look at idle timeouts and ping or pong frames. Many servers expect the client to answer ping frames to prove it is still alive, and they close connections that go quiet. A proxy or load balancer in front of the server can also kill idle connections on its own schedule. Finally, read the close code. The codes are defined in RFC 6455, and a code like 1006 points to an abnormal closure with no clean handshake, while 1011 signals a server error. The close code usually tells you which side gave up and why.

Automating WebSocket checks

A one-off manual test confirms an endpoint works today. It does not protect you from a regression next week. For that, the WebSocket check has to run unattended.

The command-line tools make this straightforward. A small script can open a connection with websocat, send a known message, capture the reply, and compare it to an expected value, then exit non-zero if it does not match. That script drops into a CI pipeline like any other test step. A GUI tool with a scenario runner, such as Apidog, can save a WebSocket flow, including the messages sent and the assertions on the replies, and replay it on a schedule or from a pipeline trigger.

Keep automated WebSocket tests focused. Assert the connection upgrades, assert one known request and response pair, and assert that a subscribed channel delivers at least one pushed message within a timeout. Trying to assert on every possible message of a long-lived connection makes a test slow and flaky. The same restraint that keeps a test case sharp keeps a WebSocket check reliable: test one clear thing, and test it well.

Frequently asked questions

Can curl test WebSocket connections?

Partly. curl 7.86 and later has experimental native WebSocket support that can complete the handshake and exchange basic messages, which is enough to confirm an endpoint is reachable. It is awkward for interactive sessions with many messages. For real WebSocket testing, websocat or a GUI client like Apidog is a better fit.

What is the difference between ws and wss?

ws:// is an unencrypted WebSocket connection, and wss:// is encrypted with TLS, the WebSocket equivalent of HTTP versus HTTPS. Always use wss:// for anything beyond local development, since ws:// sends messages in plain text. Tools treat the two URLs identically apart from the encryption.

Why does my WebSocket connection open and then immediately close?

The most common cause is authentication. If the server expects a token in a header or query parameter and does not get a valid one, it accepts the TCP connection and then closes it. Check the close code, verify your token, and confirm you are sending it the way the server expects.

Is websocat better than curl for WebSocket testing?

For WebSocket specifically, yes. websocat is purpose-built, understands the frame protocol fully, supports interactive sessions, custom headers, and piping messages in and out. curl is a general HTTP tool whose WebSocket support is still experimental. Use curl for a quick reachability check and websocat for actual testing.

How do I test that a server pushes messages without a request?

Open the connection, subscribe to the relevant channel or event if the API requires it, then wait and watch. With websocat the pushed messages print as they arrive. With a GUI client like Apidog they appear in the message timeline. Confirm the messages arrive without any further input from you, since unsolicited delivery is the point of WebSocket.

Practice API Design-first in Apidog

Discover an easier way to build and use APIs

How to Test WebSocket Connections With curl and Other Tools