WhatsApp has over 2 billion users worldwide. If your business communicates with leads over WhatsApp, you're probably doing it manually — reading messages, copying contact details into a spreadsheet, and hoping nothing falls through the cracks.
In this tutorial, I'll show you how to build a fully open-source, self-hosted lead capture bot that automatically collects lead information from WhatsApp conversations and stores it in your CRM or database. No paid APIs, no vendor lock-in.
We'll use two tools:
- WAHA — an unofficial, open-source WhatsApp API (not affiliated with or endorsed by Meta/WhatsApp). It wraps WhatsApp Web into a REST API.
- n8n — an open-source workflow automation platform you can self-host.
Disclaimer: WAHA is an unofficial, third-party tool that interacts with WhatsApp Web. It is not endorsed by, affiliated with, or supported by Meta or WhatsApp. Using unofficial APIs may violate WhatsApp's Terms of Service. Use at your own risk and evaluate your compliance requirements before deploying in production.
Architecture Overview
Here's the full data flow:
User sends WhatsApp message
│
▼
┌─────────┐
│ WAHA │ (WhatsApp Web wrapper, self-hosted)
└────┬────┘
│ Webhook POST
▼
┌─────────┐
│ n8n │ (Workflow engine, self-hosted)
└────┬────┘
│ Processes message, extracts lead data
▼
┌──────────────┐
│ CRM/Database │ (Supabase, PostgreSQL, Google Sheets, etc.)
└──────────────┘
Each component is self-hosted on your own infrastructure. You own the data end-to-end.
Prerequisites
- A VPS or local machine with Docker installed
- Basic familiarity with REST APIs and JSON
- A spare phone number for WhatsApp (don't use your personal number for development)
Step 1: Deploy WAHA with Docker
WAHA runs as a Docker container. Start it with:
docker run -d \
--name waha \
-p 3000:3000 \
-e WHATSAPP_DEFAULT_ENGINE=WEBJS \
-e WAHA_DASHBOARD_ENABLED=true \
devlikeapro/waha
Once running, open http://your-server:3000/dashboard to scan the QR code with your WhatsApp and authenticate the session.
Reminder: WAHA is unofficial software. It reverse-engineers WhatsApp Web. This is not a Meta-approved integration method.
Step 2: Configure the Webhook
WAHA can send incoming messages to any webhook URL. We'll point it to our n8n instance.
Use the WAHA API to set the webhook:
curl -X PUT http://localhost:3000/api/session/default \
-H "Content-Type: application/json" \
-d '{
"config": {
"webhooks": [
{
"url": "https://your-n8n-domain.com/webhook/whatsapp-lead",
"events": ["message"]
}
]
}
}'
When someone sends a message, WAHA will POST a payload like this to your n8n webhook:
{
"event": "message",
"session": "default",
"payload": {
"id": "true_972501234567@c.us_3EB0A608C4A3",
"timestamp": 1710500000,
"from": "972501234567@c.us",
"body": "Hi, I'm interested in your automation services",
"hasMedia": false
}
}
The from field contains the phone number. The body field contains the message text. That's all we need to start capturing leads.
Step 3: Build the n8n Workflow
In n8n, create a new workflow with the following nodes:
Node 1: Webhook (Trigger)
- Type: Webhook
- HTTP Method: POST
-
Path:
whatsapp-lead
This is the entry point. Every incoming WhatsApp message hits this node.
Node 2: Filter (IF Node)
We only want to capture new leads, not every message. Add a filter:
-
Condition:
{{ $json.payload.body }}contains keywords like "interested", "pricing", "demo", "info"
This prevents the bot from treating every casual message as a lead. Adjust the keywords to fit your business.
Node 3: Extract Lead Data (Set Node)
Parse the payload into clean lead fields:
{
"phone": "{{ $json.payload.from.replace('@c.us', '') }}",
"message": "{{ $json.payload.body }}",
"source": "whatsapp",
"captured_at": "{{ $now.toISO() }}"
}
Node 4: Save to Database
Connect to your database or CRM. Here are common options:
PostgreSQL / Supabase:
INSERT INTO leads (phone, message, source, captured_at)
VALUES ($1, $2, $3, $4)
ON CONFLICT (phone) DO UPDATE SET
last_message = $2,
updated_at = $4;
Google Sheets: Use n8n's built-in Google Sheets node to append a row.
HTTP Request (any CRM API): POST the lead data to HubSpot, Pipedrive, or any CRM with a REST API.
Node 5: Auto-Reply (HTTP Request)
Send an automatic acknowledgment back through WAHA:
curl -X POST http://localhost:3000/api/sendText \
-H "Content-Type: application/json" \
-d '{
"session": "default",
"chatId": "972501234567@c.us",
"text": "Thanks for reaching out! We received your message and will get back to you shortly."
}'
In n8n, this is an HTTP Request node:
- Method: POST
-
URL:
http://waha:3000/api/sendText -
Body: JSON with
session,chatId(from the incoming payload), andtext
The Complete Workflow
Your n8n workflow should now look like this:
Webhook → IF (keyword filter) → Set (extract data) → DB Insert
→ HTTP Request (auto-reply)
The DB Insert and auto-reply nodes can run in parallel — use n8n's split output to trigger both simultaneously.
Handling Edge Cases
A few things to consider for production:
-
Duplicate messages: WAHA may occasionally deliver the same message twice. Use the message
idfield as a deduplication key in your database. - Rate limiting: WhatsApp may flag accounts that send too many messages too quickly. Keep auto-replies minimal and add delays if needed.
-
Session persistence: WAHA sessions can expire. Mount a Docker volume (
-v waha_data:/app/store) to persist session data across container restarts. -
Media messages: If
hasMediais true, you'll need to call WAHA's media download endpoint separately. For lead capture, text messages are usually sufficient.
Security Considerations
Since you're self-hosting everything:
- Put WAHA behind a reverse proxy (Nginx/Traefik) with HTTPS
- Use n8n's built-in authentication for the webhook (Header Auth or Basic Auth)
- Never expose WAHA's API port directly to the internet without authentication
- Store lead data in compliance with your local privacy regulations
Why Self-Host?
Using open-source, self-hosted tools like n8n and WAHA means:
- No per-message fees — unlike the official WhatsApp Business API, which charges per conversation
- Full data ownership — lead data never passes through a third-party SaaS
- Customizable — modify the workflow to match your exact business logic
- No vendor lock-in — swap any component without rebuilding everything
The trade-off is that you're responsible for maintenance, uptime, and compliance — and you're using an unofficial API that could break if WhatsApp changes their web client.
Next Steps
Once the basic lead capture is working, you can extend it:
- Add a conversational flow with multiple steps (ask for name, email, budget)
- Connect to a calendar booking system for automatic demo scheduling
- Build lead scoring based on message content and response patterns
- Add multi-language support by detecting the message language
For a deeper dive into WhatsApp bot architecture and more advanced patterns, check out our complete WhatsApp bot guide.
If you're exploring business automation more broadly — not just WhatsApp — our business automation guide covers the full landscape of what you can automate with open-source tools.
I build automation systems for businesses using open-source tools like n8n, WAHA, and Supabase. If you want help setting up lead capture or any other workflow, visit achiya-automation.com to learn more.
Top comments (0)