Waton is a lightweight, standalone Python library for WhatsApp Web Multi-Device. Build WhatsApp bots, automation tools, and messaging applications entirely in Python — no Node.js required.
- Pure Python — Native async/await API, integrates seamlessly with your Python stack
- Blazing Fast Crypto — Signal Protocol encryption powered by Rust (via PyO3)
- Lightweight — ~30-60MB memory footprint, minimal dependencies
- Multi-Device Ready — Full support for WhatsApp's multi-device architecture
- No Node.js — Standalone implementation, zero JavaScript runtime dependency
- QR Code & Phone Number Pairing
- Send & Receive Text Messages
- Multi-Device Message Routing
- End-to-End Encryption (Signal Protocol)
- Persistent Session Storage (SQLite)
- Async/Await Native API
pip install waton==0.1.4Prebuilt wheels include the Rust crypto extension — no Rust toolchain needed for installation.
For development:
pip install -e .[dev]
maturin developIf you get:
failed to copy ... waton\\_crypto.pydThe process cannot access the file because it is being used by another process. (os error 32)
then _crypto.pyd is locked by another running Python process (usually examples/cli_chat.py or examples/live_connect.py).
Fix:
# from project root
Get-CimInstance Win32_Process -Filter "name='python.exe'" `
| Where-Object { $_.CommandLine -match 'examples/cli_chat.py|examples/live_connect.py' } `
| ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
python -m pip install -e .[dashboard]If you only want the browser dashboard and do not need reinstall, you can skip editable reinstall and just run:
python -m tools.dashboard.server --host 127.0.0.1 --port 8080Published artifacts are intentionally runtime-only:
- included:
waton/, Rust extension module, metadata files - excluded from source distribution:
docs/,examples/,tests/,tools/
Quick verification commands:
python -m pip wheel . --no-deps -w .tmp-wheel
python -m maturin sdist --manifest-path Cargo.toml --out .tmp-sdistWaton now provides a simple callback API for fastest onboarding, plus the existing high-level App and low-level WAClient interfaces.
If you want automation agents to run Waton with minimum prompt/context overhead:
- Install latest stable:
pip install -U waton - Or pin reproducible release:
pip install waton==0.1.4 - Start with simple API:
from waton import simple - Keep one linked WA session active during tests to avoid conflict
440 - Use quick docs page:
docs/source/content/ai-agent-quickstart.rst
If you want the shortest path from import to running bot:
from waton import simple
client = simple(storage_path="my_session.db")
@client.on_message
async def on_message(msg):
if msg.text:
await msg.reply(f"Echo: {msg.text}")
@client.on_ready
async def on_ready(bot):
print("Waton simple client is connected")
if __name__ == "__main__":
client.run()msg provides:
msg.idmsg.textmsg.from_jidmsg.senderawait msg.reply(text)await msg.react(emoji)
Use this mode when you want minimal boilerplate while keeping the same core runtime.
We provide a built-in interactive terminal chat. If you just want to test sending and receiving messages via your terminal, run:
python examples/cli_chat.py- When you run this for the first time, it will print a QR code in the terminal. Scan it with your WhatsApp app (Linked Devices).
- Once connected, any incoming messages to your number will be printed live in the terminal.
- To send a message, simply type
NOMOR_TUJUAN pesan yang ingin dikirim(e.g.,628123456789 Halo dari terminal!) and press Enter.
To validate connect/ping/send-ack/reconnect in one command:
python scripts/live_check.py --auth-db waton_live.db --test-jid 628123456789@s.whatsapp.net --test-text "hello from waton"If --test-jid is omitted, the check still validates connect/ping/reconnect without send-ack.
Run all release gates (tests, parity scan, and optional lint/typecheck/live):
python scripts/preflight_check.pyFast local run (skip lint/typecheck):
python scripts/preflight_check.py --skip-lint --skip-typecheckStrict parity release gate (requires evidence, enforces replay_pass_rate >= 0.995 and drift_count == 0 for status=done domains):
python scripts/preflight_check.py --parity-strict --parity-evidence docs/parity/artifacts/strict-evidence-sample.json --skip-lint --skip-typecheckCI strict gate (fresh CI-generated evidence + expected commit SHA enforcement):
python scripts/preflight_check.py --parity-strict --parity-evidence docs/parity/artifacts/strict-evidence-ci.json --expected-commit-sha <commit-sha> --skip-lint --skip-typecheckNote: sample evidence files are for local/dev smoke usage only.
Run parity scan + replay smoke in one command:
python scripts/parity_evidence_smoke.pyRun hybrid strict parity smoke (includes differential wire/behavior checks + strict evidence gate):
python scripts/parity_evidence_smoke.py --parity-evidence docs/parity/artifacts/strict-evidence-sample.jsonThis command is intended as a fast parity confidence smoke gate for development/release checks.
Waton tracks Baileys v7/rc11 capability drift without changing default runtime behavior:
python -m tools.parity.scan_baileys_parity --waton waton --baileys ../Baileys/src --out docs/parity/baileys-parity-latest.json
python -m tools.parity.wa_version_tracker --baileys ../Baileys --out docs/parity/wa-version-drift-latest.jsonThe scanner writes a baileys_v7 section covering LID mapping, tctoken, retry/resend, app-state resilience, offline batching, media robustness, notification coverage, and WA Web version drift. All Baileys v7 power-mode behavior is disabled by default in DEFAULT_CONNECTION_CONFIG; these flags are scaffolding for future parity work, not runtime behavior changes.
If you want a browser UI instead of terminal-only testing:
pip install -e .[dashboard]
export WATON_DASHBOARD_API_TOKEN="change-this-token"
python -m tools.dashboard.server --host 127.0.0.1 --port 8080Open http://127.0.0.1:8080.
- Security note: dashboard API is now strict-by-default. You must provide
WATON_DASHBOARD_API_TOKENand sendAuthorization: Bearer <token>for all/api/*calls. - Keep dashboard bound to local host (
127.0.0.1) unless protected by a trusted reverse proxy/auth layer. - Remote API access is blocked by default; only enable with
WATON_DASHBOARD_ALLOW_REMOTE=1when you intentionally expose it. - The dashboard is isolated in
tools/dashboard/and does not modify core runtime modules. - It uses real WhatsApp connection flow (QR pairing + real send API).
- Status will show:
connectedwhen WA session is open and authenticatedconnectingwhile waiting QR/pairingdisconnectedwhen socket is not connected
- In disconnected state, you must connect and scan QR first before sending.
- UI follows WhatsApp Web style:
- left panel: chat list (auto-populates from real incoming/outgoing chats)
- right panel: active chat thread
- if new message arrives from another number, it appears in left list and can be opened in right thread
- footer composer is WhatsApp-like (attach/emoji placeholders + autosize text input + send button)
- Debug endpoint for root-cause tracing:
- open
http://127.0.0.1:8080/api/debug/summary - check
chat_count,chats, andevents_tailto verify whether incoming nodes are reaching dashboard runtime.
- open
For building bots or automated tools, use the App class. It manages the connection, storage, and message parsing automatically, providing a simple decorator-based router.
import asyncio
from waton.app.app import App
from waton.app.context import Context
# 1. Initialize App (creates SQLite session DB)
app = App(storage_path="my_session.db")
# 2. Listen for incoming messages
@app.message()
async def on_message(ctx: Context):
msg = ctx.message
print(f"Message received from {msg.from_jid}: {msg.text}")
# Auto-reply if there is text
if msg.text:
reply_text = f"Hello! You said: {msg.text}"
await ctx.app.messages.send_text(to_jid=msg.from_jid, text=reply_text)
# 3. Connection ready callback
@app.on_ready
async def on_ready(app_instance: App):
print("Bot is connected and ready to receive messages!")
# 4. Run the loop
if __name__ == "__main__":
app.run()If you want direct control over the WebSocket or need to build custom wrappers, you can use the WAClient directly. See examples/live_connect.py for a full example.
┌─────────────────────────────────────────────────┐
│ Your App │
├─────────────────────────────────────────────────┤
│ MessagesAPI │ ChatsAPI │ GroupsAPI │ ... │
├─────────────────────────────────────────────────┤
│ WAClient │
│ (WebSocket + Noise Protocol) │
├─────────────────────────────────────────────────┤
│ Signal Protocol (E2EE) │
│ ┌─────────────────────┐ │
│ │ Rust Crypto Core │ │
│ │ (Curve25519, AES) │ │
│ └─────────────────────┘ │
├─────────────────────────────────────────────────┤
│ SQLiteStorage (Sessions) │
└─────────────────────────────────────────────────┘
| Aspect | Waton (Python) | Baileys (Node.js) |
|---|---|---|
| Runtime | Python (~30-50MB) | Node.js (~50-100MB) |
| Package Size | ~500KB + deps | ~2MB + node_modules |
| Crypto Engine | Rust native (PyO3) | JS/WASM |
| Memory Usage | ~30-60MB | ~80-150MB |
| Startup Time | Faster | Slower (JIT) |
| Encryption Speed | Faster (native) | Slower (WASM) |
| Maturity | New | Mature |
| Community | Growing | Large |
- Building Python-native applications
- Running on resource-constrained environments (VPS, Raspberry Pi, Docker)
- Need minimal memory footprint
- Want native async/await integration with FastAPI, Django, etc.
- Already invested in Node.js ecosystem
- Need battle-tested stability for production
- Require extensive community support and plugins
- Python 3.11+
- WhatsApp account (phone number)
- Internet connection
Contributions are welcome! Please feel free to submit a Pull Request.
# Setup development environment
git clone https://github.com/kaivyy/waton.git
cd waton
pip install -e .[dev]
maturin develop
# Run tests
pytest tests/Sphinx docs source is in docs/source/ with RTD config in .readthedocs.yaml.
This release targets docs for Waton v0.1.4.
Local docs build:
pip install -e .[docs]
python -m sphinx -b html docs/source docs/build/htmlMIT License — feel free to use in personal and commercial projects.
This project is not affiliated with WhatsApp or Meta. Use responsibly and in accordance with WhatsApp's Terms of Service.
