Self-hosted service
vi/websocat avatar
vi/websocat

websocat: a netcat-style CLI for WebSockets, and when it fits

Command-line client for WebSockets, like netcat (or curl) for ws:// with advanced socat-like functions

8,702 stars328 forksRustMIT

At a glance

What is it?
websocat is a Rust command-line tool that connects WebSocket endpoints to stdin, stdout, files, TCP sockets and other processes. Its value is in the address syntax and overlays; the 4.x rewrite is still in alpha, so most users should stay on the 1.x line.
Who is it for?
Adopt websocat if you debug WebSocket endpoints from a shell, bridge ws:// to TCP, or need a one-line WebSocket server; use a language-level client library instead if you need typed protocols, reconnect state machines inside an application, or a stable v4 API.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 49 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What websocat is for, and who ends up using it

The README opens by describing websocat as netcat, curl and socat for WebSockets. That sentence is the whole product: a single binary that speaks ws:// and wss:// on one side and something ordinary on the other. The ordinary side can be your terminal, a TCP port, a UNIX socket, a file, or the stdin and stdout of another program.

The people who get value from it are not usually writing application code. They are checking whether a WebSocket endpoint responds, piping a JSON-RPC frame into a browser debugging port, or exposing an SSH daemon through a WebSocket listener because a proxy in the middle only forwards HTTP upgrade traffic. The README's own example opens a Chromium tab by sending Page.navigate over the DevTools WebSocket, which is a fair sample of the tool's natural habitat: shell one-liners against something that only speaks WebSocket.

If your job is to build a chat client with reconnect logic, message queues and typed payloads, websocat is the wrong layer. It moves bytes. It does not model your protocol.

Address types and overlays: how the two-sided model works

In advanced mode websocat takes two addresses, <addr1> and <addr2>, and shuttles data between them, the way socat does. The README's help output shows the three invocation shapes: a single ws:// or wss:// URL for a simple client, -s port for a simple server, and the two-address form for everything else.

Addresses carry a type prefix. The examples in the README use ws-l:127.0.0.1:1234 for a WebSocket listener, tcp:127.0.0.1:22 for a TCP client, tcp-l:127.0.0.1:1236 for a TCP listener, and broadcast:mirror: for a fan-out address that copies every message to all connected clients. Overlays are flags that modify that pipeline, for example -b for binary mode, -t for text mode, --oneshot to stop after the first connection, -n1 to exit after one message, and --jsonrpc with --jsonrpc-omit-jsonrpc to treat lines as JSON-RPC calls.

The design consequence is that websocat is a wiring tool, not a framework. You compose behaviour out of address types and flags, and the README points to doc.md for the complete list of address types and overlays. That list is the real documentation surface; the README only samples it.

Installing websocat on Linux, macOS and Windows

The README orders installation options from easy to hard. On FreeBSD the package is available directly. On macOS there are two package managers. On Debian and Ubuntu the README says websocat is not officially packaged, so you download a pre-built executable from GitHub releases, though older versions may have Debian package files attached there. Pre-built binaries for Linux (usual and musl), Windows, OS X and Android live on the releases page.

On macOS, Homebrew and MacPorts both carry it:

bash
brew install websocat
sudo port install websocat

On Debian or Ubuntu, download the binary from the releases page and put it on your PATH. If you prefer building, install the Rust toolchain first, then use cargo:

bash
cargo install websocat

The README warns that if a -sys crate fails during that build, retrying with --no-default-features is the suggested workaround. Building from a checkout is the same story with an explicit release profile:

bash
cargo build --release

The resulting executable lands under target/, typically target/release/websocat. There is also a container image referenced in the README's echo-server example:

bash
docker run --rm -ti ghcr.io/vi/websocat:nightly wss://ws.vi-server.org/mirror

Note the tag: the image in that example is nightly, not a pinned release. If you need reproducibility, build from source at a tagged version instead.

A first real session: echo server, then your own listener

The quickest check that the binary works is the public echo server in the README. Type a line, press Enter, and the same line comes back; Ctrl+d quits.

bash
websocat ws://ws.vi-server.org/mirror

Running your own server is barely harder. The README shows a two-terminal example: one process listens, the other connects. The listener prints nothing until a client arrives, then relays whatever each side types.

bash
websocat -s 1234

In the second terminal, connect to it and exchange a couple of lines:

bash
websocat ws://127.0.0.1:1234/

The README's transcript shows ABC and 123 travelling in both directions. That is the entire mental model: two streams, one of them wrapped in the WebSocket framing. Everything else in the tool is a variation on choosing what the other stream is.

Bridging TCP and WebSocket, and where the seams show

The proxy example is the most useful non-trivial one in the README, because it solves a real deployment problem: a service that only accepts WebSocket connections, and a client that only speaks raw TCP. Two websocat processes sit back to back. The first listens for WebSocket and forwards to a TCP port; the second listens on TCP and forwards to that WebSocket listener.

bash
websocat --oneshot -b ws-l:127.0.0.1:1234 tcp:127.0.0.1:22 &
websocat --oneshot -b tcp-l:127.0.0.1:1236 ws://127.0.0.1:1234/ &
nc 127.0.0.1 1236

The README's transcript is honest about the outcome: the SSH banner arrives, a password line is typed, and the server answers Protocol mismatch. That is not a websocat bug. It is the seam between a byte stream and a message-oriented protocol. --oneshot and -b are doing the heavy lifting here, and the example shows why you cannot treat a WebSocket as a transparent TCP tunnel without thinking about framing.

The broadcast address has a similar honesty in the README. The example works, but the text adds that if you like it, you may actually want wsbroad instead. That is a maintainer telling you the built-in fan-out is a demonstration, not a product.

Limits, version confusion and the Rust toolchain constraint

The most concrete limitation is the version split. Cargo.toml in the repository declares version 1.14.1, and the README calls v1 the current stable version. The releases list also carries v4.0.0-alpha2 and v4.0.0-alpha3, described as previews of Websocat 4. So a user following a blog post that mentions v4 syntax may be running something materially different from the stable line. The README does not document a rollback path between them.

Building v1 from source has its own constraint. The README states that Websocat v1 may fail to support too new a Rust compiler because of old dependencies, and it publishes a table of minimal and maximal Rust versions per release. For 1.9 to 1.11 the minimum is 1.46 and the maximum is maybe 1.63; for 1.6 to 1.8 the minimum is 1.34. Building with legacy Rust may require copying Cargo.lock.legacy to Cargo.lock first. The README also notes that old versions may misbehave if built by Rust 1.48 or later, and that building v1.x with Rust 1.64 may expose previously hidden undefined behaviour in legacy dependencies, though it adds that in practice it seems to just work.

On Android, wss:// may fail. The README's workaround is to download a certificate bundle and point SSL_CERT_FILE at it, or to use --insecure. Neither is a happy default for production.

Finally, the Debian packaging metadata in Cargo.toml lists depends = "libssl1.1, libc6 (>= 2.19), libgcc1 (>= 1:4.9.0)". libssl1.1 is not present on newer distributions, which is consistent with the README's statement that websocat is not officially packaged for Debian.

websocat against socat and a language client library

The obvious comparison is socat, and the README names it in the first line. socat is a general-purpose relay for TCP, UDP, UNIX sockets, PTYs, files and more, with a mature address vocabulary and no WebSocket support. websocat borrows the two-address shape but adds ws:// and wss:// as first-class address types, plus WebSocket-specific overlays such as --jsonrpc, --compress-deflate, --compress-gzip and --compress-zlib. If your problem has no WebSocket in it, socat is the more general tool and has been for far longer. If the problem is specifically bridging WebSocket to something else, socat cannot do it without an external bridge.

The other alternative is a WebSocket client library in your own language, for example the websocket crate that websocat itself depends on. That gives you typed messages, control over the event loop, and integration with your application's error handling. What it does not give you is a binary you can drop into a shell pipeline, a Docker entrypoint, or an nginx integration via TCP or UNIX sockets. The README lists that nginx integration and inetd mode as features, and those are the cases where a library is simply the wrong shape.

Maintenance, upgrade cost and licence

The repository is not archived, and the last push was on 2026-08-13. The releases show two parallel lines: v1.14.1, labelled a maintenance release, and the v4.0.0 alphas. The README's Rust version table tells you what upgrading costs on the build side, and the note that v1 depends on old crates means the stable line is not a moving target you can casually rebuild on the newest compiler.

The licence is MIT, declared both in the repository and in Cargo.toml. That is permissive and imposes no source-disclosure obligation on your own code. It says nothing about the licences of the crates websocat links against, and the Debian metadata's runtime dependency on libssl1.1 means a redistributed binary may pull in OpenSSL obligations you should check separately. That is a packaging question, not a legal opinion.

Upgrade risk concentrates in the v1-to-v4 move. Nothing in the README describes a migration guide, so treat the alpha line as a separate tool until the project documents otherwise.

Editorial conclusion

Adopt websocat if you debug WebSocket endpoints from a shell, bridge ws:// to TCP, or need a one-line WebSocket server; use a language-level client library instead if you need typed protocols, reconnect state machines inside an application, or a stable v4 API. Before rolling it into scripts, verify which version you are installing (1.14.1 stable versus the 4.0.0 alphas), check the Rust version table in the README if you build from source, and confirm that the address types you need are listed in doc.md. The MIT licence is permissive, but the Debian metadata in Cargo.toml lists runtime dependencies such as libssl1.1, so check your distro's OpenSSL before packaging.

Frequently asked questions

How do I install websocat?

On FreeBSD use pkg install websocat; on macOS use brew install websocat or sudo port install websocat. On Debian and Ubuntu the README says it is not officially packaged, so download a pre-built binary from the GitHub releases page or run cargo install websocat.

How do I use websocat to connect to a WebSocket?

Run websocat followed by the ws:// or wss:// URL, for example websocat ws://ws.vi-server.org/mirror. Lines you type go out as messages and replies are printed; Ctrl+d quits.

What is the difference between websocat and socat?

Both take two addresses and relay data between them, but websocat adds ws:// and wss:// address types and WebSocket-specific overlays such as --jsonrpc and the compression flags. socat covers more non-WebSocket transports and has no built-in WebSocket support.

How do I install websocat on Windows?

The README lists pre-built binaries for Windows on the GitHub releases page. There is no Windows package manager command documented in the README.

How do I install websocat on Ubuntu?

The README states that websocat is not yet officially packaged for Debian, and Ubuntu is not listed as having a package either. The documented route is to download a pre-built executable from the GitHub releases page, or to build it with cargo install websocat.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. vi/websocat on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vi-websocat.svg)](https://hysenlabs.com/projects/vi-websocat)