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

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.2
File Size Uploaded
whatsplay-2.6.2.tar.gz 64.6 kB Details

Built distribution (wheel)

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

Total release size: 125.9 kB

Release files / whatsplay-2.6.2.tar.gz

Download URL whatsplay-2.6.2.tar.gz
Size 64.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c647bf836dd4c4df78e9de026601596c9ee8edeba32a4a16c8c54033ca751ab4
BLAKE2b-256 checksum
How to use checksums
b5f682ebde8e95755e18f74824fd3871eb2d64dd462b5b049a5f3fca85cc1ea0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

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

Download URL whatsplay-2.6.2-py3-none-any.whl
Size 61.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
92ec7fbae3b4bb8a5523354a2c8e86be0e057c3d5b9ed2ff2f2b989e1e4c8f89
BLAKE2b-256 checksum
How to use checksums
ab80384c5cbea63c4381eff56e4667ed68224ec55848d5e46e8b3ded67aa847a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

Release history Release notifications | RSS feed

This release

2.6.2 This release

2 release files

2.6.1

1 release file

2.6.0

1 release file

2.5.1

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.1

2 release files

2.2.0

2 release files

2.1.23

2 release files

2.1.22

2 release files

2.1.20

2 release files

2.1.19

2 release files

2.1.18

2 release files

2.1.17

2 release files

2.1.16

2 release files

2.0.16

2 release files

2.0.9

1 release file

2.0.8

1 release file

2.0.7

2 release files

2.0.6

2 release files

2.0.5

1 release file

2.0.1

1 release file

2.0.0

2 release files

1.9.9

2 release files

1.9.8

2 release files

1.9.7

2 release files

1.8.7

2 release files

1.8.6

2 release files

1.8.5

2 release files

1.8.4

2 release files

1.8.3

2 release files

1.8.2

2 release files

1.8.1

2 release files

1.8.0

2 release files

1.7.9

2 release files

1.7.7

2 release files

1.7.6

2 release files

1.7.5

2 release files

1.7.4

2 release files

1.7.3

2 release files

1.7.2

2 release files

1.7.1

2 release files

1.7.0

2 release files

1.6.0

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.6

2 release files

1.4.5

2 release files

1.3.5

2 release files

1.3.4

2 release files

1.3.3

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

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