pywa - Python WhatsApp Bot Framework
raw JSON → 3.9.0 verified Fri May 01 auth: no python
Pywa (Python WhatsApp API) is a powerful, fast, and easy-to-use framework for building WhatsApp bots in Python. It wraps the WhatsApp Business API (Cloud API) and provides a clean, event-driven interface for handling messages, callbacks, and sending rich media. Version 3.9.0 requires Python >=3.10. The library follows a monthly release cadence.
pip install pywa Common errors
error AttributeError: 'WhatsApp' object has no attribute 'on_message' ↓
cause Using an outdated version where the decorator syntax was different or not yet supported. Also, forgetting to import the decorator from pywa.
fix
Update pywa to >=3.0.0 and use
from pywa import WhatsApp and decorate with @wa.on_message(). error TypeError: __init__() got multiple values for argument 'phone_id' ↓
cause Passing arguments positionally in wrong order; `verify_token` is now the first positional argument (if using positional style) or better use keyword arguments.
fix
Use keyword arguments:
WhatsApp(phone_id='...', token='...', server='...', verify_token='...') error requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: / (Caused by NewConnectionError) ↓
cause The server argument expects the full URL to the webhook endpoint. If you omit the trailing slash or don't start with http://, it may fail.
fix
Set
server='http://localhost:8080' (include http:// and no trailing slash) or use a valid URL. error ValueError: The 'verify_token' must be a non-empty string ↓
cause Passing an empty string or None as verify_token; it must be provided and non-empty.
fix
Provide a non-empty string as
verify_token parameter. Warnings
breaking In pywa 3.x, the constructor changed: `verify_token` is now positional (first argument) and `server` parameter changed to accept a string URL instead of a tuple. Old code passing arguments positionally may break. ↓
fix Use keyword arguments: WhatsApp(phone_id=..., token=..., server=..., verify_token=...)
deprecated The `on_callback_button` handler is deprecated since 3.4.0; use `on_callback_query` instead. ↓
fix Replace `@wa.on_callback_button()` with `@wa.on_callback_query()`
gotcha Webhook signature verification is not mandatory by default. If you don't set a `verify_token`, you risk processing unverified requests. Always set a secure `verify_token` in production. ↓
fix Pass a `verify_token` in the constructor and verify on your server platform (e.g., using the 'cryptography' library if you enable signature checking).
breaking In pywa 3.0, the `send_message` method no longer returns the raw API response as `requests.Response` but returns a `MessageStatus` object. Accessing `.json()` on the return value will fail. ↓
fix Use the `id` attribute of the returned `MessageStatus` object instead of parsing the response.
Imports
- WhatsApp
from pywa import WhatsApp - Message
from pywa.types import Message - CallbackButton
from pywa.types import CallbackButton - CallbackData wrong
from pywa.types import CallbackData (still correct but in older versions it was in pywa.types.callback)correctfrom pywa.types import CallbackData
Quickstart
import os
from pywa import WhatsApp
wa = WhatsApp(
phone_id=os.environ['PHONE_ID'],
token=os.environ['TOKEN'],
server='http://localhost:8080',
verify_token='my_verify_token'
)
@wa.on_message()
def handle_message(client: WhatsApp, message):
client.send_message(to=message.from_user, text=f'You said: {message.text}')
wa.run()