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.5

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.5
File Size Uploaded Provenance
whatsplay-2.6.5.tar.gz 79.2 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 148.3 kB

Release files / whatsplay-2.6.5.tar.gz

Download URL whatsplay-2.6.5.tar.gz
Size 79.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b3e454230c075b01f5b1412c4d1e98b45049220c75fa06b417bae2e380f0ec5e
BLAKE2b-256 checksum
How to use checksums
0c214eb90e316242b4caf694179ce60a6fe45a5a10008da38f0379a393b4f73a
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.5-py3-none-any.whl

Download URL whatsplay-2.6.5-py3-none-any.whl
Size 69.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
75a218a704366578d2f97b41b63c1e1bddf50ed320d416e6a1044b2b6f003e76
BLAKE2b-256 checksum
How to use checksums
bcd07697bce10333efbc84d2e84f791a2856618758330de2b727ad5cad97d3fa
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.5

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.5 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