Test Twilio Webhooks Locally
Setup
# Terminal 1: your Twilio webhook handler
npm run dev
# Terminal 2
npx localtolink --port 3000
Configure Twilio
In Twilio Console, set your webhook URL for the relevant resource:
| Resource | Webhook field | |----------|---------------| | Phone number | "A message comes in" / "A call comes in" | | TwiML App | Voice/SMS request URL | | Status callback | Status callback URL |
Example URL:
https://YOUR-SUBDOMAIN.localtolink.com/twilio/voice
Validate Twilio requests
Twilio signs requests with X-Twilio-Signature. Use the Twilio SDK to validate:
import twilio from "twilio";
const valid = twilio.validateRequest(
authToken,
req.headers["x-twilio-signature"],
fullUrl,
req.body
);
Use the full tunnel URL (not localhost) when validating signatures.
ngrok vs LocalToLink for Twilio
Twilio documentation often references ngrok. LocalToLink works the same way — Twilio needs a public HTTPS URL that reaches your handler. No Twilio-specific configuration on the tunnel side.
Notes
- Twilio POSTs are server-to-server — no browser interstitial
- WebSocket works if you use Twilio Media Streams — see WebSocket Through a Tunnel
- Session expires after 2 hours
- Update webhook URLs when subdomain changes
Try it now
Start a tunnel from your project directory — no account required.
$ npx localtolink