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
}
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 >,
// ...
}
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 >,
// ...
}
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
Feature Description Implies 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" ),
}
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