OSS · MIT · No account required

Relay webhooks to localhost in under 5 seconds.

For webhook testing only. No general tunnel, no inbound networking setup. Pick an app, paste the public URL into your third-party service, run one listener command—traffic relays in memory, no server-side archive.

How it works

  • Your third-party service posts to a public HTTPS webhook URL — TLS terminates at Cloudflare
  • One outbound wss connection from your machine — no inbound port-forwarding required
  • Webhook payload forwarded in memory — no server-side archive or replay store in the app code
  • Your listener fetches localhost and sends the response back upstream over the same socket
  • No account, no dashboard, no npm install in the listener
Default sort Rolling 7 day popularity
Local runtime Node 22+ only, no extra packages
Live cards -

Operational transparency

Limits and behavior

All facts are grounded in the open source code — inspect src/lib/protocol.ts, RelaySession.ts, and src/lib/http.ts directly.

Max webhook body
512 KiB per inbound request. Larger payloads are rejected before reaching the relay.
Local response timeout
25 s per delivery. If your local app does not respond in time, the relay returns 504 to the webhook sender.
No listener connected
Returns 503 to the webhook sender. Start the listener command first, then trigger the webhook.
Listener disconnect mid-flight
Any in-flight webhook deliveries fail immediately with 503. Reconnect and retry.
Logging
No request bodies are logged in app code. Errors log a request ID and message only. Cloudflare account-level edge observability is a separate platform setting — review your CF dashboard.
Storage
Rolling 7-day popularity counts per app only. No webhook payload data is ever written to Durable Object storage.
Request headers
Most provider headers forwarded to localhost. Always stripped: host, content-length, accept-encoding, upgrade, hop-by-hop headers, and all cf-* headers.
Leaked or rotated sessions
Treat /h/… like a secret. Create a new session to get a fresh URL. Rotating the operator signing key (RELAY_SIGNING_KEY) invalidates all existing hook IDs.
Rate limits
Independent per-PoP limits on global traffic, per client IP, and per hook URL. Exceeding any returns 429 with a Retry-After: 60 header.
TLS and transport
TLS terminates at Cloudflare. The relay holds a signed hook ID in the URL path — no persistent session token needed for inbound webhooks.

Loading app catalog...

Step 1

Webhook URL

Copy and paste this webhook URL into your third-party app. We’ll move you to step 2 after a short beat so you have time to paste it.

Step 2

Confirm local port and URL

Make sure this matches the route your app is listening on before you start Terminal A.

Step 3

Terminal A · Listener command

Run this in Terminal A after you confirm the local URL. We’ll move you to step 4 as soon as the relay connects.

Waiting for Terminal A Stop listening later with Ctrl+C in Terminal A.

Optional thin CLI

Prefer a checked-in file over the pasted blob? Download it from this site with `curl`, inspect it on GitHub, then run it with the same live relay URL.

Step 4

Terminal B · `curl` smoke test

Run this in Terminal B after Terminal A is listening. You should get HTTP 200 with a short JSON summary: success if your app handled the route, or a clear message if nothing is reachable or the path 404s. Copy-paste commands are listed one per line under nextSteps (not a single string with \n escapes).