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
wssconnection 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
localhostand sends the response back upstream over the same socket - No account, no dashboard, no npm install in the listener
- One outbound
wssconnection — no inbound port-forwarding - Webhook testing only — no general tunnel, no generic ingress layer
- No npm install in the listener — paste one command and you're live
Operational transparency
Limits and behavior
Third-party service
webhookrelay.app
Cloudflare Worker + DO Local listener
Node 22+, one command localhost
your app
Cloudflare Worker + DO Local listener
Node 22+, one command localhost
your app
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 allcf-*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: 60header. - 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...