Skip to main content

evolution-whatsapp

A modern Python client for Evolution API v2 — send and receive WhatsApp messages from Python.

PyPI Python Docs CI License: MIT

evolution-whatsapp is the Python twin of the R package evolution (source). It keeps the same mental model — a preconfigured client, snake_case send_* helpers, jid() — and adds a modern Python stack:

  • httpx with sync and async clients (EvoClient / AsyncEvoClient)
  • pydantic v2 models for webhook events + parse_webhook()
  • structlog structured, timed logging via verbose=True
  • local-file → base64 auto-encoding, automatic retries, typed errors
  • optional FastAPI webhook router and pandas as_dataframe() for pipelines

This package is an independent wrapper for the Evolution API and is not affiliated with WhatsApp or Meta.

Installation

pip install evolution-whatsapp
# with extras:
pip install "evolution-whatsapp[fastapi]"   # webhook_router()
pip install "evolution-whatsapp[pandas]"    # as_dataframe()

The distribution is evolution-whatsapp; the import name is evolution_api (the bare evolution import is already taken on PyPI — see DECISIONS.md).

Quick start

from evolution_api import EvoClient, jid

client = EvoClient(
    base_url="https://YOUR-HOST",
    api_key="...",            # or set the EVO_APIKEY env var
    instance="yourInstance",
    timeout=30,               # or the EVOLUTION_TIMEOUT env var (default 60)
)

# Send a simple message (verbose logs timing + a response preview)
client.send_text("5581999990000", "Hello from Python!", verbose=True)

jid("+55 81 99999-0000")     # -> "5581999990000@s.whatsapp.net"

Async

import asyncio
from evolution_api import AsyncEvoClient

async def main():
    async with AsyncEvoClient(base_url="https://YOUR-HOST", api_key="...", instance="inst") as client:
        await client.send_text("5581999990000", "Hello from async Python!")

asyncio.run(main())

Functions overview

Method Description Key arguments
EvoClient() / AsyncEvoClient() Preconfigured client base_url, api_key, instance, timeout
send_text() Plain text message number, text, delay, verbose
send_status() Status / story (text or media) type, content, caption
send_media() Image / video / document (URL, base64, or file) number, mediatype, mimetype, media, file_name
send_whatsapp_audio() Voice note (PTT) number, audio
send_sticker() Sticker (URL, base64, or file) number, sticker
send_location() Location pin number, latitude, longitude, name
send_contact() One or more contacts (auto wuid) number, contact
send_reaction() Emoji reaction key, reaction
send_buttons() Interactive buttons ⚠️ number, buttons
send_poll() Poll number, name, values
send_list() Interactive list ⚠️ number, sections, button_text
check_is_whatsapp() / check_numbers() Check if numbers are on WhatsApp numbers
connection_state() Channel connection / health check —
jid() Build a WhatsApp JID from a phone number number

⚠️ send_buttons() / send_list(): interactive buttons and lists are not supported on the Baileys (WhatsApp Web) connector and may be discontinued — they work only on the Cloud API connector. Both emit a warning and suggest send_poll().

💡 Local files: send_media(), send_sticker() and send_whatsapp_audio() accept local paths (including ~/...), auto-encoded to base64.

Examples

# Media from a URL
client.send_media("5581999990000", "image", "image/png",
                  media="https://www.r-project.org/logo/Rlogo.png",
                  file_name="Rlogo.png", caption="R Logo")

# Media from a local file (auto base64)
client.send_media("5581999990000", "document", "application/pdf",
                  media="~/report.pdf", file_name="report.pdf")

# Poll
client.send_poll("5581999990000", "Favourite language?",
                 ["R", "Python", "Julia"], selectable_count=1)

# Contact (wuid auto-generated)
client.send_contact("5581999990000", {
    "fullName": "Jane Doe", "phoneNumber": "+5581999990000",
    "organization": "Company Ltd.", "email": "jane@example.com",
})

# Check numbers
client.check_is_whatsapp(["5581999990000", "5511988887777"])

Receiving webhooks

from evolution_api.webhooks import parse_webhook

event = parse_webhook(request_json)
if event.event_type == "MESSAGES_UPSERT":
    print(event.data.key.remote_jid, event.data.message)

FastAPI router (extra fastapi):

from fastapi import FastAPI
from evolution_api.webhooks import webhook_router

async def on_event(event):
    if event.event_type == "MESSAGES_UPSERT":
        ...

app = FastAPI()
app.include_router(webhook_router(on_event))

Drain to a DataFrame (extra pandas):

from evolution_api.webhooks import as_dataframe
df = as_dataframe([parse_webhook(p) for p in payloads])

Configuration

Setting Default Description
EVO_APIKEY (env) — API key if api_key is not passed
EVO_INSTANCE (env) — Instance if instance is not passed
EVOLUTION_TIMEOUT (env) / timeout= 60 HTTP timeout in seconds
verbose=True per-call Structured logging with timing + response preview

Relationship to the R package

This is a faithful port of StrategicProjects/evolution (CRAN). See the Parity with the R package page in the docs and DECISIONS.md for where Python idioms intentionally differ.

License

MIT © 2026 André Leite, Hugo Vasconcelos & Diogo Bezerra. See LICENSE.

Metadata

Release files for evolution-whatsapp 0.1.1

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

Source distribution (sdist)

Source distribution for evolution-whatsapp 0.1.1
File Size Uploaded
evolution_whatsapp-0.1.1.tar.gz 180.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for evolution-whatsapp 0.1.1
File Interpreter ABI Platform
evolution_whatsapp-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 206.6 kB

Release files / evolution_whatsapp-0.1.1.tar.gz

Download URL evolution_whatsapp-0.1.1.tar.gz
Size 180.8 kB
Tags Source
SHA-256 checksum
How to use checksums
f0935fda3e87e68c37413670ae154aeec4469e9cf772c166da6aaecb7acd6d99
BLAKE2b-256 checksum
How to use checksums
9f2bcfc34de4cdbe4533388d0f35503a444f3901d419a9fa949f7e0729d9d9f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.

Transparency log

Release files / evolution_whatsapp-0.1.1-py3-none-any.whl

Download URL evolution_whatsapp-0.1.1-py3-none-any.whl
Size 25.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3a6dfbf3f060096348ee32b6ded9fa61a37f1bddbbbc0b7e01792caaf1e3d0eb
BLAKE2b-256 checksum
How to use checksums
e15789e31854a517e4fea9794c20b849a128af0756edb792125ded51d032880c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

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