Skip to main content

Async WhatsApp Web (Multi-Device) protocol client in pure Python, inspired by Baileys.

Project description

pyaileys

CI PyPI Python Versions License Code style: ruff

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)
  • asyncio API 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 + notify push 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 (notify push 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, and None if 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.toml and src/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

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

pyaileys-0.1.4.tar.gz (225.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyaileys-0.1.4-py3-none-any.whl (184.3 kB view details)

Uploaded Python 3

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

Hashes for pyaileys-0.1.4.tar.gz
Algorithm Hash digest
SHA256 c3538fb23a5d7ed0db63edb14c62c6ca432ddf362706663c6405e0fe1d304407
MD5 f16623c39e160b153fa71679260f83ee
BLAKE2b-256 4024a7620125e4810992f4ebd796712ca67b21dc26672e70b22ec52708125445

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaileys-0.1.4.tar.gz:

Publisher: release.yml on atiti/pyaileys

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for pyaileys-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ae5af59b80a3e59a153949e2ea7d5b476c67086def3152288d0773281b39e834
MD5 7562a0e33ded130e99db59acfe4be2fc
BLAKE2b-256 d9112f2abe396c34051fe7216a471b642f570fdef91e38a7120e2187726bfc61

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyaileys-0.1.4-py3-none-any.whl:

Publisher: release.yml on atiti/pyaileys

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page