Twilio webhook local testing lets you receive SMS replies, voice callbacks, and messaging status updates on your local machine. Twilio sends webhooks as HTTP POST requests with form-encoded payloads—your localhost needs a public HTTPS URL to receive them during development.
Why Twilio callbacks require a public URL
When someone sends an SMS to your Twilio number or completes a voice call, Twilio POSTs the event data to your configured webhook URL. Local addresses like http://localhost:3000/sms are unreachable from Twilio's infrastructure. A localhost tunnel bridges that gap with a public HTTPS endpoint.
Twilio webhook types to test locally
- SMS inbound: when a user sends a text message to your Twilio number.
- SMS status callbacks: delivery confirmations (sent, delivered, failed).
- Voice callbacks: TwiML requests when a call connects or enters a menu.
- WhatsApp messaging: inbound and status webhooks for WhatsApp Business API.
- Conversations API: message added and participant events.
Step-by-step: Twilio webhook local testing
- Start your local app with Twilio webhook routes (for example
/sms/inbound). - Run
npx portpreview 3000to generate a public HTTPS URL. - In the Twilio Console, set your phone number's webhook URL to the tunnel URL plus your route path.
- Configure the HTTP method (usually POST) and ensure the content type matches your handler.
- Send a test SMS or make a test call to trigger the webhook.
- Inspect the captured request—Twilio sends form-encoded payloads, not JSON.
- Verify your handler validates the Twilio signature and returns valid TwiML or a 2xx response.
Validate Twilio request signatures locally
Twilio signs every request with an X-Twilio-Signature header computed from the full URL and POST parameters using your auth token. Your handler should:
- Use the exact public URL (including the tunnel hostname) for signature validation.
- Pass all POST parameters to the validation function.
- Reject requests with invalid signatures, even during local testing.
When your tunnel URL changes between sessions, update both the Twilio Console webhook URL and your validation URL accordingly.
Twilio-specific debugging tips
Form-encoded payloads
Unlike Stripe or GitHub, Twilio sends application/x-www-form-urlencoded data. Ensure your handler parses form bodies correctly, not just JSON.
TwiML responses
Voice and SMS handlers must return valid TwiML XML. Test response formatting locally before Twilio marks deliveries as failed.
Timeout behavior
Twilio expects responses within 15 seconds for most webhooks. Slow handlers cause retries and duplicate deliveries—use webhook replay to test retry handling.
Status callback chains
SMS workflows often chain inbound webhooks with status callbacks. Test both endpoints locally by configuring separate tunnel routes or paths.
Twilio local testing vs Twilio CLI
The Twilio CLI can simulate inbound requests with twilio phone-numbers:update and local tunnel plugins. A dedicated localhost tunnel with request capture gives you persistent visibility into every callback, replay capability, and a workflow that scales across multiple providers—not just Twilio.
For general webhook debugging patterns, read how to debug webhooks locally.
Join the PortPreview waitlist for Twilio and multi-provider webhook testing from one tunnel.
