- Table of Contents
- π Performance Optimization Guide
- β¨ Main Features
- π Quick Guide
- π Advanced Cache Management
- π Troubleshooting
- π API Documentation
- πͺ Messages and Interactive Features
- Basic Messages
- Text with Formatting
- Basic Media
- Advanced Media
- Stickers
- Interactive Messages
- Messages with Simple Buttons
- Messages with Buttons and Image
- List Messages
- Collection Messages (Catalog)
- Invoice Messages
- Carousel Messages with Card Types
- Interactive Messages with Audio Footer
- Interactive Messages with Product Header
- Interactive Response Messages
- Poll Messages
- Poll Result Snapshot
- Poll Update
- Comment Messages
- Question Messages
- Question Response Messages
- Status Question Answer Messages
- Status Quoted Messages
- Status Sticker Interaction Messages
- AI Rich Response Messages
- New Interactive Features (2025)
- Other Messages
- Business Call Messages (BCall)
- Call Log Messages
- Event Response Messages
- Status Mention Messages
- Group Status Messages
- Bot Task Messages
- Limit Sharing Messages
- Status Add Yours Messages
- Bot Forwarded Messages
- Event Cover Image Messages
- Poll Creation Message V4
- Poll Creation Message V5
- Poll Result Snapshot Message V3
- Encrypted Comment Messages
- Encrypted Event Response Messages
- Message History Bundle
- Message History Notice
- Newsletter Follower Invite
- Placeholder Messages
- Secret Encrypted Messages
- Status Notification Messages
- Sticker Sync RMR Messages
- Send Payment
- Decline Payment Request
- Cancel Payment Request
- Scheduled Call Creation
- Scheduled Call Edit
- Pin/Unpin Messages
- π Group Features
- Basic Messages
- π§ Fix LID/JID in Your Own Main and Handler
- π§© Events: LID and JID always available (new)
- βοΈ Advanced Configuration
- π Support and Community
- π Acknowledgments
β οΈ Disclaimer & License
This section explains the built-in performance optimizations and JID/LID validation improvements.
The library now includes comprehensive performance optimizations with these default settings:
// Performance settings
{
enableCache: true, // Enable caching for faster data retrieval
batchSize: 50, // Process messages in batches of 50
maxRetries: 5, // Maximum reconnection attempts
retryDelay: 5000, // Initial retry delay (5 seconds)
retryBackoffMultiplier: 1.5, // Exponential backoff multiplier
maxRetryDelay: 60000, // Maximum retry delay (60 seconds)
syncFullHistory: false, // Disable full history sync to prevent slowdowns
enableLidLogging: true, // Enable LID logging for debugging
logLevel: 'debug' // Detailed logging for troubleshooting
}
// Cache settings
{
lidCache: {
ttl: 300000, // 5 minutes TTL
maxSize: 10000, // Maximum 10,000 entries
cleanupInterval: 120000 // Cleanup every 2 minutes
},
jidCache: {
ttl: 300000, // 5 minutes TTL
maxSize: 10000, // Maximum 10,000 entries
cleanupInterval: 120000 // Cleanup every 2 minutes
},
lidToJidCache: {
ttl: 300000, // 5 minutes TTL
maxSize: 5000, // Maximum 5,000 entries
cleanupInterval: 180000 // Cleanup every 3 minutes
},
groupMetadataCache: {
ttl: 600000, // 10 minutes TTL
maxSize: 2000, // Maximum 2,000 entries
cleanupInterval: 300000 // Cleanup every 5 minutes
}
}The library includes comprehensive JID/LID validation utilities:
const { validateJid, getSenderLid, toJid, normalizeJid, isValidJid } = require('@realvare/based');
// Validate JID with detailed error information
const result = validateJid('1234567890@s.whatsapp.net');
console.log(result.isValid, result.error);
// Extract sender information from messages
const sender = getSenderLid(message);
console.log(sender.jid, sender.lid, sender.user, sender.isValid, sender.timestamp, sender.error);
// Convert LID to JID format
const jid = toJid('1234567890@lid'); // Returns '1234567890@s.whatsapp.net'
// Normalize JID format
const normalized = normalizeJid('1234567890@lid'); // Returns '1234567890@s.whatsapp.net'
// Simple validation check
const isValid = isValidJid('1234567890@s.whatsapp.net');Events behavior: all emitted events (e.g. messages.upsert, messages.update, group-participants.update) will expose standard JIDs (@s.whatsapp.net, @g.us, etc.) in msg.key.remoteJid and msg.key.participant whenever possible. When WhatsApp provides LIDs, the original values are preserved in msg.key.remoteLid and msg.key.participantLid.
Performance Improvements:
- β Reduced Latency: Caching reduces repeated API calls by 80-90%
- β Better Throughput: Batch processing handles message bursts efficiently
- β Improved Stability: Exponential backoff prevents rapid reconnection attempts
- β Lower Ban Risk: Disabled full history sync and reduced online presence marking
Error Reduction:
- β JID/LID Validation: Prevents undefined errors from invalid IDs
- β Automatic Conversion: Handles WhatsApp's LID format changes seamlessly
- β Detailed Logging: Helps identify and debug ID-related issues
- β Graceful Fallback: Maintains functionality even with invalid IDs
const { makeWASocket, useMultiFileAuthState, setPerformanceConfig, PerformanceConfig } = require('@realvare/based');
// Set up authentication
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys');
// Configure performance settings
const performanceConfig = new PerformanceConfig();
// Customize settings (optional)
performanceConfig.updatePerformanceConfig({
batchSize: 50,
maxRetries: 5,
retryDelay: 5000,
retryBackoffMultiplier: 1.5,
syncFullHistory: false
});
// Apply configuration
setPerformanceConfig(performanceConfig);
// Create socket
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
});- Always validate JIDs before processing messages
- Enable caching for production environments
- Disable syncFullHistory to prevent performance issues
- Use exponential backoff for reconnection attempts
- Monitor cache metrics to optimize TTL and size settings
- Implement proper error handling for invalid JIDs/LIDs
This library, based on Baileys with specific improvements, offers an intuitive API to interact with WhatsApp Web. Here is a summary of the key features:
|
β’ Intelligent LID/JID mapping |
β’ Text, media, interactive |
β’ Real-time events |
β’ Intelligent reconnection |
- This section includes basic examples for authentication and connection management.
import makeWASocket, { DisconnectReason, useMultiFileAuthState, getPerformanceConfig, setPerformanceConfig } from '@realvare/based';
// Configure performance and cache
setPerformanceConfig({
performance: {
enableCache: true,
enableMetrics: true
},
debug: {
enableLidLogging: true,
logLevel: 'info'
}
});
async function startBot() {
// π Multi-file authentication setup for persistent sessions
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys');
// π Socket creation with basic configuration
const sock = makeWASocket({
auth: state,
printQRInTerminal: true,
logger: console,
browser: ['VareBot', 'Chrome', '4.0.0'],
});
// Improved reconnection system
let reconnectAttempts = 0;
const config = getPerformanceConfig();
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update;
if (connection === 'close') {
const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut;
if (shouldReconnect) {
reconnectAttempts++;
const delay = Math.min(
config.performance.retryDelay * Math.pow(
config.performance.retryBackoffMultiplier,
reconnectAttempts - 1
),
config.performance.maxRetryDelay
);
console.log(`π Reconnection attempt ${reconnectAttempts}/${config.performance.maxRetries} in ${delay}ms`);
if (reconnectAttempts <= config.performance.maxRetries) {
setTimeout(startBot, delay);
} else {
console.log('β Maximum number of reconnection attempts reached');
}
}
} else if (connection === 'open') {
console.log('π’ Connected successfully!');
reconnectAttempts = 0;
}
});
sock.ev.on('creds.update', saveCreds);
}startBot().catch(console.error);import makeWASocket, { DisconnectReason, useMultiFileAuthState, getPerformanceConfig, setPerformanceConfig, getSenderLid, validateJid } from '@realvare/based';
// Anti-ban configuration to reduce ban risks from improper acks
setPerformanceConfig({
performance: {
enableCache: true, // Enable TTL cache to reduce API calls
enableMetrics: true, // Monitor performance to avoid overload
batchSize: 50, // Process messages in smaller batches to simulate human speed
maxRetries: 5, // Limit retry attempts to avoid aggressive behavior
retryDelay: 5000, // Base delay in ms for reconnections
retryBackoffMultiplier: 1.5,// Exponential backoff to space retries
maxRetryDelay: 60000, // Maximum delay to avoid rapid reconnections
maxMsgRetryCount: 3 // Limit message resend attempts
}
});
async function startBot() {
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys');
const sock = makeWASocket({
auth: state,
printQRInTerminal: true,
logger: console,
browser: ['YourBotName', 'Chrome', '4.0.0'], // Customize browser fingerprint
markOnlineOnConnect: false, // Crucial: Prevents always appearing online, reduces ban risk
syncFullHistory: false // Avoid syncing unnecessary data that could signal activity
});
let reconnectAttempts = 0;
const config = getPerformanceConfig();
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update;
if (connection === 'close') {
const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut;
if (shouldReconnect) {
reconnectAttempts++;
const delay = Math.min(
config.performance.retryDelay * Math.pow(
config.performance.retryBackoffMultiplier,
reconnectAttempts - 1
),
config.performance.maxRetryDelay
);
console.log(`Reconnecting attempt ${reconnectAttempts}/${config.performance.maxRetries} in ${delay}ms`);
if (reconnectAttempts <= config.performance.maxRetries) {
setTimeout(startBot, delay);
} else {
console.log('Max reconnection attempts reached');
}
}
} else if (connection === 'open') {
console.log('Connected successfully!');
reconnectAttempts = 0;
}
});
// Monitor acks through message updates to ensure proper handling
sock.ev.on('messages.update', (updates) => {
for (const update of updates) {
if (update.update.status) {
console.log(`Message ${update.key.id} status: ${update.update.status}`); // Track acks (1=sent, 2=delivered, 3=read)
// Add custom logic if necessary, but avoid overriding defaults to prevent detection
}
}
});
// Advanced LID/JID utilities for ack stability
sock.ev.on('messages.upsert', ({ messages }) => {
for (const msg of messages) {
const info = getSenderLid(msg);
const validation = validateJid(info.jid);
if (validation.isValid) {
// Process and ack safely
console.log(`Valid JID: ${info.jid}, LID: ${info.lid}`);
} else {
console.warn(`Invalid JID detected: ${info.jid}`);
}
}
});
sock.ev.on('creds.update', saveCreds);
}
startBot().catch(console.error);The library now includes an advanced cache system with automatic memory management and configurable TTL:
import { CacheManager } from '@realvare/based';
// Example of using the cache
const cache = CacheManager;
// Save a value in the cache
cache.set('lidCache', 'key', 'value', 300); // TTL of 300 seconds
// Retrieve a value
const value = cache.get('lidCache', 'key');
// Get cache statistics
const stats = cache.getStats('lidCache');
console.log('Cache statistics:', stats);The cache can be configured with various options to optimize performance:
setPerformanceConfig({
cache: {
lidCache: {
ttl: 5 * 60 * 1000, // Entry lifetime
maxSize: 10000, // Maximum number of entries
cleanupInterval: 2 * 60 * 1000 // Cleanup interval
}
},
performance: {
memoryThreshold: 0.85 // Threshold for automatic cleanup
}
});- The library now implements a retry system with exponential backoff
- Automatic monitoring of connection status
- Configurable reconnection attempts
- Automatic monitoring of memory usage
- Automatic cache cleanup when necessary
- Configurable TTL for each cache type
setPerformanceConfig({
debug: {
enableLidLogging: true,
enablePerformanceLogging: true,
logLevel: 'debug'
}
});import makeWASocket, { getSenderLid, toJid, getCacheStats, validateJid, Logger } from '@realvare/based';
// ... (sock creation code here)
conn.ev.on('messages.upsert', ({ messages }) => {
for (const msg of messages) {
// π Extract sender LID with validation
const info = getSenderLid(msg);
// β
Validate JID before using it
const validation = validateJid(info.jid);
if (!validation.isValid) {
Logger.error('Invalid JID:', validation.error);
continue;
}
const jid = toJid(info.lid); // Normalize to JID
Logger.info('π¬ Message from:', jid, 'Valid:', info.isValid);
console.log('π Content:', msg.message?.conversation);
// Automatically reply only if valid
if (info.isValid) {
conn.sendMessage(jid, { text: 'Message received!' });
}
}
// π Monitor cache performance
const stats = getCacheStats();
Logger.performance('Cache stats:', stats);
});This section expands on the main methods, with detailed examples and parameters. All methods are typed in TypeScript for a safe development experience.
| Method | Description | Import |
|---|---|---|
makeWASocket(config) |
Core: Creates WhatsApp socket | β Included |
useMultiFileAuthState(folder) |
Auth: Persistent credentials management | β Included |
getSenderLid(msg) |
LID: Extracts LID from message | β Included |
toJid(lid) |
JID: Converts LID β JID | β Included |
validateJid(jid) |
Validation: Verifies JID | β Included |
getCacheStats() |
Performance: Cache statistics | β Included |
clearCache() |
Cleanup: Clears cache | β Included |
setPerformanceConfig(config) |
Config: Customizes performance | β Included |
π₯ Note: All the above methods are ready to use and shown in the Quick Guide. Go directly to the advanced sections for specific features!
| Event | Description | Callback Signature |
|---|---|---|
connection.update |
Connection status updates | (update: Partial<ConnectionState>) => void |
creds.update |
Credentials update | () => void |
messages.upsert |
New messages or updates | ({ messages: WAMessage[], type: MessageUpsertType }) => void |
messages.update |
Changes to existing messages | (update: WAMessageUpdate[]) => void |
group-participants.update |
Group participant changes | (update: GroupParticipantEvent) => void |
Event Registration Example:
conn.ev.on('group-participants.update', (update) => {
console.log('Participant updated:', update);
});// Text with formatting and mentions
await conn.sendMessage(jid, {
text: `*Bold* _italic_ ~strikethrough~ \`monospace\`\n@mention`,
mentions: ['393476686131@s.whatsapp.net']
});// Image
await conn.sendMessage(jid, {
image: { url: './media/varebot.jpg' }, // Also supports Buffer
caption: 'zwag'
});
// Video
await conn.sendMessage(jid, {
video: { url: './media/oppastoppa.mp4' },
caption: 'brrrr',
gifPlayback: false // true to play as GIF
});
// Audio
await conn.sendMessage(jid, {
audio: { url: './media/audio.mp3' },
mimetype: 'audio/mp4',
ptt: true // true for voice message, false for normal audio
});
// Document
await conn.sendMessage(jid, {
document: { url: './media/doc.pdf' },
mimetype: 'application/pdf',
fileName: 'document.pdf'
});// Album (Multiple images)
await conn.sendMessage(jid, {
album: imageBuffers.map(buffer => ({ image: buffer })),
caption: 'ts gettin real'
});Sending stickers is supported. You can send a sticker from a URL or a buffer. For creating stickers from images, you can use an external library like wa-sticker-formatter.
// Sticker from URL
await conn.sendMessage(jid, {
sticker: { url: './stickers/sticker.webp' }
});
// Sticker from buffer using wa-sticker-formatter
const { Sticker } = require('wa-sticker-formatter'); // Optional external library
const sticker = new Sticker('path/to/image.jpg', { pack: 'My Pack', author: 'My Bot' });
const buffer = await sticker.toBuffer();
await conn.sendMessage(jid, { sticker: buffer });Send a complete sticker pack message with multiple stickers. This allows you to send a collection of stickers as a single pack message.
await conn.sendMessage(jid, {
stickerPack: {
name: 'My Sticker Pack',
publisher: 'My Bot',
description: 'A cool sticker pack',
cover: { url: './cover.png' }, // Cover image for the pack
stickerPackId: 'pack123', // Optional: auto-generated if not provided
origin: 2, // 0 = FIRST_PARTY, 1 = THIRD_PARTY, 2 = USER_CREATED
caption: 'Check out my stickers!',
stickers: [
{
sticker: { url: './sticker1.webp' },
emojis: ['π', 'π'],
isAnimated: false,
isLottie: false,
fileName: 'sticker1.webp',
accessibilityLabel: 'Celebration sticker',
mimetype: 'image/webp'
},
{
sticker: { url: './sticker2.webp' },
emojis: ['π', 'π'],
isAnimated: true,
isLottie: false,
fileName: 'sticker2.webp'
}
]
}
});Note: For creating installable sticker packs that users can add to their WhatsApp, use the official WhatsApp Sticker Maker app. This method sends a pack as a message in the chat.
The new interactive stickers on Status (e.g., with lyrics or questions) can be sent by sending a sticker to status@broadcast.
await conn.sendMessage('status@broadcast', {
sticker: { url: './sticker.webp' },
caption: 'Interactive sticker on Status'
}, { statusJidList: ['user1@s.whatsapp.net', 'user2@s.whatsapp.net'] });These messages include interactive elements like buttons, lists, polls, carousels, collections, and invoices.
Send quick reply buttons.
await conn.sendMessage(jid, {
text: 'Choose an option:',
footer: 'Footer',
buttons: [
{ buttonId: 'cmd1', buttonText: { displayText: 'Option 1' }, type: 1 },
{ buttonId: 'cmd2', buttonText: { displayText: 'Option 2' }, type: 1 },
],
});Combine an image with buttons.
await conn.sendMessage(jid, {
image: { url: 'https://i.ibb.co/hJW7WwxV/varebot.jpg' },
caption: 'Message with buttons and image',
footer: 'vare β§ bot',
buttons: [
{ buttonId: 'cmd', buttonText: { displayText: 'text1' }, type: 1 },
],
});Send a list of options (only in private chats).
await conn.sendMessage(jid, {
text: 'This is a list!',
footer: 'purplepurplepurple!',
title: 'List Title',
buttonText: 'View List',
sections: [
{
title: 'Section 1',
rows: [
{ title: 'Option 1', rowId: 'opt1',description: 'Descriptionx' },
{ title: 'Option 2', rowId: 'opt2', description: 'Descriptiony' }
]
},
],
});Send a collection/catalog message to browse products.
await conn.sendMessage(jid, {
text: 'Browse our catalog!',
footer: 'Shop now',
title: 'Our Products',
collection: {
bizJid: 'business@s.whatsapp.net',
id: 'catalog123',
messageVersion: 1
}
});Send an invoice with attachment (image or PDF).
await conn.sendMessage(jid, {
invoice: {
note: 'Invoice for your order',
token: 'invoice_token_123',
attachmentType: 1, // 0 = IMAGE, 1 = PDF
attachment: { url: './invoice.pdf' } // or image
}
});Send a carousel of cards with different card types.
await conn.sendMessage(jid, {
text: 'Check out these options!',
footer: 'Swipe to see more',
cards: [
{
title: 'Card 1',
body: 'Description 1',
footer: 'Footer 1',
image: { url: './image1.jpg' },
buttons: [
{ name: 'quick_reply', buttonParamsJson: '{"display_text":"Button 1"}' }
]
},
{
title: 'Card 2',
body: 'Description 2',
video: { url: './video.mp4' }
}
],
carouselCardType: 1 // 1 = HSCROLL_CARDS (horizontal scroll), 2 = ALBUM_IMAGE
});Compatibility note: interactiveButtons and cards are sent as interactiveMessage and are automatically wrapped by the library in viewOnceMessageV2 to improve rendering on WhatsApp clients.
Send interactive messages with audio in the footer.
await conn.sendMessage(jid, {
text: 'Listen to this message!',
title: 'Audio Message',
interactiveButtons: [
{ name: 'action1', buttonParamsJson: '{"display_text":"Action"}' }
],
footer: {
text: 'Footer text',
audio: { url: './audio.mp3' } // Audio attachment in footer
}
});Send interactive messages with a product in the header.
await conn.sendMessage(jid, {
text: 'Check out this product!',
title: 'Featured Product',
interactiveButtons: [
{ name: 'buy', buttonParamsJson: '{"display_text":"Buy Now"}' }
],
headerProduct: {
productImage: { url: './product.jpg' },
productId: 'prod123',
title: 'Product Name',
description: 'Product Description',
currency: 'EUR',
priceAmount1000: 10000
}
});Send responses to interactive messages (e.g., Native Flow responses).
await conn.sendMessage(jid, {
interactiveResponse: {
body: {
text: 'Response text',
format: 0 // 0 = DEFAULT, 1 = EXTENSIONS_1
},
nativeFlowResponse: {
name: 'flow_name',
paramsJson: '{"key":"value"}',
version: 1
},
contextInfo: {
mentionedJid: [jid]
}
}
});Create a poll for users to vote on.
await conn.sendMessage(jid, {
poll: {
name: 'Favorite Anime?',
values: ['Aot', 'Bleach', 'Death note'],
selectableCount: 1 // or >1 for multi-select
}
});Send a snapshot of poll results.
await conn.sendMessage(jid, {
pollResultSnapshot: {
name: 'Favorite Anime?',
pollVotes: [
{ optionName: 'Aot', optionVoteCount: 10 },
{ optionName: 'Bleach', optionVoteCount: 5 },
{ optionName: 'Death note', optionVoteCount: 3 }
],
pollType: 0, // 0 = POLL, 1 = QUIZ
contextInfo: {
mentionedJid: [jid]
}
}
});Send a poll vote update.
await conn.sendMessage(jid, {
pollUpdate: {
pollCreationMessageKey: {
remoteJid: jid,
fromMe: false,
id: 'pollMessageId123'
},
vote: {
encPayload: Buffer.from('encrypted_vote_payload'),
encIv: Buffer.from('encryption_iv')
},
senderTimestampMs: Date.now()
}
});Comment on a specific message in a chat.
await conn.sendMessage(jid, {
comment: {
message: { text: 'This is a comment!' },
targetMessageKey: {
remoteJid: jid,
fromMe: false,
id: 'messageId123'
}
}
});Create a question message that users can respond to.
await conn.sendMessage(jid, {
question: {
text: 'What is your favorite programming language?',
contextInfo: {
mentionedJid: [jid]
}
}
});Respond to a question message.
await conn.sendMessage(jid, {
questionResponse: {
key: {
remoteJid: jid,
fromMe: false,
id: 'questionMessageId123'
},
text: 'My answer is TypeScript!'
}
});Answer a question posted on status.
await conn.sendMessage('status@broadcast', {
statusQuestionAnswer: {
key: {
remoteJid: 'status@broadcast',
fromMe: false,
id: 'statusQuestionId123'
},
text: 'My answer to the status question'
}
}, {
statusJidList: [jid]
});Quote a status message (e.g., question-answer reshare).
await conn.sendMessage('status@broadcast', {
statusQuoted: {
type: 1, // QUESTION_ANSWER
text: 'This is my response',
thumbnail: buffer, // optional thumbnail
originalStatusId: {
remoteJid: 'status@broadcast',
fromMe: false,
id: 'originalStatusId123'
}
}
}, {
statusJidList: [jid]
});Interact with stickers on status (e.g., reactions).
await conn.sendMessage('status@broadcast', {
statusStickerInteraction: {
key: {
remoteJid: 'status@broadcast',
fromMe: false,
id: 'statusMessageId123'
},
stickerKey: 'stickerKey123',
type: 1 // REACTION
}
}, {
statusJidList: [jid]
});Send AI-generated rich responses with multiple content types (tables, code, images, maps, etc.).
await conn.sendMessage(jid, {
ai: true,
richResponse: {
messageType: 1, // AI_RICH_RESPONSE_TYPE_STANDARD
submessages: [
{
messageType: 2, // AI_RICH_RESPONSE_TEXT
messageText: 'Here is the answer to your question'
},
{
messageType: 4, // AI_RICH_RESPONSE_TABLE
tableMetadata: {
title: 'Data Table',
rows: [
{ items: ['Header 1', 'Header 2'], isHeading: true },
{ items: ['Value 1', 'Value 2'], isHeading: false }
]
}
},
{
messageType: 5, // AI_RICH_RESPONSE_CODE
codeMetadata: {
codeLanguage: 'javascript',
codeBlocks: [
{
highlightType: 0, // DEFAULT
codeContent: 'console.log("Hello World");'
}
]
}
}
],
contextInfo: {
mentionedJid: [jid]
}
}
});Note: AI rich responses may show as "not supported" on some WhatsApp clients/accounts depending on app version and feature availability.
Send business call messages with media.
await conn.sendMessage(jid, {
bCall: {
sessionId: 'call_session_123',
mediaType: 2, // 0 = UNKNOWN, 1 = AUDIO, 2 = VIDEO
masterKey: Buffer.from('master_key_bytes'),
caption: 'Business call'
}
});Send call log information.
await conn.sendMessage(jid, {
callLog: {
isVideo: true,
callOutcome: 0, // 0 = CONNECTED, 1 = MISSED, 2 = FAILED, 3 = REJECTED, etc.
durationSecs: 120,
callType: 0, // 0 = REGULAR, 1 = SCHEDULED_CALL, 2 = VOICE_CHAT
participants: [
{ jid: 'user@s.whatsapp.net', callOutcome: 0 }
]
}
});Respond to an event message (e.g., RSVP for an event).
await conn.sendMessage(jid, {
eventResponse: {
response: 1, // GOING = 1, NOT_GOING = 2, MAYBE = 3
timestampMs: Date.now(),
extraGuestCount: 0
}
});Mention a status in another status.
await conn.sendMessage('status@broadcast', {
statusMention: {
quotedStatus: {
key: {
remoteJid: 'status@broadcast',
fromMe: false,
id: 'statusId123'
},
message: {
conversation: 'Original status message'
}
}
}
}, {
statusJidList: [jid]
});Send a status message specific to a group.
await conn.sendMessage(jid, {
groupStatus: {
message: {
conversation: 'Group status update!'
}
}
});Send a message related to a bot task.
await conn.sendMessage(jid, {
botTask: {
message: {
conversation: 'Bot task completed.'
}
}
});Send a message to limit sharing.
await conn.sendMessage(jid, {
limitSharing: {
message: {
conversation: 'Sharing limited for this message.'
}
}
});Send a "Add Yours" status message.
await conn.sendMessage('status@broadcast', {
statusAddYours: {
message: {
conversation: 'Add yours to this trend!'
}
}
}, {
statusJidList: [jid]
});Send a message that was forwarded by a bot.
await conn.sendMessage(jid, {
botForwarded: {
message: {
conversation: 'This message was forwarded by a bot.'
}
}
});Send a cover image for an event.
await conn.sendMessage(jid, {
eventCoverImage: {
message: {
imageMessage: {
url: 'https://example.com/event_cover.jpg',
mimetype: 'image/jpeg'
}
}
}
});Create a poll with additional options (version 4).
await conn.sendMessage(jid, {
pollV4: {
name: 'Favorite color (V4)?',
selectableCount: 1,
values: ['Red', 'Green', 'Blue'],
pollType: 0 // Default poll type
}
});Create a poll with additional options (version 5).
await conn.sendMessage(jid, {
pollV5: {
name: 'Favorite food (V5)?',
selectableCount: 2,
values: ['Pizza', 'Pasta', 'Sushi'],
pollType: 1 // Quiz poll type
}
});Send a snapshot of poll results (version 3).
await conn.sendMessage(jid, {
pollResultSnapshotV3: {
pollCreationMessageKey: {
remoteJid: jid,
fromMe: true,
id: 'pollMessageId123'
},
pollResult: {
vote: {
selectedOptions: [Buffer.from('Red')]
},
senderTimestampMs: Date.now()
},
contextInfo: {
mentionedJid: [jid]
},
pollType: 0 // Default poll type
}
});Send encrypted comments on messages.
await conn.sendMessage(jid, {
encComment: {
targetMessageKey: {
remoteJid: jid,
fromMe: false,
id: 'messageId123'
},
encPayload: Buffer.from('encrypted_payload'),
encIv: Buffer.from('encryption_iv')
}
});Send encrypted event responses.
await conn.sendMessage(jid, {
encEventResponse: {
eventCreationMessageKey: {
remoteJid: jid,
fromMe: false,
id: 'eventMessageId123'
},
encPayload: Buffer.from('encrypted_payload'),
encIv: Buffer.from('encryption_iv')
}
});Send a bundle of message history.
await conn.sendMessage(jid, {
messageHistoryBundle: {
mimetype: 'application/octet-stream',
media: { url: './history.bundle' },
messageHistoryMetadata: {
historyReceivers: ['user1@s.whatsapp.net', 'user2@s.whatsapp.net'],
oldestMessageTimestamp: Date.now() - 86400000,
messageCount: 100
},
contextInfo: {
mentionedJid: [jid]
}
}
});Send a notice about message history.
await conn.sendMessage(jid, {
messageHistoryNotice: {
messageHistoryMetadata: {
historyReceivers: ['user1@s.whatsapp.net'],
oldestMessageTimestamp: Date.now() - 86400000,
messageCount: 50
},
contextInfo: {
mentionedJid: [jid]
}
}
});Invite followers to a newsletter.
await conn.sendMessage(jid, {
inviteFollower: {
newsletterJid: '120363418582531215@newsletter',
newsletterName: 'My Newsletter',
thumbnail: buffer, // Optional thumbnail
caption: 'Join our newsletter!',
contextInfo: {
mentionedJid: [jid]
}
}
});Send placeholder messages (e.g., to mask linked devices).
await conn.sendMessage(jid, {
placeholder: {
type: 0 // MASK_LINKED_DEVICES = 0
}
});Send secret encrypted messages (for event or message edits).
await conn.sendMessage(jid, {
secretEncrypted: {
targetMessageKey: {
remoteJid: jid,
fromMe: false,
id: 'targetMessageId123'
},
encPayload: Buffer.from('encrypted_payload'),
encIv: Buffer.from('encryption_iv'),
secretEncType: 2 // 0 = UNKNOWN, 1 = EVENT_EDIT, 2 = MESSAGE_EDIT
}
});Send status notification messages (for status interactions).
await conn.sendMessage('status@broadcast', {
statusNotification: {
responseMessageKey: {
remoteJid: 'status@broadcast',
fromMe: false,
id: 'responseId123'
},
originalMessageKey: {
remoteJid: 'status@broadcast',
fromMe: false,
id: 'originalId123'
},
type: 1 // 0 = UNKNOWN, 1 = STATUS_ADD_YOURS, 2 = STATUS_RESHARE, 3 = STATUS_QUESTION_ANSWER_RESHARE
}
}, {
statusJidList: [jid]
});Sync stickers via RMR (Recent Media Request).
await conn.sendMessage(jid, {
stickerSyncRMR: {
filehash: ['hash1', 'hash2', 'hash3'],
rmrSource: 'source_identifier',
requestTimestamp: Date.now()
}
});// Payment Messages
await conn.sendMessage(jid, {
requestPayment: {
currency: 'EUR',
amount1000: 5000,
requestFrom: '393514357738@s.whatsapp.net',
note: 'js gimme my money' // https://paypal.me/samakavare
}
});await conn.sendMessage(jid, {
sendPayment: {
requestMessageKey: {
remoteJid: jid,
fromMe: false,
id: 'paymentRequestId123'
},
noteMessage: { text: 'Payment sent' },
background: {
id: 'payment_bg_id',
type: 1 // DEFAULT = 1
},
transactionData: 'transaction_data_string'
}
});await conn.sendMessage(jid, {
declinePayment: {
key: {
remoteJid: jid,
fromMe: false,
id: 'paymentRequestId123'
}
}
});await conn.sendMessage(jid, {
cancelPayment: {
key: {
remoteJid: jid,
fromMe: true,
id: 'paymentRequestId123'
}
}
});await conn.sendMessage(jid, {
call: {
callKey: {
fromMe: true,
id: Date.now().toString(),
remoteJid: jid
},
type: 'ACCEPT', // 'MISSED', 'OFFER', 'ACCEPT', 'REJECT'..
time: Date.now() + 3600000, // Scheduled time (optional)
title: 'Team Meeting' // Optional title
}
});await conn.sendMessage(jid, {
scheduledCallEdit: {
key: {
remoteJid: jid,
fromMe: true,
id: 'scheduledCallId123'
},
editType: 1 // 0 = UNKNOWN, 1 = CANCEL
}
});Pin or unpin a message in a chat.
// Pin a message (type 1 = PIN_FOR_ALL)
await conn.sendMessage(jid, {
pin: {
key: {
remoteJid: jid,
fromMe: false,
id: 'messageId123'
},
type: 1, // 1 = PIN_FOR_ALL, 2 = UNPIN_FOR_ALL
time: 86400 // Duration in seconds (24 hours = 86400, 7 days = 604800, 30 days = 2592000)
}
});
// Or use simplified syntax
await conn.sendMessage(jid, {
pin: {
remoteJid: jid,
fromMe: false,
id: 'messageId123'
},
type: 1, // 1 = PIN_FOR_ALL, 2 = UNPIN_FOR_ALL
time: 86400 // Optional: duration in seconds
});
// Unpin a message (type 2 = UNPIN_FOR_ALL)
await conn.sendMessage(jid, {
pin: {
key: {
remoteJid: jid,
fromMe: false,
id: 'messageId123'
},
type: 2 // UNPIN_FOR_ALL
}
});To manage responses to interactive messages, use the messages.upsert listener and check the response type:
conn.ev.on('messages.upsert', async ({ messages }) => {
const msg = messages[0];
// Button response
if (msg.message?.buttonsResponseMessage) {
const selectedId = msg.message.buttonsResponseMessage.selectedButtonId;
console.log(`Selected button: ${selectedId}`);
}
// List response
if (msg.message?.listResponseMessage) {
const selectedId = msg.message.listResponseMessage.singleSelectReply.selectedRowId;
console.log(`Selected option: ${selectedId}`);
}
// Poll response
if (msg.message?.pollResponseMessage) {
const selectedOptions = msg.message.pollResponseMessage.selectedOptions;
console.log('Selected options:', selectedOptions);
}
// Comment response
if (msg.message?.commentMessage) {
const comment = msg.message.commentMessage;
console.log('Comment on message:', comment.targetMessageKey?.id);
console.log('Comment content:', comment.message);
}
// Question response
if (msg.message?.questionResponseMessage) {
const response = msg.message.questionResponseMessage;
console.log('Response to question:', response.key?.id);
console.log('Answer:', response.text);
}
// Status question answer
if (msg.message?.statusQuestionAnswerMessage) {
const answer = msg.message.statusQuestionAnswerMessage;
console.log('Status question answer:', answer.text);
}
// AI Rich Response
if (msg.message?.richResponseMessage) {
const richResponse = msg.message.richResponseMessage;
console.log('AI Rich Response type:', richResponse.messageType);
console.log('Submessages:', richResponse.submessages);
}
// Interactive Response (Native Flow Response)
if (msg.message?.interactiveResponseMessage) {
const response = msg.message.interactiveResponseMessage;
console.log('Interactive response body:', response.body?.text);
if (response.nativeFlowResponseMessage) {
console.log('Native flow response:', response.nativeFlowResponseMessage.name);
console.log('Params:', response.nativeFlowResponseMessage.paramsJson);
}
}
// Sticker Pack
if (msg.message?.stickerPackMessage) {
const pack = msg.message.stickerPackMessage;
console.log('Sticker pack:', pack.name);
console.log('Publisher:', pack.publisher);
console.log('Stickers count:', pack.stickers?.length);
console.log('Pack ID:', pack.stickerPackId);
console.log('Origin:', pack.stickerPackOrigin);
}
// Collection/Catalog response
if (msg.message?.interactiveMessage?.collectionMessage) {
const collection = msg.message.interactiveMessage.collectionMessage;
console.log('Collection opened:', collection.id);
console.log('Business JID:', collection.bizJid);
}
// Invoice response
if (msg.message?.invoiceMessage) {
const invoice = msg.message.invoiceMessage;
console.log('Invoice token:', invoice.token);
console.log('Invoice note:', invoice.note);
console.log('Attachment type:', invoice.attachmentType === 0 ? 'IMAGE' : 'PDF');
}
// Business Call
if (msg.message?.bcallMessage) {
const bcall = msg.message.bcallMessage;
console.log('Business call session:', bcall.sessionId);
console.log('Media type:', bcall.mediaType === 1 ? 'AUDIO' : 'VIDEO');
}
// Call Log
if (msg.message?.callLogMesssage) {
const callLog = msg.message.callLogMesssage;
console.log('Call outcome:', callLog.callOutcome);
console.log('Duration:', callLog.durationSecs, 'seconds');
console.log('Participants:', callLog.participants);
}
// Encrypted Comment
if (msg.message?.encCommentMessage) {
const encComment = msg.message.encCommentMessage;
console.log('Encrypted comment on message:', encComment.targetMessageKey?.id);
}
// Encrypted Event Response
if (msg.message?.encEventResponseMessage) {
const encEvent = msg.message.encEventResponseMessage;
console.log('Encrypted event response for:', encEvent.eventCreationMessageKey?.id);
}
// Message History Bundle
if (msg.message?.messageHistoryBundle) {
const bundle = msg.message.messageHistoryBundle;
console.log('History bundle receivers:', bundle.messageHistoryMetadata?.historyReceivers);
console.log('Message count:', bundle.messageHistoryMetadata?.messageCount);
}
// Message History Notice
if (msg.message?.messageHistoryNotice) {
const notice = msg.message.messageHistoryNotice;
console.log('History notice receivers:', notice.messageHistoryMetadata?.historyReceivers);
}
// Newsletter Follower Invite
if (msg.message?.newsletterFollowerInviteMessageV2) {
const invite = msg.message.newsletterFollowerInviteMessageV2;
console.log('Newsletter invite:', invite.newsletterName);
console.log('Newsletter JID:', invite.newsletterJid);
}
// Placeholder
if (msg.message?.placeholderMessage) {
const placeholder = msg.message.placeholderMessage;
console.log('Placeholder type:', placeholder.type);
}
// Secret Encrypted
if (msg.message?.secretEncryptedMessage) {
const secret = msg.message.secretEncryptedMessage;
console.log('Secret encrypted type:', secret.secretEncType);
console.log('Target message:', secret.targetMessageKey?.id);
}
// Status Notification
if (msg.message?.statusNotificationMessage) {
const notification = msg.message.statusNotificationMessage;
console.log('Status notification type:', notification.type);
console.log('Original message:', notification.originalMessageKey?.id);
}
// Sticker Sync RMR
if (msg.message?.stickerSyncRmrMessage) {
const sync = msg.message.stickerSyncRmrMessage;
console.log('Sticker sync filehashes:', sync.filehash);
console.log('RMR source:', sync.rmrSource);
}
// Send Payment
if (msg.message?.sendPaymentMessage) {
const payment = msg.message.sendPaymentMessage;
console.log('Payment sent for request:', payment.requestMessageKey?.id);
console.log('Transaction data:', payment.transactionData);
}
// Decline Payment
if (msg.message?.declinePaymentRequestMessage) {
const decline = msg.message.declinePaymentRequestMessage;
console.log('Payment declined for:', decline.key?.id);
}
// Cancel Payment
if (msg.message?.cancelPaymentRequestMessage) {
const cancel = msg.message.cancelPaymentRequestMessage;
console.log('Payment cancelled for:', cancel.key?.id);
}
// Scheduled Call Edit
if (msg.message?.scheduledCallEditMessage) {
const edit = msg.message.scheduledCallEditMessage;
console.log('Scheduled call edited:', edit.key?.id);
console.log('Edit type:', edit.editType === 1 ? 'CANCEL' : 'UNKNOWN');
}
// Poll Result Snapshot
if (msg.message?.pollResultSnapshotMessage) {
const snapshot = msg.message.pollResultSnapshotMessage;
console.log('Poll snapshot:', snapshot.name);
console.log('Votes:', snapshot.pollVotes);
}
// Poll Update
if (msg.message?.pollUpdateMessage) {
const update = msg.message.pollUpdateMessage;
console.log('Poll update for:', update.pollCreationMessageKey?.id);
}
// Pin/Unpin
if (msg.message?.pinInChatMessage) {
const pin = msg.message.pinInChatMessage;
console.log('Pin action:', pin.type === 1 ? 'PIN_FOR_ALL' : 'UNPIN_FOR_ALL');
console.log('Pinned message:', pin.key?.id);
}
});// Group creation - the jid is for adding participants
const group = await conn.groupCreate('Angels π©ΈποΈ', ['user@s.whatsapp.net']);
// Get group info
const metadata = await conn.groupMetadata(jid);
// Get invite code
const code = await conn.groupInviteCode(jid);
// Revoke invite link
await conn.groupRevokeInvite(jid);
// Leave group
await conn.groupLeave(jid);// Add participants
await conn.groupParticipantsUpdate(
jid,
['user@s.whatsapp.net'],
'add'
);
// Remove participants
await conn.groupParticipantsUpdate(
jid,
['user@s.whatsapp.net'],
'remove'
);
// Promote to admin
await conn.groupParticipantsUpdate(
jid,
['user@s.whatsapp.net'],
'promote'
);
// Demote from admin
await conn.groupParticipantsUpdate(
jid,
['user@s.whatsapp.net'],
'demote'
);// Change group name
await conn.groupUpdateSubject(jid, 'New Name');
// Change description
await conn.groupUpdateDescription(jid, 'New description');
// Change group photo
await conn.updateProfilePicture(jid, { url: './img/group.jpg' });
// Remove group photo
await conn.removeProfilePicture(jid);
// Set group as admin only
await conn.groupSettingUpdate(jid, 'announcement');
// Set group as open to all
await conn.groupSettingUpdate(jid, 'not_announcement');
// Set who can edit info - admin only
await conn.groupSettingUpdate(jid, 'locked');
// Set who can edit info - all
await conn.groupSettingUpdate(jid, 'unlocked');
// Set who can add members - admin only
await conn.groupMemberAddMode(jid, 'admin_add');
// Set who can add members - all
await conn.groupMemberAddMode(jid, 'all_member_add');
// Enable/disable temporary messages (24 hours)
await conn.groupToggleEphemeral(jid, 86400); // seconds
// Disable temporary messages
await conn.groupToggleEphemeral(jid, 0);
// Enable/disable membership approval mode
await conn.groupJoinApprovalMode(jid, 'on'); // requires approval
await conn.groupJoinApprovalMode(jid, 'off'); // open
// Get all groups
const groups = await conn.groupFetchAllParticipating();
// Get pending invites
const invites = await conn.groupGetInviteInfo(code);
// Accept group invite
await conn.groupAcceptInvite(code);
// Get group info from link
const groupInfo = await conn.groupGetInviteInfo('https://chat.whatsapp.com/ABC123');
// Listen to settings changes
conn.ev.on('group-settings.update', async ({ id, announce, restrict }) => {
if (announce !== undefined) {
await conn.sendMessage(id, { text: `The group has been set to ${announce ? 'admin only' : 'all'}` });
}
if (restrict !== undefined) {
await conn.sendMessage(id, { text: `Group info can be edited by ${restrict ? 'admin only' : 'all'}` });
}
});// Message with multiple mentions
await conn.sendMessage(jid, {
text: '@user1 @user2 @user3',
mentions: [user1, user2, user3],
contextInfo: {
mentionedJid: [user1, user2, user3]
}
});
// Message with Google search
await conn.sendMessage(jid, {
text: 'ZWAG',
contextInfo: {
forwardingScore: 999,
isForwarded: true
}
});The LID/JID support is a strength of this library, solving common problems like sender identification in groups and private chats. Here's how to integrate it into your main code and handler.
- JID Normalization: The library automatically handles JID/LID normalization in most cases.
- Use Built-in Functions: Prefer
toJid(),normalizeJid(), andvalidateJid()from the library. - Cache Management: The library includes automatic caching for LID/JID conversions.
Common Use Cases:
- Group Participants: Use
toJid()to normalize participant IDs before operations. - Message Sender: Extract sender info with
getSenderLid()for reliable identification. - Validation: Always validate JIDs with
validateJid()before critical operations.
import makeWASocket, { getSenderLid, toJid, validateJid } from '@realvare/based';
conn.ev.on('messages.upsert', async ({ messages }) => {
const msg = messages[0];
if (!msg.message) return;
const info = getSenderLid(msg);
const senderJid = toJid(info.lid);
// Validate before using
const validation = validateJid(senderJid);
if (validation.isValid) {
await conn.sendMessage(senderJid, { text: 'Message received!' }, { quoted: msg });
}
});The library now includes an advanced cache system to optimize LID/JID conversions:
import { getCacheStats, clearCache, setPerformanceConfig } from '@realvare/based';
// Configure custom cache
setPerformanceConfig({
cache: {
lidCache: {
ttl: 10 * 60 * 1000, // 10 minutes
maxSize: 15000
}
}
});
// Monitor performance
const stats = getCacheStats();
console.log('LID Cache:', stats.lidCache.size, '/', stats.lidCache.maxSize);
// Clear cache if necessary
clearCache();import { validateJid, Logger } from '@realvare/based';
const jid = '1234567890@s.whatsapp.net';
const validation = validateJid(jid);
if (validation.isValid) {
Logger.info('Valid JID:', jid);
} else {
Logger.error('Invalid JID:', validation.error);
}import { Logger, setPerformanceConfig } from '@realvare/based';
// Configure logging
setPerformanceConfig({
debug: {
enableLidLogging: true,
enablePerformanceLogging: true,
logLevel: 'debug' // 'error', 'warn', 'info', 'debug'
}
});
// Use conditional logger
Logger.debug('Debug info');
Logger.performance('Performance metrics');
Logger.error('Error occurred');import { setPerformanceConfig, getPerformanceConfig } from '@realvare/based';
// Complete configuration
setPerformanceConfig({
performance: {
enableCache: true,
enableMetrics: true,
batchSize: 100,
maxRetries: 3
},
cache: {
lidCache: { ttl: 5 * 60 * 1000, maxSize: 10000 },
jidCache: { ttl: 5 * 60 * 1000, maxSize: 10000 }
},
debug: {
enableLidLogging: false,
logLevel: 'warn'
}
});
// Get current configuration
const config = getPerformanceConfig();
console.log('Cache enabled:', config.performance.enableCache);The library enriches event payloads to provide both JID and LID, eliminating ambiguity in multi-device and group contexts.
Key Features:
- Automatic JID/LID normalization in events
- Pre-normalized fields in
msg.key(remoteJidNormalized,remoteLid,participantLid) - Seamless conversion with
toJid()andnormalizeJid()
Refer to the examples in the Quick Guide and API Documentation sections for practical usage.
Customize the socket for performance and behavior.
const sock = makeWASocket({
// π Authentication
auth: state,
// π₯οΈ UI and Debug
printQRInTerminal: true,
logger: console,
browser: ['VareBot', 'Chrome', '4.0.0'],
// β±οΈ Timeout and Connection
defaultQueryTimeoutMs: 60000,
keepAliveIntervalMs: 30000,
connectTimeoutMs: 60000,
retryRequestDelayMs: 250,
maxMsgRetryCount: 5,
// ποΈ Behavior
markOnlineOnConnect: false, // Recommended: false to reduce ban risk
syncFullHistory: false, // Keep false to prevent slowdowns
fireInitQueries: true,
generateHighQualityLinkPreview: true,
});| Feature | Description |
|---|---|
| π End-to-End Encryption | Signal protocol for secure messages |
| π Key Management | Automatic key generation/rotation |
| π Authentication | Security via QR code or pairing code |
| π‘οΈ Data Protection | Secure local credentials storage |
Join the community for help and contributions.
| Channel | Link/Info |
|---|---|
| samakavare1@gmail.com | |
| GitHub Issues | Report Bug |
| PayPal | Donate |
| WhatsApp Channel | Channel |
Thanks to the projects that inspire Based:
| Project | Contribution |
|---|---|
| Baileys | Original WhatsApp Web API |
| Yupra | LID/JID Fix |
| Signal Protocol | End-to-end encryption |
π‘οΈ Responsible Use: Avoid spam, WhatsApp ToS violations. Risk of account ban.
MIT License Β© 2025 realvare
See LICENSE for details.
π¨βπ» Created by realvaresam aka vare |

