Skip to main content

Crate whatsapp_rust

Crate whatsapp_rust 

Source
Expand description

§whatsapp-rust

CodSpeed

A high-performance, async Rust library for the WhatsApp Web API. Inspired by whatsmeow (Go) and Baileys (TypeScript).

Documentation | llms.txt | llms-full.txt

§Features

  • Authentication — QR code pairing, pair code linking, persistent sessions
  • Messaging — E2E encrypted (Signal Protocol), 1-on-1 and group chats, editing, reactions, quoting, receipts
  • Media — Upload/download images, videos, documents, GIFs, audio with automatic encryption
  • Voice calls — 1:1 VoIP audio calls with built-in MLOW or external encoded Opus/MLOW; see the codec boundary and production profiles
  • Groups & Communities — Create, manage, invite, membership approval, subgroup linking
  • Newsletters — Create, join, send messages, reactions
  • Status — Text, image, and video status posts with privacy controls
  • Contacts — Phone number lookup, profile pictures, user info, business profiles
  • Presence & Chat State — Online/offline, typing indicators, blocking
  • Chat Actions — Archive, pin, mute, star messages
  • Profile — Set push name, status text, profile picture
  • Privacy — Fetch/set privacy settings, disappearing messages
  • Modular — Pluggable storage, transport, HTTP client, and async runtime; SQLite, Tokio WebSocket, and ureq ship as the defaults, swap any of them with default-features = false
  • Native plugins — Build-time, type-safe extensions with scoped capabilities and lifecycle ownership behind the plugins feature
  • Runtime agnostic — Bring your own async runtime via the Runtime trait (Tokio included by default)

For the full API reference and guides, see the documentation.

§Quick Start

[dependencies]
whatsapp-rust = "0.7"
tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] }
use whatsapp_rust::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let bot = Bot::builder()
        .with_backend(SqliteStore::new("whatsapp.db").await?)
        .on_qr_code(|code, _timeout| async move {
            println!("Scan to pair:\n{code}");
        })
        .on_message(|ctx| async move {
            if ctx.message.text_content() == Some("ping") {
                let _ = ctx.reply("pong").await;
            }
        })
        .build()
        .await?;

    // Runs until logout or shutdown; a single await.
    bot.run().await;
    Ok(())
}

The default cargo features wire up the Tokio WebSocket transport, the ureq HTTP client, the SQLite store, and the Tokio runtime; only the storage backend has to be chosen explicitly. Every piece is replaceable through the builder (with_transport_factory, with_http_client, with_runtime) for custom environments such as wasm or embedded targets.

Native plugin APIs are opt-in: use features = ["plugins"] when implementing a plugin in the application. Published plugin crates can enable that feature in their own whatsapp-rust dependency, and Cargo feature unification activates it for the consumer. See agent_docs/plugin_architecture.md for the host contract and type-safe API example.

§One dependency is enough

whatsapp-rust re-exports the whole stack, so you never need to declare the sibling crates (wacore, wacore-binary, waproto, whatsapp-rust-tokio-transport, whatsapp-rust-ureq-http-client, whatsapp-rust-sqlite-storage) yourself, including when pinning a git revision:

[dependencies]
whatsapp-rust = { git = "https://github.com/oxidezap/whatsapp-rust", rev = "<commit>" }
  • Protobuf types: whatsapp_rust::waproto::whatsapp (aliased as wa in the prelude)
  • Core protocol/types: whatsapp_rust::wacore, whatsapp_rust::wacore_binary (Jid is also at the crate root)
  • Bundled implementations: whatsapp_rust::transport::TokioWebSocketTransportFactory, whatsapp_rust::http::UreqHttpClient, whatsapp_rust::store::SqliteStore, each behind its default-on cargo feature (tokio-transport, ureq-client, sqlite-storage)

With default-features = false, pick only what you need (e.g. features = ["tokio-runtime", "tokio-transport", "ureq-client"] for a custom store while keeping the bundled networking).

To run the bot in the background instead of blocking, use spawn() and keep the handle:

use whatsapp_rust::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let bot = Bot::builder()
        .with_backend(SqliteStore::new("whatsapp.db").await?)
        .build()
        .await?;

    let handle = bot.spawn(); // full Client API stays available via handle.client()

    tokio::signal::ctrl_c().await?;
    handle.shutdown().await; // graceful: flushes pending state, then stops
    Ok(())
}

Run the included demo bot:

cargo run --example demo                              # QR code only
cargo run --example demo -- -p 15551234567            # Pair code + QR code
cargo run --example demo -- -p 15551234567 -c MYCODE  # Custom pair code

§Project Structure

whatsapp-rust/
├── src/                    # Main client library
├── wacore/                 # Platform-agnostic core (no runtime deps)
│   ├── binary/             # WhatsApp binary protocol
│   ├── libsignal/          # Signal Protocol implementation
│   └── appstate/           # App state management
├── waproto/                # Protocol Buffers definitions
├── storages/sqlite-storage # SQLite backend
├── transports/tokio-transport
└── http_clients/ureq-client

§Disclaimer

This is an unofficial, open-source reimplementation. Using custom WhatsApp clients may violate Meta’s Terms of Service and could result in account suspension. Use at your own risk.

§Acknowledgements

Re-exports§

pub use cache::Freshness;
pub use cache_config::CacheConfig;
pub use cache_config::CacheEntryConfig;
pub use cache_config::CacheStores;
pub use client::ClientError;
pub use client::NodeFilter;
pub use client::MemoryReport;
pub use client::ResourceReport;
pub use client::CallError;
pub use client::Voip;
pub use client::Client;
pub use client::ClientBuild;
pub use client::ClientBuilder;
pub use client::ClientBuilderError;
pub use client::RawNodeLease;
pub use client::ClientLifecycle;client-lifecycle
pub use client::ConnectionScope;client-lifecycle
pub use client::ConnectionScopeState;client-lifecycle
pub use client::ConnectError;
pub use client::ConnectStage;
pub use client::SignalMaintenanceError;
pub use types::durability_hook::InboundDurabilityHook;
pub use types::retry_admission::RetryAdmission;
pub use error::ErrorChainExt;
pub use error::ServerRejection;
pub use error::Sources;
pub use handlers::chatstate::ChatStateEvent;
pub use plugins::ClientPlugin;plugins
pub use plugins::PluginCapabilities;plugins
pub use plugins::PluginCapability;plugins
pub use plugins::PluginConnectionScope;plugins
pub use plugins::PluginConnectionTasks;plugins
pub use plugins::PluginContext;plugins
pub use plugins::PluginCoreEventSubscription;plugins
pub use plugins::PluginCoreEvents;plugins
pub use plugins::PluginEventEndpointConfig;plugins
pub use plugins::PluginEventEndpointStats;plugins
pub use plugins::PluginEventEnvelope;plugins
pub use plugins::PluginEventOverflow;plugins
pub use plugins::PluginEventPayloadEncoding;plugins
pub use plugins::PluginEventPublishError;plugins
pub use plugins::PluginEventPublishReport;plugins
pub use plugins::PluginEventPublisherStats;plugins
pub use plugins::PluginEventReceiveError;plugins
pub use plugins::PluginEventRouteError;plugins
pub use plugins::PluginEventRouter;plugins
pub use plugins::PluginEventRouterStats;plugins
pub use plugins::PluginEventSelector;plugins
pub use plugins::PluginEventSubscribeError;plugins
pub use plugins::PluginEventSubscription;plugins
pub use plugins::PluginEventTopic;plugins
pub use plugins::PluginEventTryReceiveError;plugins
pub use plugins::PluginEvents;plugins
pub use plugins::PluginFuture;plugins
pub use plugins::PluginHealth;plugins
pub use plugins::PluginHostConfig;plugins
pub use plugins::PluginHostStats;plugins
pub use plugins::PluginIq;plugins
pub use plugins::PluginIqError;plugins
pub use plugins::PluginManifest;plugins
pub use plugins::PluginMessaging;plugins
pub use plugins::PluginMessagingError;plugins
pub use plugins::PluginPlanError;plugins
pub use plugins::PluginResourceError;plugins
pub use plugins::PluginState;plugins
pub use plugins::PluginStats;plugins
pub use plugins::PluginTasks;plugins
pub use plugins::UntypedClientPlugin;plugins
pub use request::IqError;
pub use runtime_impl::TokioRuntime;tokio-runtime
pub use send::EditOptions;
pub use send::PinDuration;
pub use send::RevokeType;
pub use send::SendError;
pub use send::SendOptions;
pub use send::SendResult;
pub use upload::UploadOptions;
pub use features::AppStateError;
pub use features::BatchGroupResult;
pub use features::Blocking;
pub use features::BlockingError;
pub use features::ChatActions;
pub use features::ChatStateError;
pub use features::ChatStateType;
pub use features::Chatstate;
pub use features::Comments;
pub use features::Community;
pub use features::CommunityError;
pub use features::CommunitySubgroup;
pub use features::ContactError;
pub use features::Contacts;
pub use features::CreateCommunityOptions;
pub use features::CreateCommunityResult;
pub use features::CreateGroupResult;
pub use features::EncryptedEdit;
pub use features::EventCreationParams;
pub use features::Events;
pub use features::GroupError;
pub use features::GroupMetadata;
pub use features::GroupParticipant;
pub use features::GroupType;
pub use features::Groups;
pub use features::Labels;
pub use features::LinkSubgroupsResult;
pub use features::MediaReupload;
pub use features::MediaReuploadError;
pub use features::MediaReuploadRequest;
pub use features::MessageEditError;
pub use features::MessageRetransmission;
pub use features::Mex;
pub use features::MexError;
pub use features::MexRequest;
pub use features::Newsletter;
pub use features::NewsletterError;
pub use features::NewsletterMessage;
pub use features::NewsletterMessageType;
pub use features::NewsletterMetadata;
pub use features::NewsletterReactionCount;
pub use features::NewsletterRole;
pub use features::NewsletterState;
pub use features::NewsletterVerification;
pub use features::PollError;
pub use features::PollOptionResult;
pub use features::Polls;
pub use features::Presence;
pub use features::PresenceError;
pub use features::PresenceStatus;
pub use features::PreviousDescription;
pub use features::Profile;
pub use features::ProfileError;
pub use features::RetryRequestError;
pub use features::RetryRequestOptions;
pub use features::RetryRequestOutcome;
pub use features::SecretEncKind;
pub use features::SecretEncrypted;
pub use features::Signal;
pub use features::SignalError;
pub use features::SignalSessionInfo;
pub use features::SignalSessionMigration;
pub use features::StanzaRejection;
pub use features::StanzaResponseError;
pub use features::Status;
pub use features::StatusPrivacySetting;
pub use features::StatusSendOptions;
pub use features::SyncActionMessageRange;
pub use features::TcToken;
pub use features::TcTokenError;
pub use features::UnlinkSubgroupsResult;
pub use features::group_type;
pub use features::message_key;
pub use features::message_range;
pub use shutdown::shutdown_signal;signal
pub use wacore;
pub use wacore_binary;
pub use waproto;
pub use anyhow;
pub use async_channel;
pub use bytes;
pub use futures;
pub use serde;
pub use serde_json;
pub use wacore::chrono;
pub use waproto::buffa;

Modules§

appstate_sync
bot
cache
The client’s in-process cache type.
cache_config
cache_store
Typed cache wrapper that dispatches to either the in-process Cache or a custom CacheStore backend (e.g., Redis).
client
download
error
Typed recovery over the error chain.
features
handlers
handshake
history_sync
http
jid_utils
keepalive
lid_pn_cache
LID-PN (Linked ID to Phone Number) Cache
media
High-level media-message builders.
mediaconn
Media connection management.
message
pair
pair_code
Pair code authentication for phone number linking.
passkey
PasskeyAuthenticator — the single pluggable point of the SHORTCAKE_PASSKEY login flow (see wacore::shortcake for the deterministic protocol core).
pdo
PDO (Peer Data Operation) support for requesting message content from the primary device.
pluginsplugins
Build-time client plugins and their capability-scoped host.
portable_cache
Portable in-process cache: the client’s sole cache backend, on every target including wasm32.
prekeys
Pre-key management for Signal Protocol.
prelude
One-import surface for the common bot path: use whatsapp_rust::prelude::*;.
privacy_settings
Privacy settings IQ specification.
proto_helpers
receipt
request
retry
runtime_impltokio-runtime
schemas
Auto-generated AppState (syncd) action schemas (WhatsApp 2.3000.1042742319). DO NOT EDIT.
send
Outgoing message pipeline.
session
shutdownsignal
Graceful-shutdown signal for the bundled binaries.
socket
spam_report
Spam reporting feature.
sticker_pack
Sticker pack creation helpers.
store
sync_task
telemetry
Optional metrics emission (the metrics feature). No-op when the feature is off. Optional metrics emission via the metrics facade.
traits
Storage traits for the WhatsApp client.
transport
types
unified_session
Unified session telemetry manager.
upload
usync
User device list synchronization.
version
webp
WebP format utilities.

Macros§

require_from_jid
Extract the required from JID attribute from a NodeRef, or log a warning and return from the enclosing function.

Structs§

AllocSnapshot
Point-in-time copy of an AllocMeter. Counters are cumulative over the meter’s lifetime.
BlocklistEntry
A single blocklist entry from the response.
ClientProfile
CollectionStats
Entry count plus estimated retained bytes for one internal collection.
CompactString
A CompactString is a compact string type that can be used almost anywhere a String or str can be used.
GroupCreateOptions
Options for creating a new group.
GroupDescription
A validated group description string.
GroupEphemeralSettings
Disappearing-message settings carried by a group’s <ephemeral> node.
GroupParticipantDetails
Less-common participant metadata, allocated only when at least one field is present.
GroupParticipantOptions
Options for a participant when creating a group.
GroupProfilePicture
A single group profile picture result.
GroupSubject
A validated group subject string.
GrowthLockInfo
Growth lock info (system-managed, read-only).
HttpResourceReport
Per-session footprint of a crate::net::HttpClient: idle connection-pool buffers plus any in-flight download/media buffering the impl can see.
IsOnWhatsAppResult
Jid
MembershipRequest
MexErrorExtensions
MEX GraphQL error extensions.
MexGraphQLError
MEX GraphQL error.
MexResponse
MEX GraphQL response.
MsgSecretRetention
Per-add-on-kind retention horizons applied to the parent message’s event time. Defaults are derived from verified protocol limits, not guesses.
NodeBuilder
OwnedNodeRef
A decoded node that owns its decompressed buffer. The inner NodeRef borrows string/byte payloads directly from the buffer, avoiding copies. Container allocations (attribute Vec, child Vec) still occur during decode.
ParticipantChangeResponse
Response for participant change operations. Success: error is None; type is often omitted by the server. On error == "403" the <add_request> child (add_request field) carries the V4 invite token.
PollVoteCiphertext
The encrypted vote payload and its GCM IV, paired so the two same-typed byte slices can’t be transposed at a call site.
ProfilePicture
Profile picture information.
ReachoutTimelock
SetProfilePictureResponse
Response from setting a profile picture.
SpamReportRequest
A request to report a message as spam.
SpamReportResult
The result of a spam report.
StatsSnapshot
Point-in-time copy of SessionStats, plus client-level counters the client fills in (Self::reconnect_errors, Self::resends_throttled).
StorageResourceReport
Process-local resource footprint a storage backend attributes to one session. Returned by store::traits::DeviceStore::resource_report.
TransportResourceReport
Per-session footprint of a crate::net::Transport: read/write framing buffers plus a best-effort TLS/noise session-state estimate.
UserInfo
User information from usync.
UsyncSubprotocolError
VerifiedName
Verified name certificate information.

Enums§

EncType
Classification of an encryption node’s type.
EventResponseType
GroupAppealStatus
Review state for an appeal on a suspended group.
GroupJoinError
Error codes returned when joining a group via invite.
InviteInfoError
Error codes returned when querying invite group info.
JoinGroupResult
Result of joining a group via invite code.
MediaRetryResult
Result of a media retry request.
MemberAddMode
Member add mode for who can add participants.
MemberLinkMode
Member link mode for group invite links.
MemberShareHistoryMode
Who can share message history with new members.
MembershipApprovalMode
Membership approval mode for join requests.
MsgSecretPolicy
How the core manages messageSecret persistence.
NackReason
ParticipantType
Participant type (admin level).
PictureType
Profile picture query type.
RetryReason
Retry reason codes matching WhatsApp Web’s RetryReason enum. These are included in the retry receipt to help the sender understand why the message couldn’t be decrypted.
Server
Known WhatsApp server identifiers.
SpamFlow
The type of spam flow indicating the source of the report.
StanzaType
Type-safe <message type="..."> value for the send-time override.

Traits§

CacheStore
Backend trait for pluggable cache storage.
OriginalMessageResolver
App-supplied fallback returning a parent message’s 32-byte messageSecret on a store miss, keyed by the non-AD (chat, sender, msg_id).
Runtime
A runtime-agnostic abstraction over async executor capabilities.

Attribute Macros§

async_trait