websocat: socat for WebSockets When curl Won't Cut It

2026-06-27

WebSockets are everywhere — trading feeds, IoT brokers, GraphQL subscriptions, the dashboard you hate poking at. curl doesn't speak WS. The usual reflex is npm install -g wscat: drag in a Node runtime, lose all your pipe-fu, write a throwaway script. Vitaly Shukela's websocat is a single Rust binary that behaves like socat for WebSockets — it reads stdin, writes stdout, bridges sockets, speaks both ws:// and wss://, and slots cleanly into shell pipelines.

Install with cargo install websocat, brew install websocat, or grab a static binary from the GitHub releases page.

The interactive smoke test. Confirm a service is even reachable, send a payload, read the response:

$ websocat wss://ws.example.com/feed
> {"op":"subscribe","channel":"ticker.BTCUSD"}
< {"ts":1719500000,"px":68421.5,"sz":0.01}
< {"ts":1719500001,"px":68421.7,"sz":0.05}

One-shot for scripts. -1 exits after one reply; -n suppresses the trailing newline so the server gets your bytes exactly:

$ echo '{"op":"ping"}' | websocat -1n wss://api/ws | jq .latency_ms
3

Pipe a live stream into your favorite text tools. Output is line-delimited stdout, so every Unix instinct works:

$ websocat wss://stream.example.com/trades \
    | jq -c 'select(.size > 100)' \
    | ts '[%Y-%m-%d %H:%M:%.S]' \
    | tee trades.log

Authentication is just headers. No SDK required:

$ websocat -H="Authorization: Bearer $TOKEN" \
           -H="X-Org: acme" \
           wss://api/graphql

Bridge TCP to WebSocket. Got a legacy tool that only speaks raw TCP and a service that only exposes WS? Splice them together:

# Local TCP port 9000 → remote WebSocket
$ websocat -E tcp-l:127.0.0.1:9000 wss://api.example.com/socket
# Now point any TCP client at localhost:9000

Bridge the other direction. Expose a Redis, SMTP, or SSH service through a WebSocket — handy for in-browser admin consoles and demos:

$ websocat -E ws-l:0.0.0.0:8080 tcp:localhost:6379

Reconnect-on-drop for flaky links. The autoreconnect: overlay reopens the socket with backoff; --ping-interval keeps middleboxes from killing an idle connection:

$ websocat --ping-interval 20 \
    autoreconnect:wss://stream.example.com/feed \
    | gron --stream > ticks.jsonl

Stand up a test server in one command. Echo by default, or wire it to anything else:

# Echo server on :8080
$ websocat -s 8080

# Hand every connecting client to a script
$ websocat -E ws-l:0.0.0.0:8080 exec:./handler.sh

The mental model is exactly socat: a left address, a right address, optional overlays in between. Once that clicks, every WebSocket job — debugging, smoke testing, bridging, recording, fuzzing — collapses into a one-liner.

Key Takeaway: websocat turns WebSockets into a first-class Unix citizen — pipe in, pipe out, bridge to TCP, and never write a throwaway Node script for a five-second test again.

All newsletters