Stripe Webhook Signature Verification Failed
Quick Answer
The raw request body must be used for signature verification, not the parsed JSON body. Start with "Use raw body for verification" before making broader code changes.
You're in the right place if...
- !Error: webhook signature verification failed
- !Webhooks received but rejected
- !400 errors on webhook endpoint
Why this happens
The raw request body must be used for signature verification, not the parsed JSON body.
Fix
Use raw body for verification
The most common mistake — using parsed JSON instead of raw text:
// WRONG — body is already parsed:
const body = await req.json()
// CORRECT — use raw text:
const body = await req.text()
const event = stripe.webhooks.constructEvent(
body,
req.headers.get('stripe-signature'),
process.env.STRIPE_WEBHOOK_SECRET
)Prevent this next time
Always use req.text() (not req.json()) for the body in webhook handlers. This preserves the exact bytes Stripe signed.
Frequently Asked Questions
Stripe signs the raw bytes. JSON parsing and re-stringifying changes formatting (whitespace, key order), breaking the signature.
Stripe Dashboard → Developers → Webhooks → your endpoint → Signing secret (starts with whsec_).
Related fixes
Weekly Newsletter
Get next week's fix before you need it.
Join developers getting weekly vibe coding tips, error fixes, and tool updates.
Subscribe on Substack →