edgymeow
v0.0.18
Published
EdgyMeow - WhatsApp WebSocket RPC Server with JSON-RPC 2.0 protocol
Maintainers
Readme
EdgyMeow
WebSocket JSON-RPC 2.0 API for QR Based WhatsApp Web.
Installation
npm install edgymeowPre-built binaries are automatically downloaded for your platform (Linux, macOS, Windows).
Quick Start
# Start the API server
npx edgymeow start
# Check status
npx edgymeow status
# Stop the server
npx edgymeow stopArchitecture
┌─────────────────────────────────────────────────────────┐
│ Your Application │
│ (Node.js, Python, Go, etc.) │
└─────────────────────────┬───────────────────────────────┘
│
│ WebSocket (JSON-RPC 2.0)
│
▼
┌─────────────────────────────────────────────────────────┐
│ EdgyMeow Server (:9400) │
│ ┌─────────────────────────────────────────────────┐ │
│ │ • JSON-RPC 2.0 Handler │ │
│ │ • Rate Limiter (anti-ban protection) │ │
│ │ • Event Emitter (real-time notifications) │ │
│ │ • Message History Store (SQLite) │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ whatsmeow (Go Library) │
│ WhatsApp Web Protocol │
└─────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ WhatsApp Servers │
└─────────────────────────────────────────────────────────┘
Data Storage:
┌─────────────────────────────────────────────────────────┐
│ data/ │
│ ├── whatsapp.db (SQLite: session, contacts, history)│
│ └── groups.json (Group cache) │
└─────────────────────────────────────────────────────────┘CLI Commands
npx edgymeow start # Start API server (background)
npx edgymeow stop # Stop API server
npx edgymeow restart # Restart API server
npx edgymeow status # Check if running
npx edgymeow api --foreground # Run in foreground (for Docker)
npx edgymeow build # Build from source (requires Go)
npx edgymeow web # Start standalone web dashboard (no Python needed)
npx edgymeow dev # Start API + web dashboard together
# Custom port
npx edgymeow start --port 8080Web Dashboard
A standalone static web client that connects directly to the Go WebSocket backend -- no Python/Flask required:
# Start API server first
npx edgymeow start
# Then start the web dashboard
npx edgymeow web --port 3001 --ws-port 9400
# Or start both together
npx edgymeow devOpen http://localhost:3001 for the full dashboard with pages for messaging, groups, contacts, and settings.
The web client is in web/client/ and can also be served by any static file server. Set window.WS_PORT to point to the Go backend port.
Docker
FROM node:20-alpine
WORKDIR /app
RUN npm init -y && npm install edgymeow
RUN mkdir -p /app/data
ENV PORT=9400
EXPOSE 9400
CMD ["npx", "edgymeow", "api", "--foreground"]API Reference
Connect via WebSocket to ws://localhost:9400/ws/rpc and send JSON-RPC 2.0 requests.
Connection & Status
| Method | Description |
|--------|-------------|
| status | Get connection status (connected, has_session, running, pairing, device_id) |
| start | Start WhatsApp service |
| stop | Stop WhatsApp service |
| restart | Full reset: logout, clear all caches, cleanup, start fresh |
| reset | Reset session (logout and delete credentials) |
| diagnostics | Get detailed diagnostics information |
| qr | Get QR code for pairing (code, image_data as base64 PNG) |
Messaging
| Method | Parameters | Description |
|--------|------------|-------------|
| send | phone or group_id, type, message/media_data/location/contact | Send message |
| media | message_id | Download media from received message (returns base64) |
| typing | jid, state (composing/paused) | Send typing indicator |
| presence | status (available/unavailable) | Set online/offline status |
| mark_read | message_ids[], chat_jid, sender_jid | Mark messages as read |
Message Types: text, image, video, audio, document, sticker, location, contact
Contacts
| Method | Parameters | Description |
|--------|------------|-------------|
| contacts | query (optional) | List all contacts with saved names |
| contact_info | phone | Get full contact info (name, business status, profile pic) |
| contact_check | phones[] | Check if numbers are on WhatsApp |
| contact_profile_pic | jid, preview | Get profile picture (returns URL and base64) |
Groups
| Method | Parameters | Description |
|--------|------------|-------------|
| groups | - | List all groups |
| group_info | group_id | Get group details (name, topic, participants, admins) |
| group_update | group_id, name, topic | Update group name/description |
| group_participants_add | group_id, participants[] | Add members to group |
| group_participants_remove | group_id, participants[] | Remove members from group |
| group_invite_link | group_id | Get invite link |
| group_revoke_invite | group_id | Revoke and regenerate invite link |
Channels (Newsletters)
| Method | Parameters | Description |
|--------|------------|-------------|
| newsletters | refresh | List subscribed channels (cached 24h) |
| newsletter_info | jid or invite, refresh | Get channel details |
| newsletter_create | name, description, picture | Create a new channel |
| newsletter_follow | jid | Subscribe to a channel |
| newsletter_unfollow | jid | Unsubscribe from a channel |
| newsletter_mute | jid, mute | Mute/unmute a channel |
| newsletter_messages | jid, count, offset, before, since, until, media_type, search, refresh | Get channel messages (lazy cached, filterable) |
| newsletter_send | group_id, type, message/media_data | Send to channel (admin only) |
| newsletter_mark_viewed | jid, server_ids[] | Mark messages as viewed |
| newsletter_react | jid, server_id, reaction | React to a channel message |
| newsletter_live_updates | jid | Subscribe to live view/reaction updates |
| newsletter_stats | jid or invite, count | Get channel statistics (views, reactions) |
Chat History
| Method | Parameters | Description |
|--------|------------|-------------|
| chat_history | chat_id/phone/group_id, limit, offset, sender_phone, text_only | Get stored message history |
Rate Limiting (Anti-Ban Protection)
| Method | Parameters | Description |
|--------|------------|-------------|
| rate_limit_get | - | Get config and statistics |
| rate_limit_set | enabled, min_delay_ms, max_delay_ms, max_messages_per_hour, etc. | Update configuration |
| rate_limit_stats | - | Get current statistics only |
| rate_limit_unpause | - | Resume after automatic pause |
Events
The server pushes events as JSON-RPC notifications (no id field):
{"jsonrpc": "2.0", "method": "event.message_received", "params": {...}}| Event | Description |
|-------|-------------|
| event.status | Initial status on WebSocket connection |
| event.connected | WhatsApp connected successfully |
| event.disconnected | WhatsApp disconnected |
| event.connection_failure | Connection failed |
| event.logged_out | User logged out |
| event.temporary_ban | Temporary ban received |
| event.qr_code | New QR code available (code, image_data) |
| event.message_sent | Message sent successfully |
| event.message_received | New message received (includes forwarding info) |
| event.history_sync_complete | History sync completed after first login |
| event.newsletter_join | Joined a channel |
| event.newsletter_leave | Left a channel |
| event.newsletter_mute_change | Channel mute state changed |
| event.newsletter_live_update | Live view/reaction count updates |
Message Received Event Fields
{
"message_id": "ABC123",
"sender": "[email protected]",
"chat_id": "[email protected]",
"timestamp": "2025-01-15T10:30:00Z",
"is_from_me": false,
"is_group": false,
"is_forwarded": false,
"forwarding_score": 0,
"message_type": "text",
"text": "Hello world!",
"group_info": { "group_jid": "...", "sender_jid": "...", "sender_name": "..." }
}Examples
Send Text Message
{
"jsonrpc": "2.0",
"id": 1,
"method": "send",
"params": {
"phone": "1234567890",
"type": "text",
"message": "Hello from API!"
}
}Send Image with Caption
{
"jsonrpc": "2.0",
"id": 2,
"method": "send",
"params": {
"phone": "1234567890",
"type": "image",
"media_data": {
"data": "base64_encoded_image_data",
"mime_type": "image/jpeg",
"caption": "Check this out!"
}
}
}Send to Group
{
"jsonrpc": "2.0",
"id": 3,
"method": "send",
"params": {
"group_id": "[email protected]",
"type": "text",
"message": "Hello group!"
}
}Send Location
{
"jsonrpc": "2.0",
"id": 4,
"method": "send",
"params": {
"phone": "1234567890",
"type": "location",
"location": {
"latitude": 37.7749,
"longitude": -122.4194,
"name": "San Francisco",
"address": "California, USA"
}
}
}Reply to Message
{
"jsonrpc": "2.0",
"id": 5,
"method": "send",
"params": {
"phone": "1234567890",
"type": "text",
"message": "This is a reply!",
"reply": {
"message_id": "ABC123",
"sender": "[email protected]",
"content": "Original message text"
}
}
}Get Chat History
{
"jsonrpc": "2.0",
"id": 6,
"method": "chat_history",
"params": {
"phone": "1234567890",
"limit": 50,
"text_only": true
}
}Configure Rate Limiting
{
"jsonrpc": "2.0",
"id": 7,
"method": "rate_limit_set",
"params": {
"enabled": true,
"min_delay_ms": 5000,
"max_messages_per_hour": 30,
"simulate_typing": true,
"randomize_delays": true
}
}List Channels
{
"jsonrpc": "2.0",
"id": 8,
"method": "newsletters",
"params": {}
}Get Channel Info by Invite Link
{
"jsonrpc": "2.0",
"id": 9,
"method": "newsletter_info",
"params": {
"invite": "https://whatsapp.com/channel/0029Va..."
}
}Send Message to Channel
{
"jsonrpc": "2.0",
"id": 10,
"method": "newsletter_send",
"params": {
"group_id": "123456789@newsletter",
"type": "text",
"message": "Hello subscribers!"
}
}Get Channel Statistics
{
"jsonrpc": "2.0",
"id": 11,
"method": "newsletter_stats",
"params": {
"jid": "123456789@newsletter",
"count": 20
}
}Error Codes
| Code | Description | |------|-------------| | -32700 | Parse error - Invalid JSON | | -32600 | Invalid Request - Not a valid JSON-RPC 2.0 request | | -32601 | Method not found | | -32602 | Invalid params | | -32000 | Server error (WhatsApp operation failed) | | -32001 | No QR available |
Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| PORT | 9400 | WebSocket API port |
| EDGYMEOW_PORT | 9400 | WebSocket API port (alternative to PORT) |
| EDGYMEOW_SKIP_BINARY_DOWNLOAD | - | Set to 1 to skip binary download |
| EDGYMEOW_PREFER_SOURCE | - | Set to 1 to build from source if Go is installed |
Data Files
| Path | Description |
|------|-------------|
| data/whatsapp.db | SQLite database (session, contacts, message history) |
| data/groups.json | Group cache (auto-generated on connection) |
Building from Source
Requires Go 1.21+:
npm run buildFull Schema
See schema.json for complete OpenRPC specification.
Python Client
An async Python client is available on PyPI:
pip install edgymeowimport asyncio
from edgymeow import WhatsAppRPCClient
async def main():
client = WhatsAppRPCClient("ws://localhost:9400/ws/rpc")
await client.connect()
status = await client.status()
print(status)
await client.send(phone="1234567890", type="text", message="Hello!")
await client.close()
asyncio.run(main())See src/python/README.md for full Python client documentation.
Android Integration
Cross-compile the server for Android and embed it in your app:
# Build for all platforms including Android
npm run build-cross
# Or manually:
# arm64 real device
CGO_ENABLED=0 GOOS=android GOARCH=arm64 go build -ldflags="-s -w" -o libedgymeow.so ./src/go/cmd/server
# x86_64 emulator (use GOOS=linux, not android)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o libedgymeow-x86_64.so ./src/go/cmd/serverPlace binaries in your Android project:
app/android/app/src/main/jniLibs/
arm64-v8a/libedgymeow.so
x86_64/libedgymeow-x86_64.soRequired Gradle config (build.gradle.kts):
android {
packaging { jniLibs { useLegacyPackaging = true } }
defaultConfig { ndk { abiFilters += listOf("x86_64", "arm64-v8a") } }
}Launch from Kotlin:
val binary = File(applicationInfo.nativeLibraryDir, "libedgymeow.so")
val pb = ProcessBuilder(binary.absolutePath)
pb.environment()["SSL_CERT_DIR"] = "/system/etc/security/cacerts"
pb.environment()["EDGYMEOW_ANDROID"] = "1" // enables Android DNS resolver
pb.start()Then connect via WebSocket at ws://127.0.0.1:9400/ws/rpc.
CrossMeow (Flutter Example App)
A complete Flutter Android app is in examples/android/. It bundles the Go binary and the static web client into a single APK:
cd examples/android
# Build Go binary for emulator
cd ../../ && npm run build-cross # or manually cross-compile
# Copy binary to jniLibs
cp bin/libedgymeow-android-arm64.so examples/android/android/app/src/main/jniLibs/arm64-v8a/libedgymeow.so
# Build APK
cd examples/android && flutter build apk --debugThe app uses a Dart HTTP server to serve the web client from Flutter assets, with a WebView loading the dashboard. See examples/android/ for the full source.
Requirements
- Node.js 18+
- Pre-built binaries available for:
- Linux (amd64, arm64)
- macOS (amd64, arm64)
- Windows (amd64)
- Android (arm64, x86_64)
License
MIT
