DEV Community

LeangDev
LeangDev

Posted on Edited on

How to debug WebSockets without changing your code

If you've worked with WebSockets, you know the pain: something's wrong, and you can't see what's going over the wire.

For browser apps, Chrome DevTools has you covered (Network tab → WS → Messages). But the moment your client is a Node service, a mobile app, a bot, or an IoT device, DevTools can't help. So most of us do this:

ws.on('message', (data) => {
  console.log('IN', data.toString()); // 🙃
  handle(data);
});
Enter fullscreen mode Exit fullscreen mode

It works until you have five connections, binary frames, and a terminal full of JSON.

The proxy approach

A cleaner trick: put a proxy between your client and server. The client connects to the proxy, the proxy connects to the real server, and every frame passes through something that can record and show it.

your app  ──►  proxy (records everything)  ──►  your WebSocket server
Enter fullscreen mode Exit fullscreen mode

Your code doesn't change. Only the URL does.

You can do this with general HTTP tools like mitmproxy, but for wss:// you have to set up a CA certificate and proxy config, and the UI isn't built for message streams. I wanted something I could start in one command, so I built wslog.

Try it in 10 seconds

npx wslog-proxy --demo
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:4000. The --demo flag starts a fake chat server with simulated users, so you'll see traffic right away.

Using it with your own app

npx wslog-proxy
Enter fullscreen mode Exit fullscreen mode
  1. Open http://localhost:4000 and paste the URL your app connects to, e.g. wss://api.example.com/socket
  2. wslog gives you a proxy URL like ws://127.0.0.1:4000/p/3f9a1c2b
  3. Use that URL in your app:
// before
const ws = new WebSocket('wss://api.example.com/socket');

// after (only while debugging)
const ws = new WebSocket('ws://127.0.0.1:4000/p/3f9a1c2b');
Enter fullscreen mode Exit fullscreen mode

Path and query are passed through, so .../p/3f9a1c2b/chat?room=1 reaches wss://api.example.com/socket/chat?room=1. Cookies, Authorization headers and the negotiated subprotocol are forwarded too, so auth keeps working.

Tip: load the URL from an env var (WS_URL) and you can switch between direct and proxied without touching code.

The proxy URL is derived from the target and remembered across restarts, so you only set it up once.

What you get

  • Live table of every frame: time, direction, size, connection, preview. It stays fast with tens of thousands of rows
  • Detail pane with a collapsible JSON tree, raw view, and hex/base64 for binary frames
  • Connections sidebar with status, close codes, and a message-rate sparkline
  • Search and filters by direction, connection, or target, plus export to JSON
  • Multiple servers at once, each with its own proxy URL

Don't leak your tokens

WebSocket traffic is full of secrets. wslog can mask fields before anything is stored:

npx wslog-proxy --mask token,password
Enter fullscreen mode Exit fullscreen mode

Masked values never reach disk, the dashboard, or exports, even inside nested JSON or JSON encoded in a string. Handshake headers like cookies and Authorization are forwarded but never stored. And it only listens on 127.0.0.1 by default.

Share a live view

Debugging with a backend teammate? wslog has a read-only share link (token protected) so they can watch the same traffic live instead of you pasting screenshots into Slack.

Keep the traffic

By default messages stay in memory. To keep a session:

npx wslog-proxy --store ./traffic.db     # SQLite
npx wslog-proxy --store ./traffic.jsonl  # JSON lines
Enter fullscreen mode Exit fullscreen mode

How it compares

wslog Browser DevTools wscat / websocat mitmproxy
Non-browser clients ✅ ❌ ✅ (you are the client) ✅
UI built for WS traffic ✅ ✅ ❌ partial
Search/filter across connections ✅ limited ❌ ✅
Live share with a teammate ✅ ❌ ❌ ❌
Setup one command none none proxy + CA cert

Wrapping up

wslog is MIT licensed, needs Node 22+, and also runs in Docker. It's v0.1 and I'm building it on my own, so feedback means a lot. Issues, ideas, and ⭐ are all welcome:

👉 https://github.com/hoysengleang/wslog

How do you debug WebSockets today? Let me know in the comments.

Top comments (0)