WhatsApp is where real conversations happen. Over 2 billion users. Your family. Your clients. Your team’s informal decision-making. If your AI agent isn’t on WhatsApp, it’s missing half the action.
But WhatsApp bot setup is notoriously painful. Meta doesn’t want bots. They tolerate them, barely, with restrictions that make sense for spam prevention but frustrate legitimate use.
This guide shows you two paths to get OpenClaw on WhatsApp: Path 1 — whatsapp-web.js (free, unofficial, fragile) and Path 2 — WhatsApp Cloud API (official, paid, stable). By the end you’ll know which fits, how to set it up, and how to avoid getting banned.
Why WhatsApp Bots Are Different (And Difficult)
- ●Telegram: open bot API, encouraged, free, no restrictions
- ●Slack: business-friendly, OAuth flow, well-documented
- ●WhatsApp: actively hostile to bots, API designed for enterprise, verification hoops, ban-happy automated enforcement
Why WhatsApp doesn’t want bots
- ●Spam prevention — WhatsApp is end-to-end encrypted, so they rely on behavior patterns, not content
- ●Business model — they want to sell Business API access
- ●Privacy concerns — loose bot access leads to abuse
The result: getting a bot on WhatsApp requires either reverse-engineering WhatsApp Web (fragile, ban risk) or paying Meta for official API access (stable, expensive for small use).
Path 1: whatsapp-web.js (The Unofficial Route)
whatsapp-web.js is a Node.js library that emulates WhatsApp Web. It connects to your account the same way the web client does — you scan a QR code, it maintains a Chromium session, and OpenClaw sends/receives through it.
Pros
- ●Completely free
- ●Uses your personal WhatsApp number
- ●No Meta approval process
- ●Quick setup (20-30 minutes)
Cons
- ●Ban risk — Meta can detect this and ban your number
- ●Fragile — breaks when WhatsApp updates their protocol
- ●Requires phone connection — if your phone dies, bot dies
- ●Not officially supported
Step 1: Install whatsapp-web.js
npm install whatsapp-web.js qrcode-terminal
Step 2: Create WhatsApp Adapter
Create adapters/whatsapp-web.js:
const { Client, LocalAuth } = require('whatsapp-web.js');
const qrcode = require('qrcode-terminal');
class WhatsAppWebAdapter {
constructor(config) {
this.config = config;
this.client = null;
}
async initialize() {
this.client = new Client({
authStrategy: new LocalAuth({ dataPath: './whatsapp-session' }),
puppeteer: {
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
}
});
this.client.on('qr', (qr) => {
console.log('Scan this QR code with your phone:');
qrcode.generate(qr, { small: true });
});
this.client.on('ready', () => console.log('[WhatsApp] Client is ready!'));
this.client.on('message', async (msg) => await this.handleMessage(msg));
this.client.on('disconnected', (reason) => {
console.log('[WhatsApp] Logged out:', reason);
setTimeout(() => this.initialize(), 30000);
});
await this.client.initialize();
}
async handleMessage(message) {
const from = message.from;
const text = message.body;
const isGroup = from.endsWith('@g.us');
if (isGroup && !message.mentionedIds.includes(this.client.info.wid._serialized)) return;
const response = await this.processWithOpenClaw(from, text);
await this.client.sendMessage(from, response);
}
}
module.exports = WhatsAppWebAdapter;Step 3: Configure & Link Your Number
Edit config/channels.yml:
channels:
whatsapp_web:
enabled: true
adapter: adapters/whatsapp-web.js
rate_limit:
messages_per_minute: 15
messages_per_hour: 200
ignore_groups: true
auto_reply_delay: 2000Run npm start. A QR code appears in the terminal. On your phone open WhatsApp → Settings → Linked Devices → Link a Device, then scan. You’ll see [WhatsApp] Client is ready! and your bot is connected.
Avoiding Bans (Critical)
Meta’s automated systems detect bot-like behavior and ban numbers. Avoid:
- ●High message volume — keep under ~10/min and ~100/hour
- ●Instant replies — add a 1-3s random delay so it looks human
- ●Identical message patterns — vary templates
- ●24/7 activity — schedule sleep periods (e.g. 1am-6am)
- ●Bulk messaging — stagger 5+ minutes between recipients
// Add random delay (1-3 seconds) const delay = 1000 + Math.random() * 2000; await new Promise(r => setTimeout(r, delay)); await client.sendMessage(to, text);
When You Get Banned (It Happens)
- ●Symptom: “This account is not allowed to use WhatsApp”
- ●Wait 48 hours — temporary bans lift
- ●Appeal via WhatsApp support (rarely works)
- ●Use a different number (burner SIM)
The Fragility Problem
- ●Breaks when WhatsApp updates their web protocol
- ●Your server’s IP can get flagged
- ●Chromium version mismatch
- ●Session expires unexpectedly
Monitor for breaks weekly, run npm update whatsapp-web.js regularly, and have a migration plan to the official API.
Path 2: WhatsApp Cloud API (The Official Route)
Meta’s WhatsApp Cloud API is the legitimate, stable way to build WhatsApp bots. You register as a business, Meta gives you API access, you send/receive via REST, and pay per message ($0.005-$0.05 depending on region).
Pros
- ●Official — no ban risk
- ●Stable — doesn’t break with WhatsApp updates
- ●Scalable — handle thousands of messages
- ●Rich features: media, buttons, templates
Cons
- ●Cost — $0.005+/message adds up
- ●Verification — business verification takes days/weeks
- ●Complexity — webhooks, tokens, Meta bureaucracy
- ●Free tier: 1,000 conversations/month
Step 1: Create Meta Developer Account
- 1.Go to developers.facebook.com
- 2.Sign up / log in
- 3.Create App → Business type → name it (e.g. “OpenClaw Bot”)
- 4.Add Product → select WhatsApp → click Set up
Step 2: Business Verification (The Waiting Game)
Meta requires proof you’re a real business: business name, website (or Facebook Page), address, phone number, and registration documents in some countries. Submit via Meta Business Suite and wait 1-7 days (sometimes weeks).
Step 3: Get API Credentials
- 1.WhatsApp → API Setup
- 2.Copy the temporary access token (expires in 24 hours)
- 3.Copy your Phone Number ID
- 4.Copy your WhatsApp Business Account ID
Generate a Permanent Token
- 1.Settings → Business Settings → System Users
- 2.Add → create system user
- 3.Assign access to WhatsApp
- 4.Generate Token with whatsapp_business_messaging and whatsapp_business_management scopes
- 5.Copy and store the permanent token
Step 4: Configure Webhook
WhatsApp delivers messages via webhook (POST to your server). You need a public HTTPS endpoint that responds to a verification GET and handles POSTs:
// routes/whatsapp-webhook.js
const express = require('express');
const router = express.Router();
router.get('/webhook/whatsapp', (req, res) => {
const mode = req.query['hub.mode'];
const token = req.query['hub.verify_token'];
const challenge = req.query['hub.challenge'];
if (mode === 'subscribe' && token === process.env.WHATSAPP_VERIFY_TOKEN) {
res.status(200).send(challenge);
} else {
res.sendStatus(403);
}
});
router.post('/webhook/whatsapp', async (req, res) => {
try {
const body = req.body;
if (body.object === 'whatsapp_business_account') {
for (const entry of body.entry) {
for (const change of entry.changes) {
if (change.field === 'messages') {
const message = change.value.messages?.[0];
if (message) await handleIncomingMessage(message);
}
}
}
}
res.sendStatus(200);
} catch (err) {
console.error('[WhatsApp] Webhook error:', err);
res.sendStatus(500);
}
});
async function sendWhatsAppMessage(to, text) {
const url = `https://graph.facebook.com/v18.0/${process.env.WHATSAPP_PHONE_NUMBER_ID}/messages`;
const r = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.WHATSAPP_ACCESS_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ messaging_product: 'whatsapp', to, text: { body: text } })
});
return r.json();
}
module.exports = router;Step 5: Register Webhook with Meta
- 1.WhatsApp → Configuration in the Meta dashboard
- 2.Callback URL: https://your-openclaw-domain.com/webhook/whatsapp
- 3.Verify Token: a random string stored as WHATSAPP_VERIFY_TOKEN in your .env
- 4.Verify and save — Meta sends a GET to verify
- 5.Subscribe to webhook fields: messages and message_status
Then add your credentials to .env:
WHATSAPP_ENABLED=true WHATSAPP_PROVIDER=cloud_api WHATSAPP_ACCESS_TOKEN=your-permanent-token WHATSAPP_PHONE_NUMBER_ID=your-phone-id WHATSAPP_VERIFY_TOKEN=your-random-verify-token
Step 6: Test & Go Live
Add one of Meta’s test numbers under WhatsApp → API Setup → To, verify with OTP, then send a test message:
curl -X POST "https://graph.facebook.com/v18.0/{PHONE_NUMBER_ID}/messages"
-H "Authorization: Bearer {ACCESS_TOKEN}"
-H "Content-Type: application/json"
-d '{
"messaging_product": "whatsapp",
"to": "15551234567",
"text": { "body": "Hello from OpenClaw!" }
}'Once verified, go to WhatsApp → API Setup → Upgrade, add a payment method, accept pricing terms, and you can message any WhatsApp user. Pricing: $0.005-$0.05 per user-initiated message; first 1,000 conversations/month free. A “conversation” is a 24-hour window after a user messages you, with unlimited messages inside it.
Comparing Both Paths
- ●Cost — whatsapp-web.js: free | Cloud API: $0.005+/message
- ●Setup time — 30 min vs 1-7 days verification
- ●Ban risk — high vs none
- ●Stability — fragile vs rock solid
- ●Scale — <100/day vs unlimited
- ●Features — basic text vs rich media + buttons
- ●Maintenance — high vs low (Meta handles)
- ●Best for — personal testing vs business use
The Ban Risk Reality Check
With whatsapp-web.js, you will get banned eventually if you send 50+ messages/day consistently, respond instantly with no human delay, look bot-like, or once Meta updates detection. It’s not “if,” it’s “when.” Use a burner number, accept it’s temporary, plan migration to Cloud API.
The Cost Reality Check
- ●1,000 messages/month ≈ $5-10
- ●10,000 messages/month ≈ $50-100
- ●100,000 messages/month ≈ $500-1,000
For business this is worth it. For personal use it’s expensive. PaioClaw’s managed WhatsApp integration uses the Cloud API with no per-message markup — you pay Meta directly and PaioClaw handles webhook setup, verification support, and token management. Starts free, $4/month + Meta’s API charges.
The Bottom Line
WhatsApp bot setup is harder than it should be. Two paths, both with tradeoffs:
- ●whatsapp-web.js: free, fragile, ban risk — good for testing, bad for production
- ●Cloud API: official, stable, expensive — good for business, overkill for personal
Most people start with Path 1 to test, then migrate to Path 2 when they hit bans or need reliability — or skip both and use PaioClaw, which handles the complexity end-to-end.

