BaileysEx

Hex.pmHex DocsLicense

WhatsApp Web API client for Elixir — a behaviour-accurate port of Baileys that brings the full WhatsApp multi-device protocol to the BEAM.

BaileysEx connects directly to WhatsApp's WebSocket-based protocol. No browser automation, no headless Chrome, no external Node.js sidecar. Just a supervised Elixir process tree that handles the Noise handshake, Signal Protocol encryption, binary XMPP framing, and the complete WhatsApp feature surface — natively.

Note: This library communicates with WhatsApp's servers using a reverse-engineered protocol. It is not affiliated with, authorized by, or endorsed by WhatsApp or Meta. Use responsibly and in accordance with WhatsApp's Terms of Service.

Features

Authentication

Messaging

Media

Groups and Communities

Presence and Status

Newsletters

App State Sync

Analytics

Why Elixir?

BaileysEx isn't just a translation — it's a reimagining of Baileys for a runtime built for exactly this kind of work:

Baileys (Node.js)BaileysEx (Elixir/OTP)
Callbacks and PromisesSupervised process trees with :rest_for_one restart strategy
async-mutex libraryBEAM processes — concurrency is the runtime, not a library
Manual reconnect logic:gen_statem state machine with automatic reconnection
node-cache / lru-cacheETS tables — concurrent, lock-free, built into the VM
pino loggingLogger with structured metadata and configurable backends
Single-threaded event loopPreemptive scheduling across all available cores
Process crash = app crashSupervisor restarts failed children — let it crash

Crypto is native too. All cryptographic primitives (AES, HMAC, SHA, PBKDF2, Curve25519, Ed25519) use Erlang's built-in :crypto module — no external C/Rust for standard operations. Rust NIFs are used only for the Noise Protocol framework (snow) and XEdDSA signing (curve25519-dalek), where no Erlang/Elixir equivalent exists.

Quick Start

Installation

Add baileys_ex to your mix.exs dependencies:

def deps do
[
{:baileys_ex, "~> 0.1.0-alpha.2"}
]
end

Requirements: Elixir 1.19+, OTP 28, Rust toolchain (for NIF compilation).

Choose a persistence backend

Connect and pair

alias BaileysEx.Auth.NativeFilePersistence
alias BaileysEx.Connection.Transport.MintWebSocket
# Load or create auth state
{:ok, persisted_auth} =
NativeFilePersistence.use_native_file_auth_state("tmp/baileys_auth")
parent = self()
# Start the connection
{:ok, connection} =
BaileysEx.connect(
persisted_auth.state,
Keyword.merge(persisted_auth.connect_opts, [
transport: {MintWebSocket, []},
on_qr: fn qr -> IO.puts("Scan QR: #{qr}") end,
on_connection: fn update -> send(parent, {:connection_update, update}) end
])
)
# Persist credentials on update
BaileysEx.subscribe_raw(connection, fn events ->
if Map.has_key?(events, :creds_update) do
{:ok, latest} = BaileysEx.auth_state(connection)
:ok = persisted_auth.save_creds.(latest)
end
end)
# Wait for the connection to open
receive do
{:connection_update, %{connection: :open}} -> :connected!
after
30_000 -> raise "timed out waiting for connection"
end

If you specifically need Baileys-compatible JSON auth files during a sidecar migration or compatibility rollout, swap in BaileysEx.Auth.FilePersistence.use_multi_file_auth_state/1.

Send a message

{:ok, _sent} =
BaileysEx.send_message(connection, "15551234567@s.whatsapp.net", %{
text: "Hello from BaileysEx!"
})

Listen for incoming messages

BaileysEx.subscribe(connection, fn
{:message, msg} -> IO.inspect(msg, label: "incoming")
{:connection, update} -> IO.inspect(update, label: "connection")
_other -> :ok
end)

Send media

{:ok, _sent} =
BaileysEx.send_message(connection, "15551234567@s.whatsapp.net", %{
image: {:file, "photo.jpg"},
caption: "Sent from Elixir"
})

Documentation

Full guides and API reference are available on HexDocs.

SectionWhat you'll learn
InstallationPrerequisites, dependency setup, compilation
First ConnectionQR pairing, phone pairing, credential persistence
Send MessagesText, replies, reactions, polls, forwards, edits
MediaUpload images/video/docs, download, stale URL refresh
GroupsCreate, manage participants, invite flows, communities
EventsSubscribe to connection, message, and presence events
AuthenticationCustom credential storage, Signal key management
ConfigurationAll connection and runtime options
Event CatalogEvery event type with payload shapes
Message TypesComplete message payload reference

Example

A complete echo bot is included at examples/echo_bot.exs:

mix run examples/echo_bot.exs -- --help

See the Echo Bot guide for a walkthrough.

Telemetry

BaileysEx emits Telemetry events under the [:baileys_ex] prefix — connection lifecycle, message send/receive, media upload/download, and NIF operations. Attach your handlers for dashboards, alerting, or tracing.

Status

BaileysEx is in alpha. The API surface is stabilizing but may change before 1.0. The library tracks Baileys 7.00rc9 as its upstream reference for wire behaviour and feature scope.

Acknowledgements

License

MIT — see LICENSE for details.