The Contacts struct provides methods for checking WhatsApp registration status and retrieving profile pictures and user information.
Access
Access contact operations through the client:
Methods
is_on_whatsapp
Check if JIDs are registered on WhatsApp. Accepts both PN JIDs and LID JIDs.
Parameters:
jids - Array of JIDs to check. Supports Jid::pn("phone_number") for phone number lookups and Jid::lid("lid_value") for LID lookups. If you pass a non-PN/non-LID JID (groups, newsletters, etc.), the method returns an error immediately.
Returns:
Vec<IsOnWhatsAppResult> - Registration status for each JID
IsOnWhatsAppResult fields:
jid: Jid - WhatsApp JID for the user
is_registered: bool - Whether the JID is on WhatsApp
lid: Option<Jid> - LID (Linked Identity) if available
pn_jid: Option<Jid> - Phone number JID, present when the server returns LID as the primary JID
is_business: bool - Whether this is a WhatsApp Business account
verified_name: Option<VerifiedName> - Decoded verified business name certificate, when the account is a verified business
contact_error: Option<UsyncSubprotocolError> - Server error for the contact subprotocol (e.g. privacy-blocked lookup); is_registered will be false
lid_error: Option<UsyncSubprotocolError> - Server error for the lid subprotocol; lid will be None
business_error: Option<UsyncSubprotocolError> - Server error for the business subprotocol; is_business will be false
VerifiedName fields:
name: Option<String> - Display name shown to other users (decoded from the certificate when the server omits the attribute)
serial: Option<String> - Certificate serial number
issuer: Option<String> - Certificate issuer
certificate: Option<Vec<u8>> - Raw VerifiedNameCertificate protobuf bytes, for callers that need to verify the signature themselves
IsOnWhatsAppResult is marked #[non_exhaustive], so new fields may be added in future versions without a breaking change.
Example — phone number lookup:
Example — LID lookup:
PN and LID queries use different wire protocols (matching WhatsApp Web’s ExistsJob), so mixed inputs are automatically split into separate requests. LID-PN mappings discovered from results are persisted to the local cache.
get_profile_picture
Get the profile picture URL for a JID.
Parameters:
jid - Target JID (user, group, or newsletter)
preview - true for preview thumbnail, false for full-size image
Returns:
Option<ProfilePicture> - Picture info or None if not available
ProfilePicture fields:
id: String - Picture ID
url: String - Download URL
direct_path: Option<String> - Direct path for media download
hash: Option<String> - SHA-256 hash for integrity and cache validation
Example:
For groups:
get_user_info
Get user information by JID.
Parameters:
jids - Array of JIDs to query
Returns:
HashMap<Jid, UserInfo> - Map of JID to user info
UserInfo fields:
jid: Jid - WhatsApp JID
lid: Option<Jid> - LID if available
lid_error: Option<UsyncSubprotocolError> - Server error for the lid subprotocol; lid will be None
status: Option<String> - Status message
status_error: Option<UsyncSubprotocolError> - Server error for the status subprotocol (e.g. privacy-hidden status); status will be None
picture_id: Option<String> - Profile picture ID
picture_error: Option<UsyncSubprotocolError> - Server error for the picture subprotocol; picture_id will be None
is_business: bool - Whether business account
business_error: Option<UsyncSubprotocolError> - Server error for the business subprotocol; is_business will be false
verified_name: Option<VerifiedName> - Decoded verified business name certificate, for verified business accounts (see is_on_whatsapp for field details)
devices: Vec<u16> - Device IDs from the <devices version="2"> sublist the same usync query returns (device 0 is the primary). Empty when the server omits the sublist — no extra request is needed.
devices_error: Option<UsyncSubprotocolError> - Server error for the devices subprotocol; devices will be empty
UserInfo is #[non_exhaustive], so new fields may be added in future versions without a breaking change.
UsyncSubprotocolError fields:
code: Option<u16> - Numeric error code from the server (e.g. 403, 404)
text: Option<String> - Human-readable error description
backoff: Option<u32> - Server-suggested retry delay in seconds
The library preserves per-subprotocol errors on the result struct rather than failing the whole request. A privacy error from one user’s status does not block retrieval of devices for other users in the same batch. Check the *_error fields when a corresponding Option field is None and you need to distinguish “not set” from “server error”.
Example:
Privacy & TC tokens
For user JIDs (not groups/newsletters), the library automatically includes TC tokens when fetching profile pictures. TC tokens are used for privacy-gated operations.
The implementation automatically:
- Looks up TC tokens for user JIDs
- Includes tokens in profile picture requests
- Skips tokens for groups and newsletters
get_user_info does the same for status/about: when the profile_scraping_privacy_token_in_about_usync AB prop is on, each queried JID’s TC token is attached to its <user> node in the usync IQ, matching WhatsApp Web’s USyncStatusProtocol. This is what lets status/status_error and about resolve correctly for a privacy-restricted contact instead of coming back hidden. See TC Token for details.
Async compatibility
is_on_whatsapp and get_user_info work correctly when called from #[async_trait] implementations or any context that boxes the returned future (Box<dyn Future + Send>). Earlier versions produced a compile error ("implementation of FnOnce is not general enough") that could not be worked around in user code. Fixed in #826 with no API changes.
Error handling
All methods return Result<T, ContactError>:
Batch operations
All lookup methods support batch operations for efficiency:
The server sends contacts notifications when contact data changes. These are emitted as events you can subscribe to:
ContactUpdated — a contact’s profile changed (invalidate cached presence/profile picture)
ContactNumberChanged — a contact changed their phone number (includes old/new JID and optional LID mappings)
ContactSyncRequested — the server requests a full contact re-sync
See the events reference for full struct definitions and wire format details.
Passing empty arrays returns empty results without making network requests:
Migration from previous versions
The is_on_whatsapp method previously accepted &[&str] (phone number strings). It now takes &[Jid]:
The get_info method and ContactInfo type have been removed. Use is_on_whatsapp for registration checks (now includes lid, pn_jid, and is_business fields) or get_user_info for detailed profile data (status, picture ID).