Skip to main content

WhatsPlay 🚀

Modern WhatsApp Web automation with Playwright and Python

PyPI version Downloads Python License Tests


✨ Features

  • Stable selectors — attribute-based (data-pre-plain-text, aria-label, data-testid), not minified CSS classes that break on every WA update
  • Multi-language — works with WhatsApp Web in Spanish and English out of the box
  • Voice messages — duration and download support
  • Persistent sessions — scan QR once, reuse the session
  • Unread chat detection — multiple heuristics (badges, font-weight, aria-labels)
  • Message filtering — filter by sender, text, or custom rules
  • File & media support — images, audio, documents
  • Event-driven — on_start, on_message, on_unread_chat, etc.
  • Headless mode — works on servers without GUI
  • 14k+ downloads on PyPI — battle-tested selectors

Quick Start

pip install whatsplay
python -m playwright install chromium
import asyncio
from pathlib import Path
from whatsplay import Client
from whatsplay.auth import LocalProfileAuth

async def main():
    auth = LocalProfileAuth(Path.home() / "whatsapp_session")
    client = Client(auth=auth, headless=False)

    @client.event("on_unread_chat")
    async def on_unread_chat(chat_name, messages):
        await client.send_message(chat_name, "🤖 Automatizado con WhatsPlay!")

    await client.start()

asyncio.run(main())

📦 Installation

From PyPI

pip install whatsplay

After installing, download the Playwright browser:

python -m playwright install chromium

From source

git clone https://github.com/markbus-ai/whatsplay.git
cd whatsplay
pip install -e .
python -m playwright install chromium

📖 Usage Guide

Basic connection

from pathlib import Path
from whatsplay import Client
from whatsplay.auth import LocalProfileAuth

data_dir = Path.home() / "whatsapp_session"
data_dir.mkdir(parents=True, exist_ok=True)

auth = LocalProfileAuth(data_dir)
client = Client(auth=auth, headless=False)

Events

@client.event("on_start")
async def on_start():
    print("✅ Client started")

@client.event("on_auth")
async def on_auth():
    print("📸 Scan the QR code")

@client.event("on_unread_chat")
async def on_unread_chat(chat_name, messages):
    print(f"📩 Unread messages in {chat_name}")
    for msg in messages:
        print(f"  {msg.sender}: {msg.text}")

Sending messages

# By chat name
await client.send_message("Mi Grupo", "Hola!")

# By phone number (with country code)
await client.send_message("+5491123456789", "Mensaje directo")

Voice messages

@client.event("on_unread_chat")
async def handler(chat_name, messages):
    for msg in messages:
        if msg.type == "voice":
            print(f"🎤 Voice message: {msg.duration}s")
            # Download the audio
            audio = await client.download_audio(msg)

📚 Examples

The examples/ directory includes ready-to-run scripts:

File Description
simple_example.py Basic event-driven auto-reply
open_example.py Open a specific chat programmatically
search_example.py Search conversations with detailed results
verify_selectors.py E2E validation of all selectors against live WA Web
investigate_voice.py Live DOM investigation for voice message structure
wsp.py CLI tool for quick message sending

📊 PyPI Stats

Period Downloads
All time 14,700+
Last month 2,300+
Last week 190+

🛠 Development

Setup

pip install -e ".[dev]"
python -m playwright install chromium

Running tests

pytest tests/ -v

34 tests passing with 0 warnings.


🗺 Roadmap

Completed ✅

  • Async event system
  • Persistent session (QR once)
  • Message sending / receiving
  • File & media support
  • Voice message detection & duration
  • Unread chat detection with multiple heuristics
  • Search with fallback strategies
  • Stable attribute-based selectors (no more fragile CSS classes)
  • Multi-language (Spanish / English)
  • Filter system (MessageFilter)
  • Virtualized list support

In progress 🚧

  • Message reactions API
  • Group management API
  • Webhook integration

Planned 🔮

  • Multi-account simultaneous support
  • Monitoring dashboard
  • Native TypeScript definitions

❓ FAQ

Is it safe? It uses WhatsApp Web's official interface — as safe as using WhatsApp in a browser.

Can WhatsApp detect it? There's always risk with automation. Use responsibly.

Does it work headless? Yes, Playwright's headless mode is supported.

Does it work in Spanish? Yes, all selectors handle both Spanish and English WhatsApp Web locales.


🐞 Report a bug

Open an issue with:

  • Problem description
  • Reproduction steps
  • Python version and dependencies
  • Relevant logs

🤝 Contributing

  1. Fork the repo
  2. Create a branch (git checkout -b feature/amazing)
  3. Commit (git commit -am 'Add amazing feature')
  4. Push (git push origin feature/amazing)
  5. Open a Pull Request

📄 License

Apache 2.0


⭐ Star on GitHub if you find it useful

Made with ❤️ by @markbus-ai

Metadata

Release files for whatsplay 2.6.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for whatsplay 2.6.4
File Size Uploaded Provenance
whatsplay-2.6.4.tar.gz 79.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for whatsplay 2.6.4
File Interpreter ABI Platform
whatsplay-2.6.4-py3-none-any.whl Python 3 none any Details

Total release size: 148.2 kB

Release files / whatsplay-2.6.4.tar.gz

Download URL whatsplay-2.6.4.tar.gz
Size 79.4 kB
Tags Source
SHA-256 checksum
How to use checksums
5d626dfac513457abf2bb1ffdec097e2f13f579f9d22656005856fab4d65817b
BLAKE2b-256 checksum
How to use checksums
0cad9359fad6c10cb2c16e6f0b783f9866be5effe2fa6b193637d35119b2efaf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.12

Release files / whatsplay-2.6.4-py3-none-any.whl

Download URL whatsplay-2.6.4-py3-none-any.whl
Size 68.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
508f7c25083d80c4020ff7007e9ec92ec605b39b7b390ea21a97ea13da67f518
BLAKE2b-256 checksum
How to use checksums
d7350d055e4f991746ff0e31a492ac15934d51ac6c69811912346b26bfb4f25b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.12

Security for whatsplay 2.6.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

2.6.4 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page