See every webhook. Replay any of them. Pay once.
Self-hosted webhook capture and debugging. Create a bin, point any webhook at its URL, and watch every request land in a live dashboard — headers, body, query, source IP, everything. Replay any capture against your real endpoint, or forward everything automatically. Your data never leaves your server, and your capture URLs never expire.
- Bins — named capture endpoints with unique slugs.
ANY /in/<slug>and every subpath accept every HTTP method and any content type. Bodies up to a configurable cap (default 1 MB, truncated beyond with a flag — never rejected). - Full capture — method, path, query params, headers, raw body, parsed body (JSON pretty-printed with syntax highlighting, form-urlencoded decoded), source IP, content type, size, timestamp.
- Configurable responses — per bin: status code, body, content type, and an optional response delay for timeout testing. Default
200 {"ok":true}. - Live inspector — request list updates every 2 seconds (plain polling, no websockets). Detail tabs: Headers / Body raw / Body pretty / Query. Filter by method or search body/path substrings.
- Copy as curl — reproduce any captured request from your terminal, with correct single-quote escaping.
- Replay — send any captured request to any target URL, preserving method, headers, and body (hop-by-hop headers stripped, content-length recomputed). Target's response shown inline; full replay history per request.
- Forwarding — set a target URL per bin and every new capture is immediately forwarded; the result (status or error) is recorded on the request row. No automatic retry — forwarding is fire-once by design to keep behavior predictable. Replay manually if a forward fails.
- Retention — per-bin ring buffer (default keeps the 500 newest requests) plus a global max-age (default 7 days, hourly cleanup).
- CLI-friendly — clean JSON API, curl-able capture URLs, session cookie login from the terminal (see below).
- 100% local — SQLite storage, no telemetry, no external services.
npm i
npm run build # build the dashboard
npm start # http://localhost:5321 (default password: admin)Then create a bin in the dashboard and point a webhook at it:
curl -X POST http://localhost:5321/in/<slug>/anything?src=test \
-H "Content-Type: application/json" \
-d '{"event":"order.created","amount":1999}'npm run desktopBoots the same server on a free local port with data in your user profile, opens a window, auto-logged-in. (npm run dist packages a Windows installer.)
docker compose up -d
# or: PORT=5321 ADMIN_PASSWORD=change-me node server/index.jsThe SQLite database lives in a Docker volume (/data). Set ADMIN_PASSWORD before exposing it.
Log in and keep the session cookie:
curl -s -c cookies.txt -X POST http://localhost:5321/api/login \
-H "Content-Type: application/json" -d '{"password":"admin"}'Tail the newest requests in a bin every 2 seconds:
watch -n 2 'curl -s -b cookies.txt "http://localhost:5321/api/bins/1/requests?limit=5" | jq ".[].path"'Create a bin from the CLI:
curl -s -b cookies.txt -X POST http://localhost:5321/api/bins \
-H "Content-Type: application/json" -d '{"name":"stripe-dev"}'| Endpoint | Description |
|---|---|
ANY /in/:slug, ANY /in/:slug/* |
Public capture (any method, any body) |
POST /api/login, POST /api/logout, GET /api/health |
Auth + health |
GET|POST /api/bins, GET|PUT|DELETE /api/bins/:id |
Bin CRUD |
DELETE /api/bins/:id/requests |
Clear a bin |
GET /api/bins/:id/requests?after=&limit=&method=&q= |
List/poll captures |
GET /api/requests/:id, GET /api/requests/:id/curl |
Detail + copy-as-curl |
POST /api/requests/:id/replay, GET /api/requests/:id/replays |
Replay + history |
| Hookscope | Webhook.site | Pipedream RequestBin | Beeceptor | |
|---|---|---|---|---|
| Price | $24 once | €9/mo Pro (~$120/yr) | $29+/mo (account required) | $10–$99/mo |
| URLs expire | Never | Free URLs expire | Tied to account | Rate-limited free tier |
| Data location | Your server | Their cloud | Their cloud | Their cloud |
| Replay requests | ✅ | Pro only | ✅ | Paid |
| Auto-forwarding | ✅ | Pro (CustomActions) | Via workflows | Paid rules |
| Request cap | Your disk | 100 (free) | Tiered | Tiered |
| Self-hosted | ✅ | ❌ | ❌ | ❌ |
Webhook.site Pro pays for Hookscope in under 3 months.
Don't want to touch a terminal? Grab the packaged installer (Windows, one click, auto-updates):
→ Get Hookscope on Whop — pay once, own it forever. No subscription.
- Server: Node 20+, Express, better-sqlite3 (WAL)
- UI: React 18, Vite, Tailwind CSS v4, Framer Motion, Lucide icons
- Desktop: Electron wrapper around the same server (dual native bindings vendored by
scripts/setup-native.js) - Zero external services — everything runs in one process
See .env.example: PORT, ADMIN_PASSWORD, DB_PATH, MAX_BODY_KB, RETENTION_DAYS.
Notes:
- Replay/forward targets must be
http://orhttps://; forwarding a bin to this server's own/in/URL is refused (loop guard). - Forward/replay requests time out after 15 s.
npm run dev # Vite dev server on :5322, proxying /api and /in to :5321
npm start # API server
npm test # smoke test (spawns its own server on :5393, temp DB)MIT © 2026 Ben (bensblueprints)
