Skip to main content

Overview

waproto contains the Protocol Buffers definitions for all WhatsApp message types. It’s auto-generated from whatsapp.proto using prost and provides strongly-typed Rust structs for working with WhatsApp’s binary protocol.
[dependencies]
waproto = "0.5"

Structure

waproto/
├── src/
│   ├── lib.rs         # Module definition
│   ├── whatsapp.rs    # Generated protobuf code (checked into git)
│   └── whatsapp.proto # Source protobuf definitions
└── build.rs           # prost-build script (no-op unless `generate` feature is enabled)

Usage

All protobuf types are under the waproto::whatsapp module:
use waproto::whatsapp as wa;

let message = wa::Message {
    conversation: Some("Hello, World!".to_string()),
    ..Default::default()
};

Key Message Types

Core Message Types

Message

The main message container used for all WhatsApp messages.
pub struct Message {
    // Text message
    pub conversation: Option<String>,
    
    // Media messages
    pub image_message: Option<Box<ImageMessage>>,
    pub video_message: Option<Box<VideoMessage>>,
    pub audio_message: Option<Box<AudioMessage>>,
    pub document_message: Option<Box<DocumentMessage>>,
    pub sticker_message: Option<Box<StickerMessage>>,
    
    // Rich messages
    pub extended_text_message: Option<Box<ExtendedTextMessage>>,
    pub interactive_message: Option<Box<InteractiveMessage>>,
    pub template_message: Option<Box<TemplateMessage>>,
    pub buttons_message: Option<Box<ButtonsMessage>>,
    pub list_message: Option<Box<ListMessage>>,
    
    // Group messages
    pub sender_key_distribution_message: Option<SenderKeyDistributionMessage>,
    
    // System messages
    pub protocol_message: Option<Box<ProtocolMessage>>,
    pub ephemeral_message: Option<Box<EphemeralMessage>>,
    pub view_once_message: Option<Box<ViewOnceMessage>>,
    pub view_once_message_v2: Option<Box<ViewOnceMessageV2>>,
    
    // Reactions and interactions
    pub reaction_message: Option<ReactionMessage>,
    pub edited_message: Option<Box<FutureProofMessage>>,
    pub keep_in_chat_message: Option<KeepInChatMessage>,
    
    // Album (grouped media)
    pub album_message: Option<Box<AlbumMessage>>,
    pub associated_child_message: Option<Box<FutureProofMessage>>,
    
    // Metadata
    pub message_context_info: Option<MessageContextInfo>,
    // ... and many more
}
Usage in main library:
use waproto::whatsapp as wa;

// Construct a text message
let msg = wa::Message {
    conversation: Some("Hello!".to_string()),
    ..Default::default()
};

// Construct an image message
let img = wa::Message {
    image_message: Some(Box::new(wa::message::ImageMessage {
        url: Some(media_url),
        media_key: Some(media_key.to_vec()),
        file_sha256: Some(file_sha256.to_vec()),
        file_enc_sha256: Some(file_enc_sha256.to_vec()),
        caption: Some("Check this out!".to_string()),
        ..Default::default()
    })),
    ..Default::default()
};

MessageKey

Identifies a specific message in a conversation.
pub struct MessageKey {
    pub remote_jid: Option<String>,  // Chat JID
    pub from_me: Option<bool>,       // Sent by me?
    pub id: Option<String>,          // Message ID
    pub participant: Option<String>, // Group participant JID
}

Media Messages

ImageMessage

pub struct ImageMessage {
    pub url: Option<String>,
    pub mimetype: Option<String>,
    pub caption: Option<String>,
    pub file_sha256: Option<Vec<u8>>,
    pub file_length: Option<u64>,
    pub height: Option<u32>,
    pub width: Option<u32>,
    pub media_key: Option<Vec<u8>>,
    pub file_enc_sha256: Option<Vec<u8>>,
    pub jpeg_thumbnail: Option<Vec<u8>>,
    pub context_info: Option<ContextInfo>,
    // ...
}

VideoMessage

pub struct VideoMessage {
    pub url: Option<String>,
    pub mimetype: Option<String>,
    pub caption: Option<String>,
    pub file_sha256: Option<Vec<u8>>,
    pub file_length: Option<u64>,
    pub seconds: Option<u32>,
    pub media_key: Option<Vec<u8>>,
    pub file_enc_sha256: Option<Vec<u8>>,
    pub jpeg_thumbnail: Option<Vec<u8>>,
    pub gif_playback: Option<bool>,
    // ...
}

AudioMessage

pub struct AudioMessage {
    pub url: Option<String>,
    pub mimetype: Option<String>,
    pub file_sha256: Option<Vec<u8>>,
    pub file_length: Option<u64>,
    pub seconds: Option<u32>,
    pub ptt: Option<bool>,  // Push-to-talk (voice note)
    pub media_key: Option<Vec<u8>>,
    pub file_enc_sha256: Option<Vec<u8>>,
    // ...
}

DocumentMessage

pub struct DocumentMessage {
    pub url: Option<String>,
    pub mimetype: Option<String>,
    pub title: Option<String>,
    pub file_sha256: Option<Vec<u8>>,
    pub file_length: Option<u64>,
    pub page_count: Option<u32>,
    pub media_key: Option<Vec<u8>>,
    pub file_enc_sha256: Option<Vec<u8>>,
    pub file_name: Option<String>,
    pub jpeg_thumbnail: Option<Vec<u8>>,
    // ...
}

StickerMessage

pub struct StickerMessage {
    pub url: Option<String>,
    pub file_sha256: Option<Vec<u8>>,
    pub file_enc_sha256: Option<Vec<u8>>,
    pub media_key: Option<Vec<u8>>,
    pub mimetype: Option<String>,
    pub height: Option<u32>,
    pub width: Option<u32>,
    pub is_animated: Option<bool>,
    // ...
}

Rich Content Messages

ExtendedTextMessage

Text with formatting, links, and quoted messages.
pub struct ExtendedTextMessage {
    pub text: Option<String>,
    pub matched_text: Option<String>,
    pub canonical_url: Option<String>,
    pub description: Option<String>,
    pub title: Option<String>,
    pub thumbnail: Option<Vec<u8>>,
    pub context_info: Option<ContextInfo>,
    // ...
}

InteractiveMessage

Buttons, lists, and other interactive elements.
pub struct InteractiveMessage {
    pub header: Option<interactive_message::Header>,
    pub body: Option<interactive_message::Body>,
    pub footer: Option<interactive_message::Footer>,
    pub context_info: Option<ContextInfo>,
    // One of:
    pub native_flow_message: Option<InteractiveMessage>,
    pub shop_storefront_message: Option<ShopMessage>,
    // ...
}

ButtonsMessage

pub struct ButtonsMessage {
    pub content_text: Option<String>,
    pub footer_text: Option<String>,
    pub context_info: Option<ContextInfo>,
    pub buttons: Vec<buttons_message::Button>,
    pub header_type: Option<i32>,
    // ...
}

ListMessage

pub struct ListMessage {
    pub title: Option<String>,
    pub description: Option<String>,
    pub button_text: Option<String>,
    pub list_type: Option<i32>,
    pub sections: Vec<list_message::Section>,
    pub context_info: Option<ContextInfo>,
    // ...
}

Encryption Messages

SenderKeyDistributionMessage

Used for group message encryption.
pub struct SenderKeyDistributionMessage {
    pub group_id: Option<String>,
    pub axolotl_sender_key_distribution_message: Option<Vec<u8>>,
}

PreKeySignalMessage

Used for establishing 1:1 encryption.
pub struct PreKeySignalMessage {
    // Signal Protocol encrypted message
}

System & Protocol Messages

ProtocolMessage

For protocol-level operations.
pub struct ProtocolMessage {
    pub key: Option<MessageKey>,
    pub r#type: Option<i32>,  // DELETE, REVOKE, etc.
    pub ephemeral_expiration: Option<u32>,
    pub ephemeral_setting_timestamp: Option<i64>,
    // ...
}
Common types:
  • DELETE - Delete message for everyone
  • REVOKE - Revoke sent message
  • EPHEMERAL_SETTING - Ephemeral message setting

ReactionMessage

pub struct ReactionMessage {
    pub key: Option<MessageKey>,
    pub text: Option<String>,  // Emoji
    pub group_by_key: Option<bool>,
    pub sender_timestamp_ms: Option<i64>,
    pub unread: Option<bool>,
}

EditMessage

pub struct EditMessage {
    pub key: Option<MessageKey>,
    pub message: Option<Box<Message>>,  // New message content
    pub timestamp_ms: Option<i64>,
}

AlbumMessage

Parent message for grouped media albums. Declares expected image/video counts so WhatsApp clients know how many items to group together.
pub struct AlbumMessage {
    pub expected_image_count: Option<u32>,
    pub expected_video_count: Option<u32>,
    pub context_info: Option<Box<ContextInfo>>,
}
Each child media message is wrapped in associated_child_message (a FutureProofMessage) and linked to the parent via a MessageAssociation:
pub struct MessageAssociation {
    pub association_type: Option<i32>,       // MediaAlbum = 1
    pub parent_message_key: Option<MessageKey>,
    pub message_index: Option<i32>,
}
Use whatsapp_rust::proto_helpers::wrap_as_album_child to construct album children. See Sending Messages - Album messages for usage examples.

AI & Bot Messages

AiRichResponseMessage

pub struct AiRichResponseMessage {
    pub r#type: Option<i32>,
    pub sub_messages: Vec<AiRichResponseSubMessage>,
    // ...
}

BotFeedbackMessage

pub struct BotFeedbackMessage {
    pub message_key: Option<MessageKey>,
    pub kind: Option<i32>,  // Thumbs up/down
    pub text: Option<String>,
    // ...
}

Metadata & Context

MessageContextInfo

pub struct MessageContextInfo {
    pub device_list_metadata: Option<DeviceListMetadata>,
    pub device_list_metadata_version: Option<i32>,
    pub message_secret: Option<Vec<u8>>,
    pub padding: Option<Vec<u8>>,
    pub message_add_on_duration_in_secs: Option<u32>,
    pub message_association: Option<MessageAssociation>, // Album/child linking
    // ...
}

ContextInfo

Quoted messages, mentions, and forwarding info.
pub struct ContextInfo {
    pub stanza_id: Option<String>,
    pub participant: Option<String>,
    pub quoted_message: Option<Box<Message>>,
    pub remote_jid: Option<String>,
    pub mentioned_jid: Vec<String>,
    pub conversion_source: Option<String>,
    pub forwarding_score: Option<u32>,
    pub is_forwarded: Option<bool>,
    // ...
}

Device & Identity Types

ADV Messages

Account Device Verification messages.
pub struct AdvDeviceIdentity {
    pub raw_id: Option<u32>,
    pub timestamp: Option<u64>,
    pub key_index: Option<u32>,
    pub account_type: Option<i32>,
    pub device_type: Option<i32>,
}

pub struct AdvSignedDeviceIdentity {
    pub details: Option<Vec<u8>>,
    pub account_signature_key: Option<Vec<u8>>,
    pub account_signature: Option<Vec<u8>>,
    pub device_signature: Option<Vec<u8>>,
}

pub struct AdvKeyIndexList {
    pub raw_id: Option<u32>,
    pub timestamp: Option<u64>,
    pub current_index: Option<u32>,
    pub valid_indexes: Vec<u32>,
    pub account_type: Option<i32>,
}

Signal Protocol Structures

pub struct PreKeyRecordStructure {
    pub id: Option<u32>,
    pub public_key: Option<Vec<u8>>,
    pub private_key: Option<Vec<u8>>,
}

pub struct SignedPreKeyRecordStructure {
    pub id: Option<u32>,
    pub public_key: Option<Vec<u8>>,
    pub private_key: Option<Vec<u8>>,
    pub signature: Option<Vec<u8>>,
    pub timestamp: Option<u64>,
}

Handshake & Connection Types

HandshakeMessage

Used during initial connection handshake.
pub struct HandshakeMessage {
    pub client_hello: Option<ClientHello>,
    pub server_hello: Option<ServerHello>,
    pub client_finish: Option<ClientFinish>,
}

ClientPayload

Device and client information during pairing.
pub struct ClientPayload {
    pub username: Option<u64>,
    pub passive: Option<bool>,
    pub user_agent: Option<UserAgent>,
    pub web_info: Option<WebInfo>,
    pub push_name: Option<String>,
    pub session_id: Option<i32>,
    pub short_connect: Option<bool>,
    pub connect_type: Option<i32>,
    pub connect_reason: Option<i32>,
    // ...
}

History Sync Types

HistorySyncNotification

pub struct HistorySyncNotification {
    pub file_sha256: Option<Vec<u8>>,
    pub file_length: Option<u64>,
    pub media_key: Option<Vec<u8>>,
    pub file_enc_sha256: Option<Vec<u8>>,
    pub direct_path: Option<String>,
    pub sync_type: Option<i32>,
    pub chunk_order: Option<u32>,
    pub original_message_id: Option<String>,
}

HistorySync

pub struct HistorySync {
    pub sync_type: Option<i32>,
    pub conversations: Vec<Conversation>,
    pub status_v3_messages: Vec<WebMessageInfo>,
    pub chunk_order: Option<u32>,
    pub progress: Option<u32>,
    // ...
}

Media Reference Types

ExternalBlobReference

References to uploaded media files.
pub struct ExternalBlobReference {
    pub media_key: Option<Vec<u8>>,
    pub direct_path: Option<String>,
    pub handle: Option<String>,
    pub file_size_bytes: Option<u64>,
    pub file_sha256: Option<Vec<u8>>,
    pub file_enc_sha256: Option<Vec<u8>>,
}

App State Types

SyncActionValue

App state synchronization actions.
pub struct SyncActionValue {
    pub timestamp: Option<i64>,
    // One of many action types:
    pub contact_action: Option<ContactAction>,
    pub mute_action: Option<MuteAction>,
    pub pin_action: Option<PinAction>,
    pub security_notification_setting: Option<SecurityNotificationSetting>,
    pub push_name_setting: Option<PushNameSetting>,
    pub archive_chat_action: Option<ArchiveChatAction>,
    pub delete_chat_action: Option<DeleteChatAction>,
    pub star_action: Option<StarAction>,
    // ... and many more
}

Enums

waproto includes many enum types (as i32 values with const definitions):
// Message types
pub mod protocol_message {
    pub enum Type {
        Revoke = 0,
        EphemeralSetting = 3,
        EphemeralSyncResponse = 4,
        HistorySyncNotification = 5,
        AppStateSyncKeyShare = 6,
        AppStateSyncKeyRequest = 7,
        Delete = 8,
        // ...
    }
}

// Media types
pub mod video_message {
    pub enum Attribution {
        None = 0,
        Giphy = 1,
        Tenor = 2,
    }
}

Feature flags

FeatureDescriptionImplies
generateEnables prost-build as a build dependency and runs code generation from whatsapp.proto. Only needed when modifying the .proto file — normal builds use the checked-in whatsapp.rs.
serde-deserializeAdds #[derive(serde::Deserialize)] and #[serde(default)] to all types. Use when you need to parse protobuf types from JSON.
serde-snake-caseAdds #[serde(rename_all(deserialize = "snake_case"))] to all types. Allows snake_case enum variant names during deserialization (prost generates PascalCase). Serialize output is unchanged.serde-deserialize

Serde support

All generated types derive serde::Serialize by default. Deserialization and snake_case renaming are behind optional feature flags (serde-deserialize and serde-snake-case above). Enable them in your Cargo.toml:
[dependencies]
waproto = { version = "0.5", features = ["serde-snake-case"] }

Default behavior (no feature flags)

All types derive Serialize only:
#[derive(serde::Serialize)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Message {
    // ...
}
This allows JSON serialization for debugging:
let json = serde_json::to_string_pretty(&message)?;
println!("Message: {}", json);

With serde-deserialize

All types also derive Deserialize with #[serde(default)], matching protobuf semantics where missing fields use default values:
#[derive(serde::Serialize)]
#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde-deserialize", serde(default))]
pub struct Message {
    // ...
}

With serde-snake-case

All types additionally accept snake_case during deserialization. This primarily affects enum and oneof variants (prost generates PascalCase names), while struct fields are already snake_case. Serialization output remains unchanged.
// Without serde-snake-case: must use PascalCase
let json = r#"{"accountType": "Enterprise"}"#;

// With serde-snake-case: snake_case also accepted
let json = r#"{"account_type": "enterprise"}"#;
The serde-snake-case feature is primarily useful for WASM bridge scenarios where JavaScript sends snake_case JSON to the Rust backend. For most Rust-only use cases, you only need the default Serialize support.

Code generation

The protobuf code is auto-generated but checked into version control. The prost-build dependency is gated behind the generate feature, so normal builds skip code generation entirely — build.rs is a no-op without this feature. This eliminates the heavy prost-build transitive dependency tree (protoc, tempfile, etc.) from regular compilations, improving build times. To regenerate after modifying whatsapp.proto:
cargo build -p waproto --features generate
This runs build.rs which uses prost-build to compile whatsapp.proto into whatsapp.rs.
You only need the generate feature when you’ve changed the .proto file. The generated whatsapp.rs is committed to the repository, so all other builds use it directly.

Usage Examples

Constructing Messages

use waproto::whatsapp as wa;

// Text message
let text = wa::Message {
    conversation: Some("Hello!".to_string()),
    ..Default::default()
};

// Image with caption
let image = wa::Message {
    image_message: Some(Box::new(wa::message::ImageMessage {
        url: Some(media_url),
        media_key: Some(media_key.to_vec()),
        file_sha256: Some(file_sha256.to_vec()),
        file_enc_sha256: Some(file_enc_sha256.to_vec()),
        caption: Some("Nice photo!".to_string()),
        jpeg_thumbnail: Some(thumbnail),
        ..Default::default()
    })),
    ..Default::default()
};

// Quoted reply
let reply = wa::Message {
    extended_text_message: Some(Box::new(wa::message::ExtendedTextMessage {
        text: Some("Great question!".to_string()),
        context_info: Some(Box::new(wa::message::ContextInfo {
            stanza_id: Some(original_message_id),
            participant: Some(original_sender),
            quoted_message: Some(Box::new(original_message)),
            ..Default::default()
        })),
        ..Default::default()
    })),
    ..Default::default()
};

Pattern Matching

match &proto_msg {
    wa::Message { conversation: Some(text), .. } => {
        println!("Text: {}", text);
    }
    wa::Message { image_message: Some(img), .. } => {
        println!("Image from: {}", img.url.as_ref().unwrap());
    }
    wa::Message { video_message: Some(vid), .. } => {
        println!("Video: {} seconds", vid.seconds.unwrap_or(0));
    }
    _ => println!("Other message type"),
}

Media Downloads

See Media Handling for complete examples.
use waproto::whatsapp as wa;
use wacore::download::{Downloadable, MediaType};

if let Some(img) = &message.image_message {
    // Use the Downloadable trait to download and decrypt
    let data = client.download(img).await?;
}

WhatsApp Version

The protobuf definitions are based on:
// This file is @generated by prost-build.
// WhatsApp Version: 2.3000.1035617621
This version is automatically included in the generated file header.

Relationship with wacore

wacore provides utilities for working with waproto messages:
  • proto_helpers - Conversion between protobuf and internal types
  • download - Downloadable trait for media messages
  • upload - Media encryption for upload
  • messages - Message encryption/decryption
  • send - Message building and sending
Example:
use wacore::proto_helpers;
use waproto::whatsapp as wa;

// Convert internal JID to protobuf MessageKey
let key = proto_helpers::message_key(&jid, &message_id, from_me);

// Build delete message
let delete = wa::Message {
    protocol_message: Some(wa::ProtocolMessage {
        key: Some(key),
        r#type: Some(wa::protocol_message::Type::Delete as i32),
        ..Default::default()
    }),
    ..Default::default()
};

Next Steps

wacore

Platform-agnostic protocol implementation

Sending Messages

Sending and receiving messages

Media Handling

Working with media uploads and downloads

Signal Protocol

End-to-end encryption details