n8n webhook: how to secure it and accept site data without duplicates
An n8n webhook is open to everyone by default, so lock it: Header Auth or Basic Auth in the node, IP restrictions on the proxy and data validation. Reply to the site immediately, do heavy work after the reply, and give each request a unique ID to protect against repeats.
A webhook in n8n receives data from a website, a form or another service and starts a workflow. If you leave it unprotected, anyone who learns the address can send requests and trigger your automation. Here is the setup, step by step.
Test and production URLs
The Webhook node has two addresses:
- Test URL (
/webhook-test/...) works only while you have pressed “Listen for test event” in the editor. It is for debugging. - Production URL (
/webhook/...) works when the workflow is activated.
A common mistake: a site form points at the test address, and after you close the editor the data stops arriving. On the site always use the production address.
Authentication
The Webhook node has an Authentication setting: Basic Auth, Header Auth or JWT. For requests from a site and from services Header Auth is convenient: you create credentials with a header name (for example X-Webhook-Token) and a long random value. A request without the right header is rejected.
A sample request:
curl -X POST https://n8n.example.com/webhook/lead \
-H "X-Webhook-Token: <secret-token>" \
-H "Content-Type: application/json" \
-d '{"request_id": "7f3c...", "name": "Anna", "contact": "@anna", "msg": "I need a website"}'
Important: never put the secret in page code, because any visitor can see it. A request with the token must come from your server, not from a browser. If the form is public, send it to your own backend, which then calls n8n.
Extra protection on the proxy
n8n usually sits behind nginx. There you can:
- restrict access by IP to the
/webhook/...path (only your server or the sending service); - limit the request rate so a flood cannot take down the workflow;
- limit the body size so you do not accept extra megabytes.
This works independently of the token and stops mass guessing attempts.
How to reply to the site
In the Webhook node you set when to send the reply:
- Immediately: fast, but the reply carries no result. Fits lead forms.
- After the last node: the site waits for the whole processing, and a failure leaves the request hanging.
- With the Respond to Webhook node: you decide where in the workflow to reply and what to return.
A practical rule: reply as early as possible (confirm the request was accepted) and do heavy work (writing to a database, sending messages, calling external APIs) after the reply. That way the site does not depend on the speed of the other systems.
Protection from duplicates and forgery
- Request ID. Send a unique
request_id(for example a UUID). In the workflow first check whether you already processed it, then act. - Data validation. Check required fields and length, and do not trust types: a webhook accepts any JSON.
- Signature. If the sender supports a body signature (HMAC), verify it in a Code node. It is more reliable than a shared token.
- Limited rights. The credentials the workflow uses (database, bot) should have minimum permissions.
A typical flow: a site request into a database and a chat
In our housing catalog project it looks like this: a site form sends data to a webhook, n8n validates it and writes it to PostgreSQL, then publishes it to a Telegram group and returns a reply to the site. More about automating the catalog: Da Nang House. For the publishing scheme see Telegram auto-posting with n8n and PostgreSQL.
What else to check
- n8n updates and editor access: restrict access to the editor and keep credentials only in the credentials section.
- Execution logs. Keep error executions so you can see failed requests.
- Failure alerts. Add a separate workflow that tells you about errors.
If you need help with integrations and automation, see Process automation and Integrations and APIs.
FAQ
Can I leave a webhook without authentication?
Only if the workflow it runs is safe and changes nothing. Anyone who knows the address can call it. Enable authentication for working workflows.
Why did data stop arriving?
Most often the form points at the test address or the workflow is not activated. Check that the Production URL is used and the workflow is on.
How do I avoid duplicates on a repeated send?
Pass a unique request identifier and check it in the workflow before acting, for example by writing it to a table with a unique key.
Do I need HTTPS for a webhook?
Yes. Tokens and user data must not travel over an open channel, and Telegram and many services require HTTPS.
Plain version for AI and reading without styling: Markdown.