Async WhatsApp Web (Multi-Device) protocol client in pure Python, inspired by Baileys.
Project description
pyaileys
Async WhatsApp Web (Multi-Device) protocol client in pure Python, inspired by Baileys.
What This Is
- WebSocket protocol client (no browser automation)
- QR pairing + multi-device session persistence (Baileys-like auth folder)
asyncioAPI for receiving stanzas/events and sending messages- Minimal runtime deps:
websockets,protobuf,cryptography
Status
This is an early-stage protocol client.
What works today:
- MD session login + QR pairing
- 1:1 Signal E2E (
pkmsg/msg) decrypt/encrypt - Group Signal E2E (
skmsg) decrypt/encrypt (Sender Keys) - Text send (1:1 multi-device fanout, groups via Sender Keys)
- Typing/recording indications (
chatstate) - Media send (image, PTT voice note, documents, video, stickers, static location, contacts)
- Media download/decrypt (image, audio/PTT, documents, video, stickers)
- History Sync ingestion into an in-memory store
- Best-effort contact/profile metadata (names from history sync +
notifypush names, profile picture URL, status/about)
Limitations (Important)
- Media thumbnails + waveform: not generated automatically (you can supply
jpeg_thumbnail/waveform) - App-state sync supports snapshot + patch processing and updates the in-memory store (best-effort model application)
- App-state sync depends on app-state keys from the primary phone; the client requests missing keys, but very old sessions may require re-pairing
- Chat/contact model: minimal demo store; contact names/profile are best-effort
- API stability: no guarantees yet (pre-1.0)
Legal / Safety
This project is not affiliated with WhatsApp/Meta. Using unofficial clients may violate WhatsApp Terms of Service. You are responsible for compliance and for preventing abuse (spam/automation).
Installation
pip install pyaileys
Optional (pretty QR output in terminal + SVG QR file):
pip install "pyaileys[qrcode]"
Quickstart (Pair + Connect)
import asyncio
from pyaileys import WhatsAppClient
async def main() -> None:
client, auth_state = await WhatsAppClient.from_auth_folder("./auth")
async def on_update(update) -> None:
# update is `pyaileys.socket.ConnectionUpdate`
if update.qr:
print("QR string:", update.qr)
if update.connection:
print("connection:", update.connection)
async def on_creds_update(_creds) -> None:
await auth_state.save_creds()
client.on("connection.update", on_update)
client.on("creds.update", on_creds_update)
await client.connect()
await auth_state.save_creds()
# keep the process alive
await asyncio.Event().wait()
asyncio.run(main())
Contacts & Profiles (Best-Effort)
WhatsApp Web does not provide a simple "address book" API. In practice, name/profile info comes from multiple places:
- History sync conversations (
displayName/name/username) - Incoming message stanzas (
notifypush name) - Explicit queries (e.g. profile picture URL, about/status)
This library exposes a small convenience layer:
dn = client.get_display_name("12345@s.whatsapp.net")
contact = client.get_contact("12345@s.whatsapp.net")
pic = await client.profile_picture_url("12345@s.whatsapp.net", picture_type="preview")
statuses = await client.fetch_status("12345@s.whatsapp.net")
Notes:
get_display_name()prefers a "saved name" (history sync) and falls back to push name (notify).fetch_status()may return""if the status is hidden/blocked, andNoneif unavailable.
Examples
Kitchen sink (interactive):
python examples/demo_app.py --auth ./auth --log-nodes
Simple CLI (decrypt + store + send text/media, includes appsync):
python examples/simple_cli.py --auth ./auth
Automated end-to-end smoke test against your real linked account:
tools/e2e_smoke.sh --jid 4527148803@s.whatsapp.net --auth ./auth
This script drives examples/simple_cli.py, sends test messages/media, downloads media back, and prints a pass/fail checklist.
QR-only helper (writes qr.svg into the auth dir if qrcode extra is installed):
python examples/login_qr.py
Development
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
ruff check .
ruff format .
mypy src/pyaileys
pytest -q
Optional (recommended): install git pre-commit hooks to auto-run formatting & lint on commit:
pre-commit install
Releasing to PyPI (Trusted Publishing)
This repo includes a GitHub Actions workflow (.github/workflows/release.yml) that publishes to PyPI when you push a
tag like v0.1.0.
- Bump versions in
pyproject.tomlandsrc/pyaileys/__init__.py - Tag and push:
git tag vX.Y.Z && git push --tags
Regenerating Generated Files
wabinary token tables are generated from a Baileys checkout:
git clone https://github.com/WhiskeySockets/Baileys.git /path/to/Baileys
python3 tools/gen_wabinary_constants.py --baileys /path/to/Baileys
proto/WAProto.proto is vendored from Baileys and patched to satisfy protoc:
python3 tools/patch_waproto_for_protoc.py
protoc -Iproto --python_out=src/pyaileys/proto proto/WAProto.proto
Credits
- Inspired by the Baileys TypeScript library (MIT): https://github.com/WhiskeySockets/Baileys
Contributing
See CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SECURITY.md.
Simple chat CLI (includes appsync for full app-state sync):
python examples/simple_cli.py --auth ./auth
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyaileys-0.1.4.tar.gz.
File metadata
- Download URL: pyaileys-0.1.4.tar.gz
- Upload date:
- Size: 225.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3538fb23a5d7ed0db63edb14c62c6ca432ddf362706663c6405e0fe1d304407
|
|
| MD5 |
f16623c39e160b153fa71679260f83ee
|
|
| BLAKE2b-256 |
4024a7620125e4810992f4ebd796712ca67b21dc26672e70b22ec52708125445
|
Provenance
The following attestation bundles were made for pyaileys-0.1.4.tar.gz:
Publisher:
release.yml on atiti/pyaileys
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyaileys-0.1.4.tar.gz -
Subject digest:
c3538fb23a5d7ed0db63edb14c62c6ca432ddf362706663c6405e0fe1d304407 - Sigstore transparency entry: 962781168
- Sigstore integration time:
-
Permalink:
atiti/pyaileys@4d0da1a30d4a064e1f9ecb3a7f1b1feff003a774 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/atiti
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4d0da1a30d4a064e1f9ecb3a7f1b1feff003a774 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyaileys-0.1.4-py3-none-any.whl.
File metadata
- Download URL: pyaileys-0.1.4-py3-none-any.whl
- Upload date:
- Size: 184.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae5af59b80a3e59a153949e2ea7d5b476c67086def3152288d0773281b39e834
|
|
| MD5 |
7562a0e33ded130e99db59acfe4be2fc
|
|
| BLAKE2b-256 |
d9112f2abe396c34051fe7216a471b642f570fdef91e38a7120e2187726bfc61
|
Provenance
The following attestation bundles were made for pyaileys-0.1.4-py3-none-any.whl:
Publisher:
release.yml on atiti/pyaileys
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyaileys-0.1.4-py3-none-any.whl -
Subject digest:
ae5af59b80a3e59a153949e2ea7d5b476c67086def3152288d0773281b39e834 - Sigstore transparency entry: 962781180
- Sigstore integration time:
-
Permalink:
atiti/pyaileys@4d0da1a30d4a064e1f9ecb3a7f1b1feff003a774 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/atiti
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4d0da1a30d4a064e1f9ecb3a7f1b1feff003a774 -
Trigger Event:
push
-
Statement type: