← All articles

test stripe webhooks locally

How to Test Stripe Webhooks Locally

Stripe CLI is the right first tool for local Stripe webhook development. A temporary tunnel helps when the webhook belongs to a live local demo.

Published May 2, 2026 5 min read
In this article

To test stripe webhooks locally, use Stripe CLI first. It forwards sandbox events to your local webhook route, gives you the signing secret for local verification, and can trigger common test events from your terminal.

A localhost tunnel still has a place. Use it when you need to show the full payment flow to a reviewer while Stripe sends callbacks into the local app. That review context needs a browser link, a webhook route, and clear failure signals.

Test stripe webhooks locally with Stripe CLI

Start your app and make sure the webhook route accepts POST requests. For example, your local route might be:

http://localhost:4242/webhook

Then run Stripe CLI:

stripe listen --forward-to localhost:4242/webhook

Stripe prints a webhook signing secret. Use that value in your local environment for signature verification:

STRIPE_WEBHOOK_SECRET=whsec_test_value npm run dev

Trigger a test event:

stripe trigger payment_intent.succeeded

If the handler returns a success status, Stripe CLI shows the local delivery. If the handler fails, fix the route before you involve a browser demo or external reviewer.

Build the handler around Stripe’s rules

Stripe webhook handlers need a few details that ordinary JSON API routes can miss.

First, preserve the raw request body for signature verification. Stripe signs the raw payload. If your framework parses and rewrites the body before verification, the signature check can fail.

Second, return a 2xx response before slow work. Stripe’s docs recommend returning a success status before complex processing that could time out. Put fulfillment, email, or sync work into a queue when the work can outlive the request.

Third, handle duplicate events. Stripe may deliver the same event more than once, so store processed event IDs or use the event type plus object ID when needed.

Fourth, do not assume order. Stripe does not guarantee event ordering. Retrieve missing objects from the API when your state machine needs the current object.

Filter the events you need

Forwarding every event creates noise. Stripe CLI lets you filter to the event types your handler supports:

stripe listen \
  --events payment_intent.succeeded,checkout.session.completed,payment_intent.payment_failed \
  --forward-to localhost:4242/webhook

This keeps local logs readable and helps you catch routes that subscribe to too much. In production, Stripe also recommends listening only to event types your integration needs.

When a localhost tunnel helps

Stripe CLI is the best first tool for local Stripe handler work. A tunnel helps when Stripe webhooks are part of a live local product flow.

Consider a client review where you need to show checkout, redirect handling, and a local admin state update. The reviewer opens a browser link. You run through the checkout. Stripe sends the webhook. You need to see whether the callback reached the local app and whether the UI changed.

Start wiremaven for the app server:

npx wiremaven-cli 3000 --expires 30m --name stripe-demo

Then use the generated public URL for the visible app review. If your app exposes the webhook path on the same server, you can register the temporary URL in a Stripe sandbox endpoint for the review window:

https://example.wiremaven.dev/webhook

Use this with care. It is a temporary public endpoint, so keep the route in sandbox mode, verify signatures, and remove or let the endpoint expire after the review.

wiremaven’s value here is session visibility. It shows live viewer, request, and failure signals during the walkthrough. The link uses a time-boxed TTL, and reviewers do not need an account during beta.

Stripe CLI vs. tunnel

JobUse Stripe CLIUse a tunnel
Build the handlerYesOptional
Get local signing secretYesNo
Trigger test eventsYesNo
Show full local app to reviewerNoYes
Test callback over public HTTPS URLSometimesYes
See browser reviewer stateNoDepends on tool, yes in wiremaven

For most developers, the answer is both at different stages. Use Stripe CLI while you build. Use a temporary tunnel when the webhook must participate in a visible local review.

Common local failures

  • Your route accepts GET but not POST.
  • Your framework consumes the raw body before signature verification.
  • Your handler returns a redirect.
  • The handler takes too long before returning 2xx.
  • The signing secret comes from the wrong endpoint.
  • You test live mode behavior with sandbox credentials or the reverse.

Stripe’s delivery view and CLI output help with provider-side status. A local tunnel with request signals helps with review-side status when someone opens the app through a temporary link.

FAQ

Do I need ngrok to test Stripe webhooks locally?

No. Stripe CLI can forward sandbox events to a local endpoint without ngrok. A tunnel helps when you need a public HTTPS URL for a broader local demo.

Can Stripe send webhooks to localhost directly?

No. Stripe cannot reach localhost on your machine from the internet. Stripe CLI bridges sandbox events to localhost, and a tunnel can expose a temporary public route.

Why does Stripe signature verification fail locally?

The common cause is body parsing before verification. Stripe requires the raw request body plus the Stripe-Signature header and endpoint secret.

Should I register a temporary tunnel URL in Stripe?

Only for sandbox testing or a scoped review. Keep the endpoint temporary, verify signatures, and remove the endpoint when the session ends if you registered it in the dashboard.

Start with CLI, then add review visibility

Build the handler with Stripe CLI:

stripe listen --forward-to localhost:4242/webhook

When the full local app needs a review link, use wiremaven:

npx wiremaven-cli 3000 --expires 30m --name stripe-demo

Read the wiremaven docs, review how wiremaven works, and compare the broader tradeoffs in webhook proxy vs. localhost tunnel.


Related: Webhook Proxy vs. Localhost Tunnel | 7 ngrok Alternatives for Developers in 2026