WebToolsPlanet
developer Tools

Webhook Tester

Receive, inspect, and debug incoming webhooks in real-time — see headers, body, query params, and method for any HTTP request sent to your unique endpoint.

Last updated: March 25, 2026

This tool sends data to our server for processing. Data is not stored and is deleted immediately after your result is returned.

Find this tool useful? Support the project to keep it free!

Buy me a coffee

What is Webhook Tester?

A webhook is an HTTP callback: when an event occurs in a third-party service (a payment succeeds in Stripe, a PR is merged in GitHub, a form is submitted in Typeform), that service sends a POST request to a URL you specify — your webhook endpoint. Developing and debugging webhooks is traditionally difficult because the receiving endpoint needs to be a publicly accessible URL — your localhost:3000 isn't reachable from the internet.

The Webhook Tester solves this by providing a unique, publicly addressable temporary URL. Any HTTP request sent to your URL is instantly relayed to your browser over WebSocket and displayed in the log panel with all its details: HTTP method, headers, query parameters, parsed JSON body, and raw body. This eliminates the need to run ngrok, deploy staging servers, or add debug logging just to see what a webhook payload looks like. Services this is commonly used for: Stripe (payment events), GitHub (repository webhooks), Shopify (order/product events), Twilio (SMS status callbacks), HubSpot (CRM webhooks), and Slack (interactive component payloads).

How to Use Webhook Tester

1

A unique webhook endpoint URL is automatically generated when the page loads — copy it with the "Copy URL" button

2

Paste this URL into the webhook configuration of the service you want to test (Stripe Dashboard → Developers → Webhooks, GitHub Repo Settings → Webhooks, etc.)

3

Trigger an event in the service (make a test payment, push a commit, submit a form)

4

Watch the incoming request appear instantly in the log panel — showing method, headers, body, and timestamps

5

Click any logged request to expand it and inspect the full payload, then use "Copy as cURL" to reproduce the request locally

Common Use Cases

  • Testing Stripe payment webhook payloads to understand the exact JSON structure of a "payment_intent.succeeded" event
  • Debugging a GitHub Actions webhook integration — seeing exactly what headers and body shape GitHub sends on a push event
  • Verifying that your own backend sends correctly-formatted webhooks to downstream services during development
  • Inspecting Shopify webhook payloads (new_order, product_update) before writing the handler logic
  • Testing Twilio SMS status callback payloads from twilio.com to understand delivery/failed status fields
  • Sharing a webhook capture with a teammate by copying the URL — both can see incoming requests in real-time
  • Using the "Respond with custom status" feature to test how the sending service handles 2xx vs 4xx vs 5xx responses
  • Capturing a webhook payload to use as a test fixture in unit tests for your webhook handler function

Example Input and Output

Inspecting a Stripe "payment_intent.succeeded" webhook captured by the tester:

Stripe webhook trigger: test payment succeeded
Webhook URL pasted in Stripe:
https://webtoolsplanet.com/api/webhook-tester/abc123xyz

Stripe event triggered:
Test → payment_intent.succeeded
Request shown in webhook tester
Incoming request captured at 14:23:05 UTC

Method: POST
URL: /api/webhook-tester/abc123xyz

Headers:
  Stripe-Signature: t=1706745600,v1=abc123...
  Content-Type: application/json
  User-Agent: Stripe/1.0 (+https://stripe.com/docs/webhooks)

Body (parsed JSON):
{
  "id": "evt_1234",
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_1234",
      "amount": 2000,
      "currency": "usd",
      "status": "succeeded"
    }
  }
}

Privacy Warning

Webhook payloads are received and temporarily held on our servers to relay to your browser — this is necessary for the tool to function. Do not use this tool with production webhooks containing personal data (names, emails, payment info). All payloads are in-memory only with no persistent storage and no logging.

Saving Payloads as Test Fixtures

Use the "Copy JSON" button on each captured request to save the payload as a JSON test fixture file. Use this in your unit tests: const mockPayload = require("./fixtures/stripe-payment-succeeded.json"). This ensures your handler is tested against a real payload shape, not hand-crafted mock data that might miss edge cases in the actual API response structure.

Webhook Retry Behavior

Webhook retry policies vary by provider: Stripe retries failed webhooks (non-2xx) with exponential backoff for up to 3 days. GitHub retries once after 30 minutes. Shopify retries 19 times over 48 hours. Twilio retries up to 3 times. If your webhook endpoint returns 2xx immediately but processes asynchronously, always respond 200 first, then process in a background job — never respond after long processing since the provider may time out and retry unnecessarily.

Frequently Asked Questions

How is this different from ngrok?
ngrok is a tunneling tool: it creates an encrypted tunnel from a public URL to your local machine, so webhooks are forwarded to your localhost server. The Webhook Tester doesn't require tunneling or a running server — it's a hosted receiver that captures and displays requests in your browser. Use ngrok when you need your local application code to process the webhook in real time. Use the Webhook Tester when you just want to see what the payload looks like without writing any handler code first.
Are webhook payloads stored permanently?
No. All received requests are stored in server memory for the session duration only and are automatically purged when your session ends. Each endpoint stores a maximum of the 50 most recent requests. Never send production webhook payloads containing personal data (customer PII, payment card data) to this tool. For production webhook development, use ngrok or a staging environment with proper data handling.
How do I verify the webhook signature in my handler code?
Most webhook providers include a signature header for security — verifying it prevents attackers from sending fake webhooks to your endpoint. Stripe uses Stripe-Signature with HMAC-SHA256. GitHub uses X-Hub-Signature-256. Shopify uses X-Shopify-Hmac-Sha256. The Webhook Tester displays all headers so you can see the exact signature header name and format. For verification code: use the provider's official SDK (stripe.webhooks.constructEvent() in Node.js) or implement HMAC verification with the raw request body.
Can I replay or re-send a captured webhook?
Yes. Click "Copy as cURL" on any captured request to get a cURL command that re-sends the exact same request — same body, same headers. Paste this command in your terminal to replay the webhook against your local handler: curl -X POST http://localhost:3000/webhook -H "Content-Type: application/json" -H "Stripe-Signature: ..." -d '{"type":"payment_intent.succeeded",...}'. This makes captured real payloads reusable as test fixtures during development.
Does this work with webhook services that require HTTPS?
Yes. All Webhook Tester endpoints are served over HTTPS with a valid TLS certificate. Services that require HTTPS (Stripe, PayPal, GitHub) will accept the generated URL. The URL format is: https://webtoolsplanet.com/api/webhook-tester/{unique-id}. TLS certificate validation is handled by our hosting infrastructure, so you don't need to configure any SSL settings.
Can I set a custom response status code for my webhook endpoint?
Yes. Use the "Response Configuration" panel to set a custom HTTP status code (200, 201, 204, 400, 500) and optional response body that your webhook endpoint returns. This lets you test how the sending service handles error responses — for example, Stripe will retry webhooks that receive 5xx responses up to 3 days. Setting a 500 status lets you see the retry behavior without writing any code.

How This Tool Works

When the page loads, a unique endpoint ID is generated and registered on our server. Incoming HTTP requests to the endpoint URL are received by the server and immediately relayed to the browser via a WebSocket connection. The browser renders incoming request objects (method, URL, headers, body) in the log panel in real-time. The server stores up to 50 requests per endpoint in memory for the session. WebSocket disconnection automatically expires the endpoint.

Technical Stack

WebSocket real-time relayHTTPS webhook receiverHeader/body/query parsingServer-side request relay