Chats, Presence & Privacy

The account-level surface of the socket: how your bot appears, what it does with chats, and every privacy switch WhatsApp exposes.

Presence

MethodNotes
sendPresenceUpdate(type, toJid?)type: 'available' | 'unavailable' | 'composing' | 'recording' | 'paused'. Without toJid it sets your global presence; with one, the typing/recording indicator in that chat
presenceSubscribe(toJid, tcToken?)Subscribe to a contact's presence β€” required before presence.update events arrive for them
readMessages(keys)Mark messages as read (blue ticks) β€” the polite bot pattern: read, then reply
sendReceipt(jid, participant, messageIds, type) / sendReceipts(keys, type)Lower-level receipt control: 'read' | 'read-self' | 'played' | …
await sock.sendPresenceUpdate('composing', jid)   // "typing…"
await new Promise(r => setTimeout(r, 1200))       // humans don't answer in 0 ms
await sock.sendPresenceUpdate('paused', jid)
await sock.readMessages([m.key])
await sock.sendMessage(jid, { text: 'Here you go.' })

With AunuAntiBan's typing simulation on (the default), text/caption sends do the composing step for you β€” don't double it.

Profile

MethodNotes
profilePictureUrl(jid, type?, timeoutMs?)type: 'preview' | 'image' β€” thumbnail or full-size URL. Returns undefined when the picture is private/absent
updateProfilePicture(jid, content)Set a profile picture. Since v1.0.4 the crop is centered (upstream cropped top-left) and jimp v1 works again
removeProfilePicture(jid)Remove the picture
updateProfileName(name) / updateProfileStatus(status)Your account's display name and "about" text
fetchStatus(...jids)Status/about text for numbers
getBusinessProfile(jid)Business profile (description, email, websites, hours) when the account is a business

Chat management

MethodNotes
chatModify(mod, jid)The one call behind archive/pin/mute/read state β€” see the recipes below
star(jid, messages, star)Star/unstar specific messages (messages: [{ id, fromMe }])
addChatLabel(jid, labelId) / removeChatLabel(jid, labelId)Business labels on chats
addMessageLabel(jid, messageId, labelId) / removeMessageLabel(...)Business labels on individual messages
addLabel(jid, labelAction)Create/edit label definitions
fetchDisappearingDuration(...jids)Current disappearing-message duration per chat
updateDefaultDisappearingMode(duration)Default timer for new chats (seconds)
// Archive a chat, pin another, mute a loud one for 8 hours
await sock.chatModify({ archive: true }, quietJid)
await sock.chatModify({ pin: true }, importantJid)
await sock.chatModify({ mute: Date.now() + 8 * 60 * 60 * 1000 }, loudJid)
// Mark as unread for yourself, and clear:
await sock.chatModify({ markRead: false }, jid)
await sock.chatModify({ clear: 'all' }, jid)

Blocklist & contacts

MethodNotes
fetchBlocklist()All blocked JIDs
updateBlockStatus(jid, 'block' | 'unblock')Block or unblock β€” changes fire blocklist.update
onWhatsApp(...jids)Check which numbers are registered on WhatsApp β†’ { exists, jid }[] (input in international format)
addOrEditContact(jid, contactAction) / removeContact(jid)Address-book sync actions
const [info] = await sock.onWhatsApp('12125550123')
if (info?.exists) console.log('Registered as', info.jid)

Privacy settings β€” the complete switchboard

Read everything at once with fetchPrivacySettings(); write each switch individually:

MethodValues
updateLastSeenPrivacy(value)'all' | 'contacts' | 'contact_blacklist' | 'none' (per-switch enums vary slightly β€” the types enforce them)
updateProfilePicturePrivacy(value)
updateStatusPrivacy(value)
updateGroupsAddPrivacy(value)
updateOnlinePrivacy(value)'all' | 'match_last_seen'
updateReadReceiptsPrivacy(value)'all' | 'none'
updateCallPrivacy(value)Who can call the account
updateMessagesPrivacy(value)Message-related privacy mode
updateDisableLinkPreviewsPrivacy(bool)Stop generating link previews for your own sends
Privacy is account-wide, not per-bot-session. These switches change the real WhatsApp account's settings and are visible in the phone app. Set them deliberately β€” ideally once, at provisioning time.