---
title: "Test Typeform Webhooks Locally | WebhookRelay"
meta:
  "og:description": "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."
  "og:title": "Test Typeform Webhooks Locally"
  description: "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."
---

![Stripes](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/images/stripes.svg)

# **Test Typeform Webhooks Locally**

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.

![Test Typeform Webhooks Locally (Typeform Webhook on localhost)](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/images/blog/heroes/localhost.jpg)

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](#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](https://my.webhookrelay.com/register) 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](#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](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/webhook-bin/) — no signup — and you get an instant public URL.

1. Copy the Webhook Bin URL.
2. Open your form, click **Connect** in the top menu, and open the **Webhooks** tab.
3. Click **Add a webhook** and paste the URL as your endpoint.
4. 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](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/blog/how-to-test-webhooks/) and [What is a webhook](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/blog/what-is-webhook/).

## [Step 2: Forward the events to localhost with the relay agent](#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](https://my.webhookrelay.com/register), 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](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/docs/webhooks/internal/localhost/).

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](#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_response` structure. (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 `answers` array can be `null` with 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](#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](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/hmac-verification/). 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](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/blog/verify-webhook-signature/) and the [HMAC auth docs](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/docs/webhooks/auth/hmac/).

## [Replay and iterate](#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_response` without 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](#get-started)

1. Inspect the real payload in the free [Webhook Bin](https://webhookrelay.com/blog/receive-typeform-webhooks-locally/webhook-bin/) — no signup needed.
2. [Create a Webhook Relay account](https://my.webhookrelay.com/register), install the agent, and run `relay forward --bucket typeform http://localhost:8080/webhook`.
3. 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.