Neonize
WhatsApp Automation for Python
A Python library for WhatsApp automation. A native Go core built on whatsmeow is compiled into a shared library and exposed to Python through a zero-copy FFI layer.
Getting Started | Features | Examples | Documentation | Contributing
Why Neonize?
| Go core performance | The WhatsApp multidevice protocol runs in Go, called directly through ctypes. No subprocesses, no HTTP bridges. |
| Python native | Fully typed, idiomatic API. Sync and async clients with identical surfaces. |
| Persistent sessions | SQLite or PostgreSQL. Pair once, reconnect forever. |
| Enterprise ready | Structured error hierarchy, FFmpeg diagnostics, robust FFI with retry logic. |
Features
Messaging
- Send and receive text, images, videos, documents, audio, voice notes, stickers
- Message replies, reactions, polls, interactive buttons and lists
- Receipt and presence tracking
Groups and Channels
- Create, update, and manage groups (name, description, photo, participants)
- Newsletter/channel operations: fetch messages, update profile, send media
Contacts and Presence
- Profile picture retrieval, push name updates
- Typing and recording indicators
- Contact sync and blocklist management
Architecture
- Sync (
NewClient) and async (NewAClient) with identical APIs - Multi-session support via
ClientFactory - Event-driven with 37+ typed event classes
- QR code and phone-number pairing
Getting Started
Prerequisites
- Python 3.10 or newer
- FFmpeg (required for media operations: stickers, audio, video, thumbnails)
Installation
pip install neonize
Quick Start
from neonize.client import NewClient
from neonize.events import ConnectedEv, MessageEv
client = NewClient("session.db")
@client.event(ConnectedEv)
def on_connected(client: NewClient, _: ConnectedEv) -> None:
print("Connected")
@client.event(MessageEv)
def on_message(client: NewClient, message: MessageEv) -> None:
text = message.Message.conversation or message.Message.extendedTextMessage.text
if text == "ping":
client.reply_message("pong", message)
client.connect()
Async Quick Start
import asyncio
from neonize.aioze.client import NewAClient
from neonize.aioze.events import ConnectedEv, MessageEv
client = NewAClient("async_session.db")
@client.event(ConnectedEv)
async def on_connected(client: NewAClient, _: ConnectedEv) -> None:
print("Connected")
@client.event(MessageEv)
async def on_message(client: NewAClient, message: MessageEv) -> None:
text = message.Message.conversation or message.Message.extendedTextMessage.text
if text == "ping":
await client.reply_message("pong", message)
async def main():
await client.connect()
await client.idle()
asyncio.run(main())
Examples
Sending Media
from neonize.utils.jid import build_jid
jid = build_jid("1234567890", "s.whatsapp.net")
# Text
client.send_message(jid, "Hello from Neonize")
# Image with caption
with open("photo.jpg", "rb") as f:
msg = client.build_image_message(f.read(), caption="Photo", mime_type="image/jpeg")
client.send_message(jid, message=msg)
# Document
with open("report.pdf", "rb") as f:
msg = client.build_document_message(
f.read(), filename="report.pdf", mime_type="application/pdf"
)
client.send_message(jid, message=msg)
Handling Incoming Messages
from neonize.events import MessageEv, ReceiptEv, PresenceEv
from neonize.utils.message import extract_text
@client.event(MessageEv)
def on_message(client: NewClient, event: MessageEv) -> None:
text = extract_text(event.Message)
sender = event.Info.MessageSource.Sender
if text == "help":
client.reply_message("Available commands: help, time", event)
@client.event(ReceiptEv)
def on_receipt(client: NewClient, event: ReceiptEv) -> None:
print(f"Receipt: {event.Receipt.Type} for {event.MessageIDs}")
@client.event(PresenceEv)
def on_presence(client: NewClient, event: PresenceEv) -> None:
print(f"{event.MessageSource.Sender} is {event.Presence}")
Group Management
from neonize.utils.jid import build_jid
# Create group
participants = [build_jid("1234567890"), build_jid("0987654321")]
info = client.create_group("Project Team", participants)
print(f"Group created: {info.JID}")
# Update settings
client.set_group_name(info.JID, "New Name")
client.set_group_description(info.JID, "Updated description")
# Manage participants
client.update_group_participants(info.JID, [build_jid("5555555555")], "add")
Multi-Session (Async)
import asyncio
from neonize.aioze.client import ClientFactory, NewAClient
from neonize.aioze.events import MessageEv, ConnectedEv
factory = ClientFactory("multisession.db")
# Load existing sessions
for device in factory.get_all_devices():
factory.new_client(device.JID)
# Pair a new account
factory.new_client(uuid="second-account", new_device=True)
@factory.event(ConnectedEv)
async def on_connected(client: NewAClient, event: ConnectedEv) -> None:
print("Client connected")
@factory.event(MessageEv)
async def on_message(client: NewAClient, event: MessageEv) -> None:
if event.Message.conversation == "ping":
await client.reply_message("pong", event)
async def main():
await factory.run()
await factory.idle_all()
asyncio.run(main())
Integration with FastAPI
from contextlib import asynccontextmanager
from fastapi import FastAPI
from neonize.aioze.client import NewAClient
from neonize.aioze.events import MessageEv
from neonize.utils.jid import build_jid
client = NewAClient("fastapi_bot")
@client.event(MessageEv)
async def on_message(client: NewAClient, event: MessageEv) -> None:
if event.Message.conversation == "/status":
await client.reply_message("API is running", event)
@asynccontextmanager
async def lifespan(app: FastAPI):
await client.connect()
yield
await client.disconnect()
app = FastAPI(lifespan=lifespan)
@app.get("/send")
async def send(phone: str, message: str):
await client.send_message(build_jid(phone), message)
return {"status": "sent"}
Database Configuration
Neonize stores session data in a database. The default is SQLite, which works well for development and single-instance deployments.
# SQLite (default)
client = NewClient("bot", database="./session.db")
# PostgreSQL (recommended for production)
client = NewClient("bot", database="postgres://user:pass@localhost:5432/neonize")
# Connection pooling
client = NewClient(
"bot", database="postgres://user:pass@localhost/neonize?pool_min_conns=5&pool_max_conns=20"
)
# In-memory (testing only)
client = NewClient("bot", database=":memory:")
Project Structure
neonize/
├── examples/ # Runnable example bots
│ ├── basic.py
│ ├── async_basic.py
│ ├── multisession.py
│ ├── multisession_async.py
│ └── paircode.py
├── goneonize/ # Go shared library (FFI core)
│ ├── main.go
│ ├── defproto/ # Generated protobuf definitions
│ └── utils/ # Go encoder helpers
├── neonize/ # Python package
│ ├── __init__.py
│ ├── client.py # Sync client (NewClient)
│ ├── aioze/ # Async client (NewAClient)
│ ├── events.py # Event types and dispatcher
│ ├── exc.py # Exception hierarchy
│ ├── ext/ # Extensions (interactive messages)
│ ├── proto/ # Python protobuf bindings
│ └── utils/ # Helpers (JID, media, FFmpeg, etc.)
├── docs/ # Zensical documentation source
├── tools/ # Build, release, and dev scripts
└── pyproject.toml # Project metadata and dependencies
Contributing
We welcome contributions. See CONTRIBUTING.md for the branching model, conventional-commit standards, and release process.
# Clone and setup
git clone https://github.com/krypton-byte/neonize.git
cd neonize
uv sync --dev
# Build the Go shared library
CGO_ENABLED=1 uv run task build goneonize
# Run tests
uv run --with pytest python -m pytest
# Lint
uv run ruff check .
uv run ruff format --check .
Workflow: feature branches target dev, merges to master trigger the
automated release pipeline.
Documentation
Full documentation is available at neonize.readthedocs.io
Related Projects
| Project | Description |
|---|---|
| Thundra | High-level bot framework built on Neonize |
| Tryx | Rust-powered Python SDK for WhatsApp automation |
| Neonize Dart | Dart/Flutter wrapper for Neonize |
| Whatsmeow | Go WhatsApp Web API library that powers Neonize |
License
This project is licensed under the Apache License 2.0. See LICENSE for details.
Built by krypton-byte and contributors
Metadata
Release files for neonize 0.5.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| neonize-0.5.2-py310-none-win_arm64.whl | Python 3.10 | none | Windows ARM64 | Details |
| neonize-0.5.2-py310-none-win_amd64.whl | Python 3.10 | none | Windows x86-64 | Details |
| neonize-0.5.2-py310-none-win32.whl | Python 3.10 | none | Windows x86-32 | Details |
| neonize-0.5.2-py310-none-manylinux2014_x86_64.whl | Python 3.10 | none | Linux glibc 2.17+ x86-64 | Details |
| neonize-0.5.2-py310-none-manylinux2014_s390x.whl | Python 3.10 | none | Linux glibc 2.17+ IBM System/390x | Details |
| neonize-0.5.2-py310-none-manylinux2014_i686.whl | Python 3.10 | none | Linux glibc 2.17+ x86-32 | Details |
| neonize-0.5.2-py310-none-manylinux2014_aarch64.whl | Python 3.10 | none | Linux glibc 2.17+ ARM64 | Details |
| neonize-0.5.2-py310-none-macosx_12_0_x86_64.whl | Python 3.10 | none | macOS 12.0+ x86-64 | Details |
| neonize-0.5.2-py310-none-macosx_12_0_arm64.whl | Python 3.10 | none | macOS 12.0+ ARM64 | Details |
Total release size: 64.3 MB
Release files / neonize-0.5.2-py310-none-win_arm64.whl
| Download URL | neonize-0.5.2-py310-none-win_arm64.whl |
|---|---|
| Size | 6.4 MB |
| Tags | Python 3.10 Windows ARM64 |
|
SHA-256 checksum How to use checksums |
9baeac04b085aa8e47a2c866fad9908a185097246a49ddac288d2825b2d08d2e
|
|
BLAKE2b-256 checksum How to use checksums |
0488a643ca2cbc18100d5b5495d57b8b7a3b584a8ce52cb3f15317380ca26569
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / neonize-0.5.2-py310-none-win_amd64.whl
| Download URL | neonize-0.5.2-py310-none-win_amd64.whl |
|---|---|
| Size | 7.0 MB |
| Tags | Python 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
08fa22aac7b8b6b66f2f53195cb12fa990685c89bd99a0ff17f346a0b4f4710a
|
|
BLAKE2b-256 checksum How to use checksums |
1fd66d63715700c0cb5ea4525c8328ae58700bfa7723f8b57212301fae5835a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / neonize-0.5.2-py310-none-win32.whl
| Download URL | neonize-0.5.2-py310-none-win32.whl |
|---|---|
| Size | 7.0 MB |
| Tags | Python 3.10 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
a4630048fe0e13a8d460bf128e46ae10845a4ae8ce4fafa2a0bf5669db696a87
|
|
BLAKE2b-256 checksum How to use checksums |
8c7602fe7ce9b734b1fe015d0973c3c0153d0555fe86b3fcd46020eb6e56ccc8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / neonize-0.5.2-py310-none-manylinux2014_x86_64.whl
| Download URL | neonize-0.5.2-py310-none-manylinux2014_x86_64.whl |
|---|---|
| Size | 7.1 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3.10 |
|
SHA-256 checksum How to use checksums |
d737efc03d3a4db0a89d1efac3b55199472eb57acda041927ca8efc797872b69
|
|
BLAKE2b-256 checksum How to use checksums |
9d215230e201176c1d405bb291dda66bb31efe85f78ac02ef60bc2a6f634990b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / neonize-0.5.2-py310-none-manylinux2014_s390x.whl
| Download URL | neonize-0.5.2-py310-none-manylinux2014_s390x.whl |
|---|---|
| Size | 7.1 MB |
| Tags | Linux glibc 2.17+ IBM System/390x Python 3.10 |
|
SHA-256 checksum How to use checksums |
bc0874e3abaab520433b9456b020c973885353af1caa2a73c0c71e866973e3ce
|
|
BLAKE2b-256 checksum How to use checksums |
50c0db72411b2fb31cc4db7393287696ae38e3c1f4a076140a13ff09b453750a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / neonize-0.5.2-py310-none-manylinux2014_i686.whl
| Download URL | neonize-0.5.2-py310-none-manylinux2014_i686.whl |
|---|---|
| Size | 9.7 MB |
| Tags | Linux glibc 2.17+ x86-32 Python 3.10 |
|
SHA-256 checksum How to use checksums |
96ea2eb144064a5ae7667709021f4b9515e1206f163c267349ecbc531369ecdc
|
|
BLAKE2b-256 checksum How to use checksums |
b98d1924d19e45ec54528fd5d7223e8319cecf944d50cd8e617ba711af31a543
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / neonize-0.5.2-py310-none-manylinux2014_aarch64.whl
| Download URL | neonize-0.5.2-py310-none-manylinux2014_aarch64.whl |
|---|---|
| Size | 6.6 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3.10 |
|
SHA-256 checksum How to use checksums |
258fc41a72b60854255815c697ea24db14d96d6205d10e9524db3318615e3ca3
|
|
BLAKE2b-256 checksum How to use checksums |
ec54be02d1f3eabdb8f7659f16d0ac7c28b75f78bd36fdf151117b33dd49dd7e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / neonize-0.5.2-py310-none-macosx_12_0_x86_64.whl
| Download URL | neonize-0.5.2-py310-none-macosx_12_0_x86_64.whl |
|---|---|
| Size | 6.8 MB |
| Tags | Python 3.10 macOS 12.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
7065552a7d4acfb7327f845ba176f887125a20578d5bfafb683ecb870d12c41b
|
|
BLAKE2b-256 checksum How to use checksums |
74fbee1011d67def59535feb15b92d21a66f113af3a6c77a51567ef2390c7f74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / neonize-0.5.2-py310-none-macosx_12_0_arm64.whl
| Download URL | neonize-0.5.2-py310-none-macosx_12_0_arm64.whl |
|---|---|
| Size | 6.4 MB |
| Tags | Python 3.10 macOS 12.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
670376f5479c56da35fce80ba3c0f98540a46d77364b04f4a6405f6dda783617
|
|
BLAKE2b-256 checksum How to use checksums |
93a5316bdcd25baf2300c34ab88efb13def89ba4f0b828d965f5df74fdbb57af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|