Test Typeform Webhooks Locally (Typeform Webhook on localhost)
Test Typeform webhooks locally on localhost without deploying. Add the webhook in the Typeform UI, inspect the real form_response payload, and verify the signature.
You are building a Typeform integration — piping survey answers into your database, triggering a follow-up email, creating a lead in your CRM — and you need to see your handler react to a real form submission. The problem is immediate: Typeform will only POST to a public URL, and your handler is running on localhost:8080. Typeform has no way to reach it.
The usual workarounds are painful. Deploying to a staging server for every code change is slow. Pasting the sample payload from the docs into curl gives you a guess at the real request, not the real headers and body Typeform actually sends. What you want is to test Typeform webhooks locally — real form_response events, hitting your local handler, with a URL that does not change every time you restart.
This guide shows how to do exactly that.
Why testing Typeform webhooks locally is tricky
A webhook is just an HTTP request that Typeform sends to a URL when someone submits a form. Typeform sits on the public internet; your dev machine usually does not. It is behind a router, a corporate firewall, or both, with no public IP and no inbound ports open.
So you need something in the middle: a public endpoint Typeform can hit, that relays each request down to your laptop without you opening a single firewall port. That is what Webhook Relay does — and unlike a random tunnel URL, the endpoint is stable, so you configure Typeform once and never touch it again.
Step 1: Inspect the real payload with Webhook Bin
Before you write any handler code, find out what Typeform actually sends. Open the free Webhook Bin — no signup — and you get an instant public URL.
- Copy the Webhook Bin URL.
- Open your form, click Connect in the top menu, and open the Webhooks tab.
- Click Add a webhook and paste the URL as your endpoint.
- Click View deliveries, then Send test request to fire a sample payload, or just submit the form yourself.
Inspect the captured request in Webhook Bin: the full JSON body, the query string, and every header. Typeform wraps each submission in an event_type of form_response and a form_response object containing the form_id, a unique token, submitted_at / landed_at timestamps, hidden fields, the form definition (the questions), and the answers array. Test deliveries are flagged so you can tell them apart from real submissions.
Now you know the exact shape of the data before writing a line of code. For more on this approach, see How to test webhooks and What is a webhook.
Step 2: Forward the events to localhost with the relay agent
Once you know the payload, route those same events into your local handler. Sign up for Webhook Relay, install the relay agent (CLI or Docker), and create a bucket — say typeform. The bucket gives you a stable public input endpoint.
Start forwarding to your local server:
relay forward --bucket typeform http://localhost:8080/webhook
The agent opens an outbound connection to Webhook Relay and streams every incoming request down to http://localhost:8080/webhook. Because the connection is outbound, there are no firewall ports to open and no public IP needed — this works from your laptop, behind a corporate proxy, or inside a Kubernetes cluster. Running in Docker? The same command works in the official webhookrelay/webhookrelayd image. Full details are in the localhost forwarding docs.
Now update the Typeform webhook's endpoint to your Webhook Relay URL (or just create it there from the start), and click View deliveries → Send test request. Watch it arrive on localhost.
Typeform-specific configuration and quirks
A few Typeform details worth knowing:
- Where to add it: webhooks are configured per form under Connect → Webhooks, or programmatically via the Webhooks API. There is no account-wide webhook — each form has its own.
- Fixed payload: the JSON shape is fixed. You cannot add, remove, or reshape fields before delivery, so plan your handler around the standard
form_responsestructure. (If you need a different shape, transform it in Webhook Relay or your handler.) - Partial submissions: if someone lands on the form but does not finish, the
answersarray can benullwith no hidden fields or score — handle that case. - Test request: the View deliveries panel has a Send test request button. Keep your webhook toggled On to redeliver. All test deliveries are clearly marked as tests.
- Secret: add a secret via the Edit option to enable signed requests.
Step 3: Verify the Typeform webhook signature
If you set a secret on the webhook, Typeform signs each request. It computes an HMAC-SHA256 over the raw request body using your secret, base64-encodes the result, and sends it in the Typeform-Signature header prefixed with sha256=. Your handler should recompute the HMAC over the raw body, base64-encode it, prepend sha256=, and compare in constant time before trusting the payload.
One gotcha trips up almost everyone: you must hash the exact raw bytes Typeform sent. Re-serializing the JSON after parsing it changes whitespace and breaks the comparison, so capture the body before any JSON middleware touches it.
To sanity-check your implementation, paste a captured body, your secret, and the received signature into the free HMAC signature verifier. For language-specific code and the common pitfalls (reading the body after a JSON parser has consumed it, timing-safe comparison), read Verify a webhook signature and the HMAC auth docs.
Replay and iterate
This is where local development gets fast:
- Replay from Typeform via View deliveries → Send test request to re-fire a delivery against your handler.
- Replay from Webhook Relay — past requests are stored on your bucket, so you can resend a captured
form_responsewithout touching Typeform at all. - Iterate on your handler by editing code and replaying the same delivery until it behaves correctly. No commits, no pushes, no deploys just to test a code path.
Because the Webhook Relay endpoint is stable, you can stop and restart the agent, reboot your machine, or come back next week — the Typeform configuration never needs to change.
Get started
- Inspect the real payload in the free Webhook Bin — no signup needed.
- Create a Webhook Relay account, install the agent, and run
relay forward --bucket typeform http://localhost:8080/webhook. - Point your Typeform webhook at the stable endpoint, send a test request, and watch it hit
localhost.
You will be testing real Typeform submissions against your local handler in a few minutes — no deploys, no open firewall ports, and a URL you configure exactly once.
