Multi Session Whatsapp Library with MongoDB Integration
npm install wa-multi-mongodbLightweight library for WhatsApp with MongoDB integration. No Selenium or browser required.
Built on Baileys Library.
Install package using npm:
``bash`
npm install wa-multi-mongodb@latest
Then import into your code:
`typescript
// Using ES modules
import * as whatsapp from "wa-multi-mongodb";
// Or using CommonJS
const whatsapp = require("wa-multi-mongodb");
`
For secure MongoDB URI management, we recommend using environment variables:
1. Create a .env file in your project root (copy from .env.example):`
# MongoDB Configuration
MONGODB_URI=mongodb://username:password@hostname:port/database
# Optional database settings
WA_DB_NAME=wa_session
WA_COLLECTION_NAME=auth
`
2. Install and use the dotenv package:
`javascript
// Load environment variables
require('dotenv').config();
// Use in your code
const MONGODB_URI = process.env.MONGODB_URI;
if (!MONGODB_URI) {
console.error('Error: MONGODB_URI not found in environment variables');
process.exit(1);
}
// Initialize WhatsApp with MongoDB
await whatsapp.setMongoURI(MONGODB_URI);
`
3. Make sure to add .env to your .gitignore file to prevent exposing sensitive credentials
javascript
require('dotenv').config();
await whatsapp.setMongoURI(process.env.MONGODB_URI);
` Directly in code (not recommended for production):
`javascript
await whatsapp.setMongoURI("mongodb+srv://username:password@host/db?options");
`3. Optionally customize the database and collection names:
`javascript
// Default values are "wa_session" and "auth"
whatsapp.setMongoDBNames("custom_database_name", "custom_collection_name");
`Basic Usage
$3
`javascript
// Start a new session with QR Code
const session = await whatsapp.startSession("mysession");// Start with options
await whatsapp.startSession("mysession2", {
printQR: true,
onConnected: () => console.log("Connected!"),
onDisconnected: () => console.log("Disconnected!"),
onQRUpdated: (qr) => {
console.log("New QR:", qr);
// QR data is raw and ready for frontend use
// You can display this in React, Vue, Angular, etc.
}
});
// Start with custom browser configuration (v3.10.4+)
// Display: "Safari (Mac OS)" in WhatsApp Linked Devices
await whatsapp.startSession("mysession3", {
printQR: true,
browserType: "macOS", // Options: "ubuntu", "macOS", "windows", "appropriate"
browserName: "Safari", // Valid: Chrome, Safari, Firefox, Edge, Opera, IE, Desktop
onConnected: () => console.log("Connected with custom browser!"),
});
// Start session with Pairing Code (v3.9.6+)
await whatsapp.startSessionWithPairingCode("mysession4", "6281234567890", {
onConnected: () => console.log("Pairing session connected!"),
onDisconnected: () => console.log("Pairing session disconnected!"),
onPairingCode: (code) => {
console.log("Pairing code:", code);
// Enter this code in your WhatsApp app: Settings > Linked Devices > Link a Device > Link with phone number
}
});
// Pairing code with valid browser config - displays "Edge (Windows)"
// ⚠️ IMPORTANT: Pairing code ONLY works with valid browser configurations!
await whatsapp.startSessionWithPairingCode("mysession5", "6281234567890", {
browserType: "windows",
browserName: "Edge", // Must be valid: Chrome, Safari, Firefox, Edge, Opera, IE, Desktop
onPairingCode: (code) => console.log("Code:", code),
});
// Get all active sessions
const sessions = await whatsapp.getAllSession();
// Get data for a specific session
const sessionData = whatsapp.getSession("mysession");
// Load all saved sessions from MongoDB
await whatsapp.loadSessionsFromMongo();
// Session Management Utilities (v3.9.6+)
// Get session status with detailed information
const status = await whatsapp.getSessionStatus("mysession");
console.log("Session status:", status);
// Returns: { exists: true, connected: true, sessionType: 'qr' | 'pairing' }
// Manual reconnection for any session
try {
const reconnected = await whatsapp.reconnect("mysession");
console.log("Reconnection successful:", reconnected);
} catch (error) {
console.error("Reconnection failed:", error);
}
// Get all pairing code sessions
const pairingSessions = whatsapp.getPairingCodeSessions();
console.log("Pairing code sessions:", pairingSessions);
// Bulk reconnect all pairing code sessions
await whatsapp.reconnectAllPairingCodeSessions();
`$3
Customize how your session appears in WhatsApp's "Linked Devices" list.
Display Format in WhatsApp:
browserName (OsName) - e.g., "Safari (Mac OS)"#### Valid browserName Values
These are recognized by WhatsApp and will display correctly:
| browserName | Description |
|-------------|-------------|
|
"Chrome" | Google Chrome (default) |
| "Safari" | Apple Safari |
| "Firefox" | Mozilla Firefox |
| "Edge" | Microsoft Edge |
| "Opera" | Opera Browser |
| "IE" | Internet Explorer |
| "Desktop" | Generic Desktop App |#### browserType Options
| browserType | OS Name Displayed | OS Version |
|-------------|-------------------|------------|
|
"ubuntu" | Ubuntu | 22.04.4 |
| "macOS" | Mac OS | 14.4.1 |
| "windows" | Windows | 10.0.22631 |
| "appropriate" | Auto-detect | Based on platform |#### Usage Examples
`javascript
// Safari on macOS → displays as "Safari (Mac OS)"
await whatsapp.startSession("session1", {
printQR: true,
browserType: "macOS",
browserName: "Safari",
});// Chrome on Windows → displays as "Chrome (Windows)"
await whatsapp.startSession("session2", {
printQR: true,
browserType: "windows",
browserName: "Chrome",
});
// Firefox on Ubuntu → displays as "Firefox (Ubuntu)"
await whatsapp.startSession("session3", {
printQR: true,
browserType: "ubuntu",
browserName: "Firefox",
});
// Edge on Windows → displays as "Edge (Windows)"
await whatsapp.startSession("session4", {
printQR: true,
browserType: "windows",
browserName: "Edge",
});
// Desktop app on macOS → displays as "Desktop (Mac OS)"
await whatsapp.startSession("session5", {
printQR: true,
browserType: "macOS",
browserName: "Desktop",
});
// Custom name (fallback to Chrome) → displays as "Chrome (My Bot App)"
await whatsapp.startSession("session6", {
printQR: true,
browserType: "windows",
browserName: "My Bot App",
});
// Custom name with Safari → displays as "Safari (My Bot App)"
await whatsapp.startSession("session7", {
printQR: true,
browserType: "macOS",
browserName: "My Bot App",
displayBrowser: "Safari", // Choose which browser type to display
});
// Custom name with Firefox → displays as "Firefox (Device Bot)"
await whatsapp.startSession("session8", {
printQR: true,
browserType: "ubuntu",
browserName: "Device Bot",
displayBrowser: "Firefox",
});
`#### displayBrowser Parameter (v3.10.5+)
When using a custom
browserName, you can now choose which browser type to display using the displayBrowser parameter:| displayBrowser | Custom Name Example | Display Result |
|----------------|---------------------|----------------|
|
"Chrome" (default) | "My Bot" | Chrome (My Bot) |
| "Safari" | "My Bot" | Safari (My Bot) |
| "Firefox" | "My Bot" | Firefox (My Bot) |
| "Edge" | "My Bot" | Edge (My Bot) |
| "Opera" | "My Bot" | Opera (My Bot) |
| "Desktop" | "My Bot" | Desktop (My Bot) |> Note:
displayBrowser is only used when browserName is a custom name (not a valid browser type like Chrome, Safari, etc.).> [!WARNING]
> Custom browserName and displayBrowser are NOT supported for Pairing Code sessions!
>
> WhatsApp server validates browser configuration strictly during pairing code authentication. You MUST use valid browser configurations for pairing code:
>
> | browserType | browserName | Display | Pairing Code |
> |-------------|-------------|---------|--------------|
> |
"windows" | "Chrome" | Chrome (Windows) | ✅ Works |
> | "macOS" | "Safari" | Safari (Mac OS) | ✅ Works |
> | "windows" | "Edge" | Edge (Windows) | ✅ Works |
> | "ubuntu" | "Firefox" | Firefox (Ubuntu) | ✅ Works |
> | "windows" | "My Bot" | Chrome (My Bot) | ❌ Fails |
>
> Custom names (like "My Bot App") only work with QR Code authentication.$3
You can use a proxy for WebSocket connections and media upload/download. No additional dependencies are included - install your preferred proxy agent package if needed.
#### Install Proxy Agent (User's Choice)
`bash
For HTTP/HTTPS proxy
npm install https-proxy-agentFor SOCKS4/SOCKS5 proxy
npm install socks-proxy-agent
`#### Usage Examples
`javascript
// Using HTTPS proxy
import { HttpsProxyAgent } from 'https-proxy-agent';const proxyAgent = new HttpsProxyAgent('http://proxy.example.com:8080');
// With authentication: new HttpsProxyAgent('http://user:pass@proxy.example.com:8080');
await whatsapp.startSession("mysession", {
printQR: true,
agent: proxyAgent, // Proxy for WebSocket connection
fetchAgent: proxyAgent, // Proxy for media upload/download (optional, defaults to agent)
});
// Using SOCKS5 proxy
import { SocksProxyAgent } from 'socks-proxy-agent';
const socksAgent = new SocksProxyAgent('socks5://127.0.0.1:1080');
// With authentication: new SocksProxyAgent('socks5://user:pass@127.0.0.1:1080');
await whatsapp.startSessionWithPairingCode("mysession", "6281234567890", {
browserType: "windows",
browserName: "Chrome",
agent: socksAgent,
});
`| Option | Type | Description |
|--------|------|-------------|
|
agent | Agent | Proxy agent for WebSocket connection |
| fetchAgent | Agent | Proxy agent for media upload/download (defaults to agent) |> Note: Proxy is optional. If not provided, direct connection is used.
$3
`javascript
// Send text message
await whatsapp.sendTextMessage({
sessionId: "mysession",
to: "6281234567890", // always include country code
text: "Hello from wa-multi-mongodb!"
// isGroup parameter is optional (v3.9.0+)
// The library will automatically detect if the destination is a group
});// Send to a group (automatic detection in v3.9.0+)
await whatsapp.sendTextMessage({
sessionId: "mysession",
to: "120363152682073800", // group ID
text: "Hello group!"
// No need for isGroup: true parameter in v3.9.0+
});
// Send to a group (compatible with older versions)
await whatsapp.sendTextMessage({
sessionId: "mysession",
to: "120363152682073800", // group ID
text: "Hello group!",
isGroup: true // still works but optional in v3.9.0+
});
// Send media (unified function)
await whatsapp.sendMedia({
sessionId: "mysession",
to: "6281234567890",
type: "image", // options: image, video, pdf, doc, docx, xls, xlsx, zip, mp3
media: fs.readFileSync("./image.jpg"), // or URL string
caption: "Image caption",
fileName: "image.jpg", // required for documents
// isGroup parameter is optional (v3.9.0+)
});
// Send voice note
await whatsapp.sendVoiceNote({
sessionId: "mysession",
to: "6281234567890",
media: fs.readFileSync("./audio.mp3"),
// isGroup parameter is optional (v3.9.0+)
});
// Mark message as read
await whatsapp.readMessage({
sessionId: "mysession",
key: msg.key,
});
// Send typing indicator
await whatsapp.sendTyping({
sessionId: "mysession",
to: "6281234567890", // or group ID
duration: 3000, // milliseconds
// isGroup parameter is optional (v3.9.0+)
});
// Delete message (v3.9.5+)
// Delete own message for everyone
await whatsapp.deleteMessage({
sessionId: "mysession",
key: messageObject.key, // message key from received or sent message
});
// Delete someone else's message (requires admin permissions in groups)
await whatsapp.deleteMessage({
sessionId: "mysession",
key: {
remoteJid: "120363152682073800@g.us", // group ID with @g.us
fromMe: false,
id: "MESSAGE_ID",
participant: "SENDER_JID" // required for group messages
}
});
// Auto-delete message after delay (helper function example)
function autoDeleteMessage(sessionId, message, delayMs = 3000) {
setTimeout(async () => {
try {
await whatsapp.deleteMessage({
sessionId: sessionId,
key: message.key
});
} catch (error) {
console.error("Error auto-deleting message:", error);
}
}, delayMs);
}
// Send text message with mention (v3.9.8+)
// Mention one user in a group
await whatsapp.sendTextMessageWithMention({
sessionId: "mysession",
to: "6281234567890@g.us", // group JID
text: "Halo @6281234567890, selamat datang di grup!",
mentions: ["6281234567890@s.whatsapp.net"], // JID to mention
isGroup: true
});
// Mention multiple users in a group
await whatsapp.sendTextMessageWithMention({
sessionId: "mysession",
to: "6281234567890@g.us",
text: "Halo @6281234567890 dan @6289876543210, ada yang bisa saya bantu?",
mentions: [
"6281234567890@s.whatsapp.net",
"6289876543210@s.whatsapp.net"
],
isGroup: true
});
// Mention in private chat (less common but supported)
await whatsapp.sendTextMessageWithMention({
sessionId: "mysession",
to: "6281234567890",
text: "Halo @6281234567890, ini adalah pesan pribadi dengan mention",
mentions: ["6281234567890@s.whatsapp.net"]
});
// Alternative: Use sendTextMessage with mentions property
// You can also use the regular sendTextMessage with mentions
const session = whatsapp.getSession("mysession");
if (session) {
await session.sendMessage(
"6281234567890@g.us",
{
text: "Halo @6281234567890, ini pesan dengan mention!",
mentions: ["6281234567890@s.whatsapp.net"]
},
{
quoted: null // or message to quote
}
);
}
`$3
`javascript
// Incoming messages
whatsapp.onMessageReceived((msg) => {
console.log(Message from ${msg.key.remoteJid}:, msg);
});// QR code updates
whatsapp.onQRUpdated(({ sessionId, qr }) => {
console.log(
QR Code for ${sessionId}:, qr);
// You can display this QR in a UI or save it to a file
});// Connection events
whatsapp.onConnected((sessionId) => {
console.log(
Session ${sessionId} connected);
});whatsapp.onDisconnected((sessionId) => {
console.log(
Session ${sessionId} disconnected);
});
`$3
`javascript
whatsapp.onMessageReceived(async (msg) => {
if (msg.message?.imageMessage) {
await msg.saveImage("./saved-image.jpg");
} if (msg.message?.videoMessage) {
await msg.saveVideo("./saved-video.mp4");
}
if (msg.message?.documentMessage) {
await msg.saveDocument("./saved-document"); // extension will be added automatically
}
if (msg.message?.audioMessage) {
await msg.saveAudio("./saved-audio.mp3");
}
});
`$3
The library now implements a hybrid caching system for group metadata using both in-memory (NodeCache) and persistent storage (MongoDB). This significantly improves performance for applications that frequently use group metadata information.
`javascript
// Configure cache settings (optional, has default values)
whatsapp.setGroupCacheConfig({
stdTTL: 10 * 60, // Time-to-live in seconds (10 minutes)
checkperiod: 120 // Check for expired keys every 2 minutes
});// Get group metadata (automatically uses cache if available)
const metadata = await whatsapp.getGroupMetadata(sessionId, groupJid);
console.log(
Group name: ${metadata.subject});
console.log(Participants: ${metadata.participants.length});
console.log(Created on: ${new Date(metadata.creation * 1000).toLocaleString()});// Force fetch fresh data from server and update cache
const freshData = await whatsapp.getGroupMetadata(sessionId, groupJid, true);
// Clear cache for specific group in a specific session
await whatsapp.clearGroupMetadataCache(sessionId, groupJid);
// Clear all group metadata cache for a specific session
await whatsapp.clearSessionGroupMetadataCache(sessionId);
// Clear all cached group metadata for all sessions
whatsapp.clearAllGroupMetadataCache();
`Benefits of the hybrid caching system:
1. Significantly reduces WhatsApp API calls for group metadata
2. Improves response time for group-related features
3. Persistent cache in MongoDB survives application restarts
4. In-memory cache provides ultra-fast access for frequently used groups
5. Automatic cache invalidation on group updates (members, settings, etc.)
6. Full multi-session support - each session has isolated cache for group metadata
7. Automatic cleanup when sessions are deleted or invalidated
#### Multi-Session Caching Architecture
The group metadata cache system is designed to support multiple WhatsApp sessions running simultaneously without any cache collision:
- Each session maintains its own isolated cache for group metadata
- Cache keys combine both session ID and group ID to ensure separation
- MongoDB storage includes session information for persistent separation
- Cache cleanup happens automatically when sessions are deleted or invalidated
- Memory and database efficiency through shared infrastructure
This approach ensures that in multi-session environments:
- Session A and Session B can both cache metadata for the same group ID without conflicts
- Each session gets its own view of its accessible groups
- Cache invalidation in one session doesn't affect other sessions
Utility Functions
`javascript
// Create a delay
import { createDelay } from "wa-multi-mongodb";
await createDelay(2000); // wait 2 seconds// Execute with timeout
import { withTimeout } from "wa-multi-mongodb";
try {
const result = await withTimeout(
functionThatMightTakeTooLong(),
10000, // timeout in ms
"Operation timed out" // error message if timeout occurs
);
} catch (error) {
console.error(error.message);
}
// Attempt to reconnect a session
import { reconnect } from "wa-multi-mongodb";
try {
const reconnected = await reconnect("mysession");
console.log("Reconnect successful:", reconnected);
} catch (error) {
console.error("Reconnect failed:", error);
}
`LID ↔ PN Conversion Utilities (v3.10.4+)
WhatsApp has introduced LID (Linked ID) as a new anonymous identifier format to enhance user privacy. These utility functions help you convert between LID and Phone Number (PN) formats.
$3
| Format | Description | Example |
|--------|-------------|---------|
| LID | Anonymous identifier (new format) |
1524746986546@lid |
| PN/JID | Phone number based identifier (traditional) | 6281234567890@s.whatsapp.net |$3
`javascript
// Get phone number from LID
const result = await whatsapp.getPNForLID("mysession", "1524746986546@lid");
if (result.success && result.pn) {
console.log(Phone number: ${result.pn});
} else {
console.log("Phone number not found:", result.error);
}// Returns: { success: boolean, lid: string, pn: string | null, error?: string }
`$3
`javascript
// Get LID from phone number
const result = await whatsapp.getLIDForPN("mysession", "6281234567890");
if (result.success && result.lid) {
console.log(LID: ${result.lid});
} else {
console.log("LID not found:", result.error);
}// Returns: { success: boolean, pn: string, lid: string | null, error?: string }
`$3
`javascript
// Automatically convert any JID to phone number
const phoneNumber = await whatsapp.toPhoneNumber("mysession", anyJid);
if (phoneNumber) {
console.log(Phone: ${phoneNumber});
}// Automatically convert any JID to LID
const lid = await whatsapp.toLID("mysession", "6281234567890@s.whatsapp.net");
if (lid) {
console.log(
LID: ${lid});
}
`$3
`javascript
// Get all LID-PN mappings for a session
const mappings = await whatsapp.getAllLIDMappings("mysession");
for (const { lid, pn } of mappings) {
console.log(${lid} => ${pn});
}
`$3
`javascript
// Check if JID is in LID format
if (whatsapp.isLIDFormat("1524746986546@lid")) {
console.log("This is an LID");
}// Check if JID is in PN format
if (whatsapp.isPNFormat("6281234567890@s.whatsapp.net")) {
console.log("This is a phone number JID");
}
`$3
> ⚠️ Limitations:
> -
getPNForLID may return null for new contacts or when WhatsApp hasn't provided the LID-PN mapping
> - LID mappings are only available for contacts that have already interacted with your session
> - WhatsApp is increasingly focusing on privacy, so not all LIDs have known phone numbers| Function | Description |
|----------|-------------|
|
getPNForLID(sessionId, lid) | Convert LID to phone number |
| getLIDForPN(sessionId, pn) | Convert phone number to LID |
| toPhoneNumber(sessionId, jid) | Smart convert any JID to PN |
| toLID(sessionId, jid) | Smart convert any JID to LID |
| getAllLIDMappings(sessionId) | Get all known LID-PN mappings |
| isLIDFormat(jid) | Check if JID is in LID format |
| isPNFormat(jid) | Check if JID is in PN format |Complete Example: Auto-Reconnect Application
`javascript
import * as whatsapp from "wa-multi-mongodb";
import { withTimeout } from "wa-multi-mongodb";
require('dotenv').config();// Store connection status
const sessionStatus = {};
// Function to check and reconnect if disconnected
async function checkAndReconnect(sessionId) {
if (sessionStatus[sessionId] === 'disconnected') {
try {
const reconnected = await whatsapp.reconnect(sessionId);
if (reconnected) {
sessionStatus[sessionId] = 'connected';
console.log(
Session ${sessionId} reconnected);
}
} catch (error) {
console.error(Error during reconnect: ${error.message});
}
}
}async function startApp() {
// MongoDB Configuration
await whatsapp.setMongoURI(process.env.MONGODB_URI);
// Event listeners
whatsapp.onQRUpdated(({ sessionId, qr }) => {
console.log(
QR Code for session ${sessionId}:, qr);
});
whatsapp.onConnected((sessionId) => {
console.log(Session ${sessionId} connected!);
sessionStatus[sessionId] = 'connected';
});
whatsapp.onDisconnected((sessionId) => {
console.log(Session ${sessionId} disconnected!);
sessionStatus[sessionId] = 'disconnected';
// Try to reconnect after a few seconds
setTimeout(() => checkAndReconnect(sessionId), 10000);
});
// Message handler with error handling and group detection
whatsapp.onMessageReceived(async (msg) => {
try {
if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
const messageContent = msg.message?.conversation ||
msg.message?.extendedTextMessage?.text ||
"";
// Detect if message is from a group
const isGroup = msg.key.remoteJid.endsWith('@g.us');
// Using group metadata cache (v3.9.4+)
if (isGroup) {
const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid);
console.log(Message from group: ${metadata.subject} with ${metadata.participants.length} members);
}
// Mark message as read
try {
await whatsapp.readMessage({
sessionId: msg.sessionId,
key: msg.key,
});
} catch (error) {
if (error.message.includes('Connection Closed')) {
sessionStatus[msg.sessionId] = 'disconnected';
setTimeout(() => checkAndReconnect(msg.sessionId), 5000);
}
}
// Reply to messages containing "hello"
if (messageContent.toLowerCase().includes("hello")) {
// Show typing indicator (works in both private and group chats since v3.9.1+)
await whatsapp.sendTyping({
sessionId: msg.sessionId,
to: msg.key.remoteJid,
duration: 2000,
});
// Use different timeouts for groups vs private chats
const timeoutMs = isGroup ? 60000 : 30000;
try {
await withTimeout(
whatsapp.sendTextMessage({
sessionId: msg.sessionId,
to: msg.key.remoteJid,
text: "Hello! How can I help you?",
answering: msg,
}),
timeoutMs,
"Message sending timed out"
);
} catch (error) {
console.error("Error sending message:", error.message);
}
}
// Example command to get group info
if (messageContent === "!groupinfo" && isGroup) {
try {
// Force fetch fresh data
const metadata = await whatsapp.getGroupMetadata(msg.sessionId, msg.key.remoteJid, true);
const adminList = metadata.participants
.filter(p => p.admin)
.map(p => p.id.split('@')[0])
.join(", ");
const infoText = Group Info\n +
Name: ${metadata.subject}\n +
Description: ${metadata.desc || 'None'}\n +
Members: ${metadata.participants.length}\n +
Admins: ${adminList}\n +
Created: ${new Date(metadata.creation * 1000).toLocaleString()};
await whatsapp.sendTextMessage({
sessionId: msg.sessionId,
to: msg.key.remoteJid,
text: infoText
});
} catch (error) {
console.error("Error getting group info:", error.message);
}
}
} catch (error) {
// Prevent application crash
console.error("Error processing message:", error.message);
}
});
// Load all sessions from MongoDB
await whatsapp.loadSessionsFromMongo();
// Create a main session if it doesn't exist
const mainSession = "main_session";
const existingSessions = await whatsapp.getAllSession();
if (!existingSessions.includes(mainSession)) {
await whatsapp.startSession(mainSession);
} else {
sessionStatus[mainSession] = 'connected';
}
// Check connections periodically
setInterval(() => {
Object.keys(sessionStatus).forEach(sid => {
checkAndReconnect(sid);
});
}, 5 60 1000); // check every 5 minutes
}startApp().catch(err => {
console.error("Failed to start application:", err);
process.exit(1);
});
`Complete Example: Pairing Code with Auto-Reconnect (v3.9.6+)
`javascript
import * as whatsapp from "wa-multi-mongodb";
require('dotenv').config();// Store connection status
const sessionStatus = {};
async function startPairingApp() {
// MongoDB Configuration
await whatsapp.setMongoURI(process.env.MONGODB_URI);
// Event listeners for pairing code sessions
whatsapp.onConnected((sessionId) => {
console.log(
Pairing session ${sessionId} connected!);
sessionStatus[sessionId] = 'connected';
});
whatsapp.onDisconnected(async (sessionId) => {
console.log(Pairing session ${sessionId} disconnected!);
sessionStatus[sessionId] = 'disconnected';
// Check if it's a pairing code session
const status = await whatsapp.getSessionStatus(sessionId);
if (status.sessionType === 'pairing') {
console.log(Attempting to reconnect pairing session ${sessionId}...);
// Auto-reconnect after 5 seconds
setTimeout(async () => {
try {
const reconnected = await whatsapp.reconnect(sessionId);
if (reconnected) {
console.log(Pairing session ${sessionId} reconnected successfully!);
sessionStatus[sessionId] = 'connected';
}
} catch (error) {
console.error(Failed to reconnect pairing session ${sessionId}:, error);
}
}, 5000);
}
});
// Message handler
whatsapp.onMessageReceived(async (msg) => {
if (msg.key.fromMe || msg.key.remoteJid.includes("status")) return;
const messageContent = msg.message?.conversation ||
msg.message?.extendedTextMessage?.text ||
"";
console.log(Message from ${msg.key.remoteJid}: ${messageContent});
// Auto-reply example
if (messageContent.toLowerCase().includes("ping")) {
await whatsapp.sendTextMessage({
sessionId: msg.sessionId,
to: msg.key.remoteJid,
text: "Pong! Message received from pairing session.",
answering: msg
});
}
});
// Load existing sessions from MongoDB
await whatsapp.loadSessionsFromMongo();
// Start a new pairing code session
const pairingSessionId = "pairing_session_1";
const yourPhoneNumber = "6281234567890"; // Replace with your phone number
try {
await whatsapp.startSessionWithPairingCode(pairingSessionId, yourPhoneNumber, {
onConnected: () => {
console.log("Pairing session connected successfully!");
sessionStatus[pairingSessionId] = 'connected';
},
onDisconnected: () => {
console.log("Pairing session disconnected!");
sessionStatus[pairingSessionId] = 'disconnected';
},
onPairingCode: (code) => {
console.log("\n" + "=".repeat(50));
console.log("📱 PAIRING CODE:", code);
console.log("=".repeat(50));
console.log("1. Open WhatsApp on your phone");
console.log("2. Go to Settings > Linked Devices");
console.log("3. Tap 'Link a Device'");
console.log("4. Tap 'Link with phone number instead'");
console.log("5. Enter the pairing code above");
console.log("=".repeat(50) + "\n");
}
});
sessionStatus[pairingSessionId] = 'connecting';
} catch (error) {
console.error("Error starting pairing session:", error);
}
// Periodic health check for pairing sessions
setInterval(async () => {
const pairingSessions = whatsapp.getPairingCodeSessions();
console.log(Active pairing sessions: ${pairingSessions.length});
// Check each pairing session status
for (const sessionId of pairingSessions) {
const status = await whatsapp.getSessionStatus(sessionId);
console.log(Session ${sessionId}: ${status.connected ? 'Connected' : 'Disconnected'});
if (!status.connected && sessionStatus[sessionId] === 'connected') {
console.log(Detected disconnection for ${sessionId}, attempting reconnect...);
try {
await whatsapp.reconnect(sessionId);
} catch (error) {
console.error(Reconnect failed for ${sessionId}:, error);
}
}
}
}, 30000); // Check every 30 seconds
// Bulk reconnect utility
setInterval(async () => {
try {
await whatsapp.reconnectAllPairingCodeSessions();
console.log("Bulk reconnect completed for all pairing sessions");
} catch (error) {
console.error("Bulk reconnect failed:", error);
}
}, 10 60 1000); // Every 10 minutes
console.log("Pairing code application started!");
}startPairingApp().catch(err => {
console.error("Failed to start pairing application:", err);
process.exit(1);
});
`Frontend Integration Example: QR Code Display (v3.9.6+)
`javascript
// React.js example for QR code display
import React, { useState, useEffect } from 'react';
import QRCode from 'qrcode';
import * as whatsapp from "wa-multi-mongodb";function WhatsAppQRComponent() {
const [qrDataURL, setQrDataURL] = useState('');
const [sessionStatus, setSessionStatus] = useState('disconnected');
useEffect(() => {
// Initialize WhatsApp connection
const initWhatsApp = async () => {
await whatsapp.setMongoURI(process.env.REACT_APP_MONGODB_URI);
// Start session with simplified QR callback
await whatsapp.startSession("frontend_session", {
printQR: false, // Don't print in terminal
onQRUpdated: async (qr) => {
// QR data is raw and ready for frontend use
try {
const qrDataURL = await QRCode.toDataURL(qr);
setQrDataURL(qrDataURL);
} catch (error) {
console.error('Error generating QR code:', error);
}
},
onConnected: () => {
setSessionStatus('connected');
setQrDataURL(''); // Clear QR when connected
},
onDisconnected: () => {
setSessionStatus('disconnected');
}
});
};
initWhatsApp().catch(console.error);
}, []);
return (
WhatsApp Connection
Status: {sessionStatus}
{qrDataURL && (
Scan this QR code with WhatsApp:

)}
{sessionStatus === 'connected' && (
✅ WhatsApp connected successfully!
)}
);
}export default WhatsAppQRComponent;
`Best Practices for Group Chats
1. Auto Group Detection: Since v3.9.0, the library automatically detects if a chat is a group based on its JID format
2. Typing Indicators: Typing indicators now work in both private and group chats (v3.9.1+)
3. Longer Timeouts: Use longer timeouts when sending media to groups (60+ seconds)
4. Handle Errors: Implement retry mechanisms for failed group messages
5. Announcement Channels: Groups with announcement channels may trigger
MessageCounterError (handled automatically in v3.9.1+)
6. Retry Strategy: For announcement channel groups, the library will automatically retry sending messages up to 3 times with increasing delays
7. Group Metadata Caching: Use the hybrid caching system (v3.9.4+) to improve performance when working with groups
8. New sendTextMessageWithMention Function: Comprehensive mention functionality for WhatsApp messages (v3.9.8+)WhatsApp Limitations
1. Media Transfer: Large media files to groups may take longer or timeout
2. Connection Stability: Auto-reconnect may be needed in production apps
3. Announcement Channels: Some groups with announcement channels may still fail after multiple retries
Changelog
$3
- Custom Browser Configuration: Added ability to customize browser type and name for WhatsApp connection
- New browserType option: Choose from "ubuntu" (default), "macOS", "windows", or "appropriate"
- New browserName option: Customize the app name displayed in WhatsApp's "Linked Devices" list
- Works with both startSession() and startSessionWithPairingCode() methods
- Default behavior unchanged (Ubuntu browser with "Chrome" name)
- LID ↔ PN Conversion Utilities: Added comprehensive utilities for converting between LID (Linked ID) and Phone Number formats
- New getPNForLID(sessionId, lid) function to convert LID to phone number
- New getLIDForPN(sessionId, pn) function to convert phone number to LID
- New toPhoneNumber(sessionId, jid) smart conversion function (auto-detects format)
- New toLID(sessionId, jid) smart conversion function (auto-detects format)
- New getAllLIDMappings(sessionId) function to get all known LID-PN mappings
- New isLIDFormat(jid) and isPNFormat(jid) helper functions
- Uses Baileys' internal signalRepository.lidMapping for conversions
$3
- Fixed Group JID Validation: Resolved issue with group chat validation
- Fixed isValidJid() function to properly validate group JIDs without requiring dash (-) character
- Some WhatsApp group IDs don't use dash format, validation now accepts all valid group formats
- Error "Invalid JID format: [group-id]@g.us" has been resolved$3
- Using Baileys New Version (7.x.x): Update & support function with latest baileys version
- Added @lid Format Support: Full support for WhatsApp's new @lid identifier format
- Updated phoneToJid() function to handle both @s.whatsapp.net and @lid formats
- Enhanced all message sending functions with JID validation:
- sendTextMessage()
- sendTextMessageWithMention()
- sendMedia()
- sendVoiceNote()
- sendSticker()
- sendTyping()
- No breaking changes - existing @s.whatsapp.net format continues to work
- Automatic detection and handling of @lid format to prevent 404 errors
- Added comprehensive error handling for invalid JID formats$3
$3
- New sendTextMessageWithMention Function: Comprehensive mention functionality for WhatsApp messages
- Support for mentioning single or multiple users in group chats
- Automatic JID format validation and conversion
- Full retry mechanism with error handling for mention messages
- Support for quoted messages with mentions
- Compatible with both group and private chat mentions
- Enhanced timeout handling for mention messages$3
- Enhanced Message Processing for Group Chats: Fixed issues with group message handling and improved message processing architecture
- Multiple Message Processing: Event handler messages.upsert now processes all messages in array instead of only the first message
- Improved Message Filtering: Added intelligent filtering to skip protocol messages and empty messages while preserving valid group messages
- Enhanced Group Message Support: Better detection and processing of group messages with participant information
- Group vs Private Chat Detection: Better differentiation between group and private messages
- Improved Error Recovery: Better error handling without changing existing error patterns$3
- Enhanced Pairing Code Support: Added comprehensive pairing code session management with auto-reconnect capabilities
- New startSessionWithPairingCode() function for creating sessions using pairing codes
- Intelligent session tracking system that preserves pairing code session data across disconnections
- Enhanced auto-reconnect mechanism that differentiates between QR code and pairing code sessions
- Session persistence in MongoDB for pairing code sessions to enable seamless reconnection
- New Utility Functions for Session Management:
- reconnect(sessionId) - Manual reconnection for any session type
- reconnectAllPairingCodeSessions() - Bulk reconnection for all tracked pairing code sessions
- getPairingCodeSessions() - Get list of all pairing code session IDs
- getSessionStatus(sessionId) - Get detailed session status information including session type
- QR Data Raw for Frontend Integration: Simplified QR handling optimized for frontend development
- Cleaned up QR callback to provide only essential QR data raw for frontend processing
- Removed unnecessary QR string complexity from callbacks for better performance
- QR data can be directly used with any frontend QR code library (React, Vue, Angular, etc.)
- Terminal QR display handled automatically via printQR option
- Breaking Changes:
- Simplified onQRUpdated callback signature: removed qrString parameter, now only provides raw QR data
- Session-level onQRUpdated option simplified from (qr, qrString) to (qr) only
- Enhanced Session Persistence: Pairing code sessions maintain authentication state in MongoDB during disconnections
- Improved Error Handling: Better error recovery and automatic session restoration for pairing code sessions$3
- New deleteMessage() function for deleting messages
- Support for deleting both own messages and others' messages (requires admin permissions in groups)
- Auto-delete message utility function example$3
- Updated baileys dependency to v6.7.18
- Added hybrid caching system for group metadata (NodeCache + MongoDB)
- Improved group operations performance with automatic caching
- New functions for group metadata management:
- getGroupMetadata() - Get metadata with automatic caching
- setGroupCacheConfig() - Configure cache TTL and check periods
- clearGroupMetadataCache() - Clear specific group metadata
- clearAllGroupMetadataCache() - Clear all cached group metadata$3
- Updated QR code implementation for better display in terminal
- Replaced deprecated printQRInTerminal option with qrcode library implementation
- Added support for latest Baileys version$3
- Updated Baileys dependency to v6.7.17 for improved stability and compatibility$3
- Added special handling for MessageCounterError in group chats with announcement channels
- Implemented automatic retry mechanism for messages to announcement channels
- Enhanced error reporting for group chat issues
- Fixed typing indicators to work properly in group chats$3
- Added automatic group chat detection - no need to specify isGroup: true` parameter- GitHub Repository
- Issue Tracker
- Original wa-multi-session
- Baileys Library
- @wahdalo
ISC