parley
Attaches to an already logged-in WhatsApp Desktop instance over local Chrome DevTools Protocol to read chats and unread messages, send messages to contacts/groups/numbers, reply with quotes, react with emoji, and schedule one-shot or recurring sends. Exposes these WhatsApp capabilities through a CLI, Python SDK, local HTTP API, TUI, and MCP tools without using the WhatsApp cloud service or requiring a new QR-code login.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@parleysend Ava a WhatsApp saying I'll be there at 7"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
One line to install on any machine:
# Windows (PowerShell) — runs the installer: install + enable the port + next steps
irm https://raw.githubusercontent.com/Sachitt-AV-08/parley/main/install.ps1 | iex# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/Sachitt-AV-08/parley/main/install.sh | shThe installer detects uv → pipx → pip, installs parley-wa (CLI, TUI and
MCP extras) from the latest release, enables the local debugging
port, and prints the two commands to start.
One line to send from a script on any machine:
pip install 'parley-wa'[mcp] # or: pip install <release wheel URL>
parley setup # enable the local debugging port (auto-undoable)
parley send --to Ava --text "ci is green" # resolves Ava -> live chat -> sends -> confirms it landedOr in Python:
from parley import Session, parley_connect
wa = parley_connect() # auto-attaches to the running WhatsApp Desktop
wa.send("Weekend Hikers", "who's bringing the snacks?")
for chat in wa.chats(unread_only=True):
print(chat)No WhatsApp account? The entire API runs on a fully scripted simulator:
parley --demo status
parley --demo send --to Ava --text "hi from parley"
parley --demo tuiWhy parley exists
The mainstream way to automate WhatsApp is a cloud service — or a library that quietly talks to one. Your chats, your contacts, your fingerprints transit a third party that is not WhatsApp, and a lot of accounts got flagged for it.
parley takes the opposite side:
It never talks to anything but your own machine. You already trusted WhatsApp Desktop with your account — parley attaches to that process over the Chrome DevTools Protocol (a local debugging channel, one setting away from enabled), and drives the very page you're looking at. Everything stays on
127.0.0.1.
The result: no new login, no re-encoding of credentials, no upload, no ban-risk multiplier — automation for your own account, on your own screen, as if a tireless human assistant with hands were sitting at your desk.
Windows — WhatsApp Desktop renders WhatsApp Web in WebView2 (Chromium). parley turns on its debugging channel with
parley setupand connects.macOS / Linux — same CLI attaches to any Chromium with
--remote-debugging-port=9334pointed atweb.whatsapp.com.Remote / containers —
PARLEY_CDP_HOST/PARLEY_CDP_PORTpoint parley at whatever machine exposes the port.
Related MCP server: waxum-mcp
Features
| attach health, login state, endpoint checks, reversible setup |
| conversations, unread counts, pins, last message, last seen |
| full history, richest first, JSON-ready |
| sends to a contact, group, number, or chat id — parley resolves the recipient first |
| quoted replies where WhatsApp supports them |
| reactions, not read receipts |
| one-shot and recurring (hourly/daily/weekly) sends, persisted to disk |
| local JSON HTTP API — for agents, webhooks, cron, you name it |
| a real terminal chat inside your WhatsApp |
| the entire surface, fully scripted, zero WhatsApp needed (also what CI tests live on) |
--to knows people and groups: pass an id (15551234567@c.us), a bare
number (+1 555 123 4567), a contact name (Ava) or a group subject
(Weekend Hikers) — parley finds the exact chat, opens it, verifies the
header and only then types. No wrong-chat accidents.
Quick tour
# enable the debugging channel (undo later with: parley setup --undo)
parley setup # user-level env var, no admin; add --admin for HKLM
parley doctor # confirm: process running? flag present? endpoint open?
# your real install:
parley chats
parley send --to "Weekend Hikers" --text "who's bringing the snacks?"
parley send --to "+91 98765 43210" --text "sms alternative, but over WhatsApp"
parley chat Ava --json | jq '.[0]'
# scheduled + recurring sends, right from the API:
parley schedule add --to Ava --text "morning standup reminder" \
--at "2026-10-02T09:00:00" --repeat daily
parley schedule list
parley schedule run --once # fire anything due, right now
# any HTTP client can use it too — `parley server` issues a token on first
# run and prints it (see `~/.parley/server.token`); pass it as a Bearer token:
export PARLEY_TOKEN="$(cat ~/.parley/server.token)"
curl -X POST localhost:8300/send -H "content-type: application/json" \
-H "authorization: Bearer $PARLEY_TOKEN" \
-d '{"to":"Ava","text":"via http"}'Every command supports --json for piping into scripts, agents and cron.
Scheduled entries live in ~/.parley/schedules.json (override with
PARLEY_DATA_DIR), and parley server watches the queue in the background —
a scheduled blast obeys the same pacing and budget as a manual send.
How it actually works
┌─────────────────────────── your machine ───────────────────────────┐
│ │
CLI/TUI │ ┌──────────┐ ┌──────────────────┐ ┌───────────────────────┐ │
HTTP API │ │ parley │──▶│ Session (paced,│──▶│ Backend (CDP attach) │ │
agents │ │ Session │ │ retried) │ │ playwright over CDP │ │
│ └──────────┘ └──────────────────┘ └──────────┬────────────┘ │
│ │ CDP over │
│ ┌──────────────────────────┐ ┌──────────────┐ │ ws:// │
│ │ WhatsApp Desktop (WinUI3) │◀────▶│ WebView2 │◀────── localhost│
│ │ …already logged in… │ │ (Chromium) │ │
│ └──────────────────────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────────────────┘parley setupopens the WebView2 debugging channel (user env var by default, machine-wide HKLM policy with--admin;--undoremoves both) — exactly how you'd debug any WebView2 app.WebViewBackend attaches over CDP and finds the WhatsApp page target.
Reads prefer WhatsApp's internal Store (
WAWebCollections, or a webpack registry scan) — structured, fast, no screen-scraping. A DOM fallback kicks in when the store's internal name changes between builds.Writes go through the Store's message API (
sendTextMsg/chat.sendMessagewith several strategy fallbacks) and, when the build exposes none, the DOM path drives the visible UI: search (name and number candidates) → click the exact row by title → verify the conversation header switched → type → Enter → poll until the text visibly appears in the conversation before reporting success.HumanPacing guards every send so an account never looks like a spam bot.
SchedulerThread (in
parley server) fires due entries through the same paced session.
DemoBackend implements the same backend protocol entirely in memory — that's
what powers --demo, the unit tests and the CI.
Give your AI agent hands on WhatsApp
parley ships a Model Context Protocol (MCP) server, so any MCP client — Claude Desktop, Claude Code, Cursor, Copilot, or any agent framework — can read chats and send/reply/react/schedule on your real WhatsApp, locally.
pip install 'parley-wa[mcp]' # install with the MCP extra
parley mcp # serve an MCP stdio server on your live accountPoint your client at it. Claude Desktop-style config (the command must honor the
--demo global flag placement — it goes before the subcommand):
{
"mcpServers": {
"parley": { "command": "parley", "args": ["mcp"] }
}
}For Claude Code, one command installs the bundled agent skill into
~/.claude/skills — the skill teaches the agent the tool set, pacing and
guardrails:
parley skill installExposed tools: status, list_chats, read_messages, send_message,
reply_message, react_message, schedule_message, list_schedules,
cancel_schedule, run_due_schedules. Everything stays on 127.0.0.1 and
runs through the same paced, verified session as the CLI.
Reliability, with receipts
Automating a store you don't own is only as good as the verifier. parley treats "send" as three confirmed steps, each independently checked:
Resolve —
resolve_recipient(needle)returns a(chat_id, display_name)you can inspect, or raises cleanly. Name, number, id and group all work.Open — the DOM path only clicks a row whose title matches, then re-checks the conversation header really switched before allowing typing.
Landed — after Enter, parley polls
#mainuntil the exact normalized text appears in the conversation bubble stream. Only then isok: truereturned. Failed confirmation raises instead of silently pretending.
Measured on the author's Windows 11 box (one-time cold vs warm):
path | cost |
CDP attach + login check | ~0.8 s |
recipient resolution | ~0.1 s |
open an already-open chat + send + confirm | ~5 s |
full cold path (search → open → type → confirm) | ~9 s |
Every number is paced down further by HumanPacing before it touches the wire.
parley vs the status quo
parley | WhatsApp Cloud API | web-scraping "bots" | "tools-in-the-cloud" platforms | |
where data lives | your machine | Meta | random VPS | their cloud |
new login / QR needed | no | yes (business mgr) | sometimes | yes |
cost | free, open source | usage-metered | blocked fast | subscriptions |
ban profile | low (your own desktop) | official but gated | high | high |
offline dev / CI | yes ( | no | no | no |
self-hostable | yes | no | makeshift | no |
Human by default
Blasting is how accounts get flagged. parley's HumanPacing:
types for ~90 ms/character (bounded), jittered;
sleeps a variable "network" beat before each sent;
keeps a rolling burst budget (18 messages / 60 s by default).
Every value is overridable per command and per API call, because you are the responsible party for your own account.
Safety notes
parley never sees, stores or transmits your credentials, chats, contacts or session state. All traffic stays on
127.0.0.1.Sends are paced and budgeted by design. Read operations never write.
Treaty: use your own account, your own device, your own automation — comply with local law and WhatsApp's ToS. The issues tracker is open for questions.
If you expose the HTTP server beyond loopback, set
--tokenand use TLS in front — and honestly, don't; keep it on127.0.0.1.
Status
Area | State |
Simulator ( | stable, unit-tested, CI |
Live attach (Windows WhatsApp Desktop) | verified — real messages sent & content-confirmed in the UI |
Recipient resolution (contact, group, number, id) | stable, unit-tested |
Scheduler (one-shot + hourly/daily/weekly, JSON store) | stable, unit-tested |
CDP attach + status + login detect | implemented |
Store read path (chats/messages/contacts) | implemented, version-tolerant |
DOM fallback reads + DOM send | implemented, verified |
HTTP API (incl. | implemented, unit-tested |
TUI | functional, rides the simulator too |
Cross-platform (any Chromium + web.whatsapp.com) | supported |
Tests / CI | 40+ green on Windows + Ubuntu, Python 3.10–3.13 |
The live-store APIs are inherently version-sensitive (they call WhatsApp's own internal module surface). parley degrades gracefully — a build bump only ever softens a feature, never crashes the process.
Roadmap
PyPI release of
parley-wa(one token away —uv tool install parley-wa)First-class Python SDK docs and a
docs/siteMedia sends (images, voice notes) and message download
Webhooks →
parley serverpush channelsA
parley as a servicemode for containers (still local-first)Contributions welcome — see CONTRIBUTING
Contributing
uv venv && uv pip install -e '.[dev]'
uv run pytest # green, offline, fast
uv run parley --demo chatsIssues, PRs and "it works on this build" reports are all gold. Read CONTRIBUTING and the code of conduct first.
Contributors
Sachitt (@Sachitt-AV-08) — creator, maintainer
License
MIT © Sachitt. Made for people who automate their own machines — not for harvesting other people's. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Drive WhatsApp from any MCP client: pair devices, send text and media, manage contacts and groups.
Your own WhatsApp as an MCP server: read, search and send from any MCP client.
Hosted MCP server for your own WhatsApp accounts: messages, contacts, groups, channels, calls.
WhatsMCP connects Claude and other MCP-compatible AI agents directly to WhatsApp. Send and receive text, images, documents, and voice notes; manage groups (create, add/remove members, promote admins); look up contacts and profiles; follow channels; and read call and message history — all through a standard MCP interface. For voice use cases, WhatsMCP offers SIP-based calling plans (inbound-only, or full inbound/outbound) so AI voice agents can answer and place WhatsApp calls, plus low-latency WebSocket integrations with voice agent providers like ElevenLabs. Multiple WhatsApp accounts can be paired and managed per workspace, with webhook support for real-time inbound message delivery to your own infrastructure.
Related MCP Servers
- FlicenseBqualityDmaintenanceRead-only MCP server for WhatsApp Web allowing listing chats and reading recent messages, without sending or mutating WhatsApp state.312 npm-
- FlicenseNot gradedqualityCmaintenanceMCP server for WhatsApp that exposes send, read, and media management tools through the waxum REST API gateway, enabling any MCP client to interact with WhatsApp chats and media over stdio.1-
- AlicenseNot gradedqualityBmaintenanceMCP server that controls WhatsApp Desktop via Chrome DevTools Protocol using the user's real session, enabling tools to list chats, read messages, search contacts, and send messages with simulated typing and rate limiting.31 npm1MIT
- AlicenseNot gradedqualityBmaintenanceMCP server that turns WhatsApp into agent-callable tools, enabling search contacts, send/receive messages, read chats, handle media, and monitor calls via the WhatsApp Web multi-device protocol.2 npmMIT