Connect OpenClaw to WhatsApp: The QR Isn't the Hard Part
Almost every complaint about OpenClaw’s WhatsApp channel is the same complaint: it worked, then it stopped, and now it wants the QR code again.
The QR scan isn’t where people get stuck. The scan works the first time. What breaks is the session, and it breaks for a boring reason — WhatsApp linking writes credentials to a directory on disk, and if that directory lives inside a container you recreate, the link goes with it.
So this guide leads with persistence and comes back to the scan afterwards.
Where the link actually lives
OpenClaw stores WhatsApp auth state here:
~/.openclaw/credentials/whatsapp/<accountId>/creds.json
with a creds.json.bak alongside it. That file is the linked session. Keep it and the gateway resumes silently after a restart; lose it and you’re back at the QR.
If you run OpenClaw in Docker, map the whole OpenClaw home directory to a named volume rather than picking out the credentials path:
services:
openclaw:
image: openclaw/openclaw
volumes:
- openclaw-data:/root/.openclaw # match your image's home directory
volumes:
openclaw-data:
Mapping the parent directory means config, credentials and state all survive together — and it avoids the trap where you persist credentials but lose the rest and end up half-configured. Check your image’s actual home path before copying that line; it may not be /root.
If you’d rather keep WhatsApp auth somewhere specific, OpenClaw supports attaching a directory at account creation:
openclaw channels add --channel whatsapp --account work --auth-dir /path/to/wa-auth
openclaw channels login --channel whatsapp --account work
Installing the channel
The WhatsApp runtime ships as a separate plugin, not in the core package, so its dependencies stay out of the main install. openclaw onboard and openclaw channels add --channel whatsapp both offer to install it the first time you pick WhatsApp. Manually:
openclaw plugins install clawhub:@openclaw/whatsapp
The channel connects through WhatsApp Web (Baileys) — OpenClaw’s docs describe it as production-ready and note there’s no separate Twilio WhatsApp channel. The gateway owns the linked session.
Set the access policy before you link
Decide who can talk to it before it’s reachable, not after:
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
groupPolicy: "allowlist",
groupAllowFrom: ["+15551234567"],
},
},
}
WhatsApp identities are phone numbers, which makes this more readable than Telegram’s numeric IDs. dmPolicy: "pairing" is the alternative if you’d rather approve senders as they arrive, via Settings → Channels → DM access requests or the CLI.
Link it
openclaw channels login --channel whatsapp
Then on the phone: WhatsApp → Settings → Linked devices → Link a device, and scan.
Login is QR-only — there’s no pairing-code path. That matters on a headless server, and OpenClaw’s docs are direct about the pitfall:
“On remote or headless hosts, have a reliable path to deliver the live QR to the phone before starting login; terminal-rendered QRs, screenshots, or chat attachments can expire in transit.”
In practice: be at the terminal with the phone in your hand before you run the command. The QR rotates, so a screenshot pasted into a chat and scanned a minute later will fail — and the failure looks like a broken setup rather than an expired code. If you’re SSH’d in from a laptop, run the login in that live session and scan directly off your own screen.
Then start the gateway:
openclaw gateway
When the session drops anyway
If persistence is sorted and it still disconnects, work through it in this order rather than re-linking immediately.
First, check whether it’s actually broken. OpenClaw’s watchdog tracks transport activity and application-message activity separately, precisely so a quiet-but-healthy session isn’t restarted just because nobody messaged it for a while. A silent account is not necessarily a dead one.
openclaw channels status --probe
openclaw doctor
openclaw logs --follow
openclaw gateway status
If it’s a genuine reconnect loop, back up the auth directory before re-linking — that way a re-link that goes wrong isn’t a one-way door:
cp -a ~/.openclaw/credentials/whatsapp/<accountId> \
~/.openclaw/credentials/whatsapp/<accountId>.bak
openclaw channels logout --channel whatsapp --account <accountId>
openclaw channels login --channel whatsapp --account <accountId>
If QR login times out behind a proxy with status=408 Request Time-out or a TLS disconnect, WhatsApp Web login uses the host’s standard proxy environment. Confirm the gateway process inherits it, and that NO_PROXY doesn’t match mmg.whatsapp.net — that specific exclusion is an easy one to have inherited from an unrelated config.
If a reply shows in the transcript but never arrives in WhatsApp, those are two different things. The transcript records what the agent generated; delivery is tracked separately, and OpenClaw only counts an auto-reply as sent once Baileys returns an outbound message ID. Look for auto-reply delivery failed or auto-reply was not accepted by WhatsApp provider in the gateway logs. Note also that an acknowledgment reaction arriving is not proof the reply landed — reactions are independent pre-reply receipts.
If whatsapp-health.log says Gateway inactive while openclaw gateway status and channels status --probe both look healthy, run openclaw doctor. On Linux this is often a stale crontab entry calling the retired ensure-whatsapp.sh script; cron can lack the systemd user-bus environment and misreport health. Remove the entry with crontab -e.
One runtime constraint worth knowing: OpenClaw gateways require Node. Bun doesn’t provide the node:sqlite API the state store uses, and doctor migrates legacy Bun services to Node.
Groups
If groups are ignored, check in the order the docs give — it’s ordered by how often each one is the cause:
groupPolicy-
groupAllowFrom/allowFrom -
groupsallowlist entries - mention gating (
requireMentionand mention patterns) -
duplicate keys in
openclaw.json— it’s JSON5, so a latergroupPolicysilently overrides an earlier one
That last one catches people who’ve edited config across several sessions. Keep one groupPolicy per scope.
Note the behaviour when channels.whatsapp.groups exists: WhatsApp still observes messages from other groups, but OpenClaw drops them before session routing. Add the group’s JID, or use groups["*"] to admit all groups while keeping sender authorisation under groupPolicy/groupAllowFrom.
Use a separate number
OpenClaw’s docs list a dedicated number as the recommended deployment pattern, for cleaner allowlists and routing boundaries and to avoid self-chat confusion. Personal-number mode is supported — onboarding writes selfChatMode: true and self-chat safeguards activate when your own number is in allowFrom — but it’s the fallback, not the default advice.
There’s a second reason the docs don’t make, and it’s worth stating plainly. This channel connects through Baileys, whose own README says:
“This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates.”
That’s an unofficial client path. It works well and it’s what OpenClaw ships, but you’re automating an account through a route WhatsApp doesn’t publish or support. Use a number you can afford to lose, keep message volume human, and don’t point it at anything you’d be stuck without. If a channel that’s officially supported end to end matters more to you than WhatsApp specifically, Telegram is the easier and better-documented option and its bot API is designed for exactly this.
Before you leave it running
An always-on WhatsApp link needs a machine that stays up, which is the argument for a small VPS rather than a laptop. Our OpenClaw self-hosting guide covers the install with hardening first, and best VPS for OpenClaw covers sizing — 4GB is the practical floor.
Two things worth doing once it’s live: confirm the credentials directory really is on the volume by recreating the container and checking it doesn’t ask for a QR — the same test that decides whether moving to another server will carry the session with it, and make sure the box itself isn’t exposed to the internet on some other port while you were busy securing the channel.
How we checked this
The commands, config keys, credential paths, log strings and troubleshooting order in this guide are from OpenClaw’s own WhatsApp channel documentation in the project repository, read in August 2026 — including the QR-only login constraint and its headless warning, the ~/.openclaw/credentials/whatsapp/<accountId>/creds.json path, the watchdog’s two-signal behaviour, and the group-precedence checklist. The Baileys disclaimer is quoted from the Baileys README.
What we have not done: we didn’t run this end to end for this article, so treat it as a careful reading of the documentation rather than a lab report. Two details in particular you should verify against your own setup: the container home directory in the volume mapping varies by image, and config schemas move between versions — openclaw doctor is the authority on whether your file is valid for the version you’re running.
We also haven’t tested how WhatsApp responds to automated accounts over time, and we’re not going to guess at it. The dedicated-number advice above is what OpenClaw recommends for routing reasons; the unofficial-client point is ours, and it’s a reason for caution rather than a prediction.
This guide has no affiliate links.
FAQ
Why does OpenClaw keep asking me to scan the WhatsApp QR code again?
Because the auth state isn’t persisting. WhatsApp credentials live at ~/.openclaw/credentials/whatsapp/<accountId>/creds.json, and if that path is inside a container without a volume, recreating the container destroys the link. Map the OpenClaw home directory to a named volume and the session survives restarts.
Can I link WhatsApp without scanning a QR code?
No. OpenClaw’s WhatsApp login is QR-only. On a headless server, run the login while you have the phone to hand and scan from the live terminal — the code rotates, so screenshots and forwarded images frequently expire before you scan them.
Where does OpenClaw store WhatsApp credentials?
~/.openclaw/credentials/whatsapp/<accountId>/creds.json, with a .bak alongside. You can point an account at a different directory with --auth-dir when adding it.
My WhatsApp session keeps disconnecting. What should I check?
Run openclaw channels status --probe, openclaw doctor and openclaw logs --follow first — a quiet session isn’t necessarily a broken one, since the watchdog deliberately doesn’t restart connected-but-idle accounts. If it’s a real loop, back up the auth directory, then log out and re-link.
Should I use my personal WhatsApp number?
OpenClaw recommends a dedicated number, mainly for cleaner allowlists and to avoid self-chat confusion. Personal-number mode is supported with self-chat safeguards. Separately, this runs through an unofficial WhatsApp Web client, which is its own reason to use a number you can afford to lose.
The agent replied in the transcript but nothing arrived in WhatsApp.
Those are tracked separately. A reply only counts as delivered once Baileys returns an outbound message ID — check the gateway logs for auto-reply delivery failed or auto-reply was not accepted by WhatsApp provider. An acknowledgment reaction landing doesn’t prove the reply did.
Is WhatsApp or Telegram the better first channel?
Telegram, for setup and debugging — it uses an official bot API, links with a token instead of a QR, and its failures have documented names. Choose WhatsApp when it’s where the people you want to reach already are.