DEV Community

hao li
hao li

Posted on Originally published at github.com

Stop debugging webhooks blind. I built a tap that shows you the raw bytes.

You're wiring up a Stripe webhook. You click "send test event", your handler 500s — and the logs say nothing useful. Or worse: the provider insists it delivered, but your app swears nothing arrived. Did it even reach your machine? What did the headers actually look like? Was the body the shape you assumed?

I got tired of guessing. So I built webhook-tap: point the callback URL at http://localhost:8901/hook and watch exactly what arrives — method, path, headers, body — in your terminal.

git clone https://github.com/hahahahahahahahah6/webhook-tap
cd webhook-tap
./webhook_tap.py
# webhook-tap listening on http://127.0.0.1:8901/ (Ctrl-C to stop)
Enter fullscreen mode Exit fullscreen mode

When a Stripe-style webhook hits, you see this:

[2026-10-01T07:30:12.441230+00:00] POST /hook
Headers:
  Host: localhost:8901
  Stripe-Signature: [redacted]
  Content-Type: application/json
Body:
  {
    "id": "evt_123",
    "type": "checkout.session.completed"
  }
Enter fullscreen mode Exit fullscreen mode

Details that matter:

  • authorization, cookie, and proxy-authorization headers are always redacted — safe to paste output into Slack or a GitHub issue.
  • Binds 127.0.0.1 only. An open request inspector on a public interface would leak your webhook payloads; if an external service needs to reach it, put an SSH tunnel in front instead.
  • Every request gets a 200 {"ok": true} ack so providers don't retry while you're inspecting.
  • --log-file requests.log appends each request as JSONL for later replay; JSON bodies are pretty-printed; bodies over 64KB are truncated and flagged.

This is not ngrok or a tunnel. Those solve getting traffic to your machine. webhook-tap is the last mile: traffic is already reaching localhost, and you need to see the raw bytes your framework would otherwise swallow. It pairs with any tunnel instead of replacing one — no account, no egress, no third party ever seeing your payloads.

It also works as a library: subclass TapHandler, override record(rec), and capture requests in memory for your test suite.

Stdlib only, Python 3.9+. MIT licensed.

Repo: https://github.com/hahahahahahahahah6/webhook-tap

What's the weirdest thing you've ever caught a webhook provider actually sending vs. what their docs claimed?

Top comments (0)