A professionally enhanced, feature-rich version of the Baileys WhatsApp Web API. Built for developers requiring robust WhatsApp automation with modern tooling and comprehensive documentation.
Maintainer: π±π‘_ππ₯π’π§ππ¨π§ [Dev]
- π Modern & Fast β Built with TypeScript and latest technologies
- π§ Enhanced Stability β Improved connection handling and error recovery
- π± Multi-Device Support β Full support for WhatsApp's multi-device protocol
- π End-to-End Encryption β Secure communication using Signal Protocol
- π¨ All Message Types β Support for text, media, documents, contacts, locations, polls, and more
- π₯ Advanced Group Management β Comprehensive group controls and utilities, including group status support
- πΎ Flexible Authentication β Multiple auth state storage options
- π οΈ Developer Friendly β Clean API, extensive examples, and detailed documentation
Choose the installation method that best fits your workflow:
Use npm aliasing to replace the original package with this enhanced version:
// In your package.json
"dependencies": {
"@whiskeysockets/baileys": "github:xhclintohn/Baileys.git"
}// In your package.json
"dependencies": {
"@whiskeysockets/baileys": "npm:@xh_clinton/baileys-mod@latest"
}Then run npm install.
Note: This will make your imports of @whiskeysockets/baileys resolve to this enhanced package.
npm install @xh_clinton/baileys-modInstall the latest development version directly from the source repository:
# Install main branch
npm install https://github.com/xhclintohn/Baileys.gitFor contributing or local testing, install from a local directory:
# Clone the repository first
git clone https://github.com/xhclintohn/Baileys.git
cd your-project
# Install as local dependency
npm install /path/to/cloned/Baileysyarn add @xh_clinton/baileys-mod
# or from GitHub
yarn add https://github.com/xhclintohn/Baileys.gitClick to expand code
const { makeWASocket, useMultiFileAuthState, DisconnectReason } = require('@whiskeysockets/baileys');
const { Boom } = require('@hapi/boom');
async function connectToWhatsApp() {
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys');
const sock = makeWASocket({
auth: state,
printQRInTerminal: true,
browser: ["Ubuntu", "Chrome", "125"],
logger: console, // Optional: Enable detailed logging
});
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update;
if (connection === 'close') {
const shouldReconnect = (lastDisconnect?.error)?.output?.statusCode !== DisconnectReason.loggedOut;
console.log('Connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect);
if (shouldReconnect) {
connectToWhatsApp();
}
} else if (connection === 'open') {
console.log('β
Successfully connected to WhatsApp!');
// Send a welcome message to yourself
const selfJid = sock.user.id;
sock.sendMessage(selfJid, { text: 'Hello! I am online using @xh_clinton/baileys-mod π€' });
}
});
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const m of messages) {
if (!m.message) continue;
console.log('π± New message received:', JSON.stringify(m, undefined, 2));
// Example: Auto-reply to messages
if (m.message.conversation) {
await sock.sendMessage(m.key.remoteJid, {
text: `You said: "${m.message.conversation}"`
});
}
}
});
sock.ev.on('creds.update', saveCreds);
}
connectToWhatsApp().catch(console.error);Click to expand code
const { makeWASocket } = require('@whiskeysockets/baileys');
const sock = makeWASocket({ printQRInTerminal: false });
// Request a pairing code for a phone number
if (!sock.authState.creds.registered) {
const phoneNumber = '1234567890'; // Include country code, no symbols
const pairingCode = await sock.requestPairingCode(phoneNumber);
console.log('π Your Pairing Code:', pairingCode);
// For custom pairing codes (must be 8 characters):
// const customPairingCode = await sock.requestPairingCode(phoneNumber, 'MYCODE123');
}Click to expand code
const { makeWASocket, Browsers } = require('@whiskeysockets/baileys');
// Pre-defined browser configurations
const sock = makeWASocket({
browser: Browsers.ubuntu('MyApp'), // Ubuntu/Chrome
// browser: Browsers.macOS('MyApp'), // macOS/Safari
// browser: Browsers.windows('MyApp'), // Windows/Edge
printQRInTerminal: true,
syncFullHistory: true, // Receive full chat history
});Click to expand code
const NodeCache = require('node-cache');
const groupCache = new NodeCache({ stdTTL: 300, useClones: false });
const sock = makeWASocket({
// Cache group metadata for better performance
cachedGroupMetadata: async (jid) => groupCache.get(jid),
// Custom message store retrieval
getMessage: async (key) => {
// Implement your own message store logic here
return await yourDatabase.getMessage(key);
},
// Disable online presence to receive notifications in mobile app
markOnlineOnConnect: false,
// Connection timeouts
connectTimeoutMs: 60000,
defaultQueryTimeoutMs: 60000,
});
// Update cache when groups change
sock.ev.on('groups.update', async ([event]) => {
const metadata = await sock.groupMetadata(event.id);
groupCache.set(event.id, metadata);
});Click to expand code
const { makeWASocket, useMultiFileAuthState } = require('@whiskeysockets/baileys');
async function connect() {
const { state, saveCreds } = await useMultiFileAuthState('auth_info_directory');
const sock = makeWASocket({ auth: state });
sock.ev.on('creds.update', saveCreds);
}Click to expand code
const { makeWASocket, makeCacheableSignalKeyStore } = require('@whiskeysockets/baileys');
// Example with custom database storage
const myAuthState = {
creds: await yourDatabase.getAuthCreds(),
keys: makeCacheableSignalKeyStore(
await yourDatabase.getSignalKeys(),
console.log // Optional logger
)
};
const sock = makeWASocket({ auth: myAuthState });
// Update your database when credentials change
sock.ev.on('creds.update', async (creds) => {
await yourDatabase.saveAuthCreds(creds);
});Click to expand code
// Text message
await sock.sendMessage(jid, { text: 'Hello World!' });
// Text with mentions
await sock.sendMessage(jid, {
text: 'Hello @12345678901!',
mentions: ['12345678901@s.whatsapp.net']
});
// Reply to a message
await sock.sendMessage(jid, { text: 'This is a reply!' }, { quoted: originalMessage });
// Forward a message
await sock.sendMessage(jid, { forward: messageToForward });Click to expand code
// Image with caption
await sock.sendMessage(jid, {
image: { url: './path/to/image.jpg' }, // Can also use Buffer or stream
caption: 'Check out this image!',
mimetype: 'image/jpeg'
});
// Video
await sock.sendMessage(jid, {
video: { url: './path/to/video.mp4' },
caption: 'Watch this video',
gifPlayback: true // For GIF-like playback
});
// Audio/voice note
await sock.sendMessage(jid, {
audio: { url: './path/to/audio.ogg' },
mimetype: 'audio/ogg; codecs=opus',
ptt: true // For voice note
});
// Document
await sock.sendMessage(jid, {
document: { url: './path/to/document.pdf' },
fileName: 'ImportantDocument.pdf',
mimetype: 'application/pdf'
});Click to expand code
// Location
await sock.sendMessage(jid, {
location: {
degreesLatitude: 40.7128,
degreesLongitude: -74.0060,
name: 'New York City'
}
});
// Contact card
const vcard = `BEGIN:VCARD
VERSION:3.0
FN:John Doe
ORG:Example Corp;
TEL;type=CELL;type=VOICE;waid=1234567890:+1 234 567 890
EMAIL:john@example.com
END:VCARD`;
await sock.sendMessage(jid, {
contacts: {
displayName: 'John Doe',
contacts: [{ vcard }]
}
});
// Poll
await sock.sendMessage(jid, {
poll: {
name: 'Favorite Programming Language?',
values: ['JavaScript', 'Python', 'TypeScript', 'Go', 'Rust'],
selectableCount: 1
}
});
// Reaction
await sock.sendMessage(jid, {
react: {
text: 'π', // Empty string to remove reaction
key: targetMessage.key
}
});Click to expand code
// Archive/unarchive chat
await sock.chatModify({ archive: true }, jid);
await sock.chatModify({ archive: false }, jid);
// Mute/unmute chat (8 hours example)
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid);
await sock.chatModify({ mute: null }, jid);
// Pin/unpin chat
await sock.chatModify({ pin: true }, jid);
await sock.chatModify({ pin: false }, jid);
// Mark as read/unread
await sock.chatModify({ markRead: true }, jid);
await sock.chatModify({ markRead: false }, jid);
// Delete chat
await sock.chatModify({ delete: true }, jid);Click to expand code
// Delete message for everyone
const sentMsg = await sock.sendMessage(jid, { text: 'This will be deleted' });
await sock.sendMessage(jid, { delete: sentMsg.key });
// Edit message
const response = await sock.sendMessage(jid, { text: 'Original text' });
await sock.sendMessage(jid, {
text: 'Updated text!',
edit: response.key
});
// Read messages
await sock.readMessages([messageKey1, messageKey2]);
// Download media from message
const { downloadMediaMessage } = require('@whiskeysockets/baileys');
const fs = require('fs');
sock.ev.on('messages.upsert', async ({ messages }) => {
const m = messages[0];
if (m.message?.imageMessage) {
const stream = await downloadMediaMessage(
m, 'stream', {}, { logger: console }
);
const file = fs.createWriteStream('./download.jpg');
stream.pipe(file);
}
});Click to expand code
// Create group
const group = await sock.groupCreate('My New Group', [
'12345678901@s.whatsapp.net',
'09876543210@s.whatsapp.net'
]);
// Add/remove participants
await sock.groupParticipantsUpdate(
groupJid,
['12345678901@s.whatsapp.net'],
'add' // 'remove', 'promote', or 'demote'
);
// Update group info
await sock.groupUpdateSubject(groupJid, 'New Group Name');
await sock.groupUpdateDescription(groupJid, 'New group description');
// Group settings
await sock.groupSettingUpdate(groupJid, 'announcement'); // Only admins can send
await sock.groupSettingUpdate(groupJid, 'not_announcement'); // Everyone can send
await sock.groupSettingUpdate(groupJid, 'locked'); // Only admins can change settings
await sock.groupSettingUpdate(groupJid, 'unlocked'); // Everyone can change settings
// Invite links
const inviteCode = await sock.groupInviteCode(groupJid);
const inviteLink = `https://chat.whatsapp.com/${inviteCode}`;
// Join group via invite
const groupJid = await sock.groupAcceptInvite('INVITECODEHERE');
// Get group metadata
const metadata = await sock.groupMetadata(groupJid);
console.log(`Group: ${metadata.subject}, Participants: ${metadata.participants.length}`);
// Leave group
await sock.groupLeave(groupJid);Click to expand code
module.exports = {
name: 'gstatus',
aliases: ['groupstatus', 'gs'],
description: 'Posts a group status with text, image, video, or audio.',
run: async (context) => {
const { client, m, prefix, isBotAdmin, IsGroup, botname } = context;
const formatMsg = (text) => `βββββββββββββββββ\n${text}\nβββββββββββββββββ`;
try {
if (!botname) {
return client.sendText(m.chat, formatMsg(`Bot name is not set. Please configure it before using this command.`), m);
}
if (!m.sender || typeof m.sender !== 'string' || !m.sender.includes('@s.whatsapp.net')) {
return client.sendText(m.chat, formatMsg(`Could not identify your WhatsApp ID. Please try again.`), m);
}
if (!IsGroup) {
return client.sendText(m.chat, formatMsg(`This command can only be used in group chats.`), m);
}
if (!isBotAdmin) {
return client.sendText(m.chat, formatMsg(`I need to be *admin* to post a group status. Please make me admin first.`), m);
}
const settings = await getSettings();
if (!settings) {
return client.sendText(m.chat, formatMsg(`Failed to load settings. Please try again later.`), m);
}
const quoted = m.quoted ? m.quoted : m;
const mime = (quoted.msg || quoted).mimetype || '';
const caption = m.body
.replace(new RegExp(`^${prefix}(gstatus|groupstatus|gs)\\s*`, 'i'), '')
.trim();
if (!/image|video|audio/.test(mime) && !caption) {
return client.sendText(
m.chat,
formatMsg(`Please reply to an image, video, audio, or include text with the command.\nExample: ${prefix}gstatus Check out this update!`),
m
);
}
const defaultCaption = `Group status Posted By Toxic-MDβ
\n\nJOIN\nhttps://chat.whatsapp.com/GoXKLVJgTAAC3556FXkfFI?mode=wwt`;
if (/image/.test(mime)) {
const buffer = await client.downloadMediaMessage(quoted);
await client.sendMessage(m.chat, {
groupStatusMessage: {
image: buffer,
caption: caption || defaultCaption
}
});
await client.sendText(m.chat, formatMsg(`Image status has been posted successfully β
`), m);
} else if (/video/.test(mime)) {
const buffer = await client.downloadMediaMessage(quoted);
await client.sendMessage(m.chat, {
groupStatusMessage: {
video: buffer,
caption: caption || defaultCaption
}
});
await client.sendText(m.chat, formatMsg(`Video status has been posted successfully β
`), m);
} else if (/audio/.test(mime)) {
const buffer = await client.downloadMediaMessage(quoted);
await client.sendMessage(m.chat, {
groupStatusMessage: {
audio: buffer,
mimetype: 'audio/mp4'
}
});
await client.sendText(m.chat, formatMsg(`Audio status has been posted successfully β
`), m);
} else if (caption) {
await client.sendMessage(m.chat, {
groupStatusMessage: { text: caption }
});
await client.sendText(m.chat, formatMsg(`Text status has been posted successfully β
`), m);
}
} catch (error) {
await client.sendText(
m.chat,
formatMsg(`An error occurred while posting status:\n${error.message}`),
m
);
}
}
};Click to expand code
// Check if user exists on WhatsApp
const [result] = await sock.onWhatsApp('12345678901@s.whatsapp.net');
if (result.exists) {
console.log(`User exists with JID: ${result.jid}`);
}
// Get profile picture
const ppUrl = await sock.profilePictureUrl('12345678901@s.whatsapp.net');
const ppUrlHighRes = await sock.profilePictureUrl('12345678901@s.whatsapp.net', 'image');
// Get user status
const status = await sock.fetchStatus('12345678901@s.whatsapp.net');
// Subscribe to presence updates
sock.ev.on('presence.update', ({ id, presences }) => {
console.log(`${id} presence:`, presences);
});
await sock.presenceSubscribe('12345678901@s.whatsapp.net');
// Business profile
const businessProfile = await sock.getBusinessProfile('12345678901@s.whatsapp.net');Click to expand code
// Update your own profile
await sock.updateProfileName('Your New Name');
await sock.updateProfileStatus('Online and coding! π');
// Update profile picture
await sock.updateProfilePicture(
'12345678901@s.whatsapp.net',
fs.readFileSync('./new-avatar.jpg')
);
// Remove profile picture
await sock.removeProfilePicture('12345678901@s.whatsapp.net');Click to expand code
// Update various privacy settings
await sock.updateLastSeenPrivacy('contacts'); // 'all', 'contacts', 'contact_blacklist', 'none'
await sock.updateOnlinePrivacy('match_last_seen'); // 'all', 'match_last_seen'
await sock.updateProfilePicturePrivacy('contacts');
await sock.updateStatusPrivacy('contacts');
await sock.updateReadReceiptsPrivacy('all'); // 'all', 'none'
await sock.updateGroupsAddPrivacy('contacts');
// Get current privacy settings
const privacySettings = await sock.fetchPrivacySettings(true);Click to expand code
// Block/unblock user
await sock.updateBlockStatus(jid, 'block');
await sock.updateBlockStatus(jid, 'unblock');
// Get blocklist
const blocklist = await sock.fetchBlocklist();Click to expand code
const { makeInMemoryStore } = require('@whiskeysockets/baileys');
const store = makeInMemoryStore({ logger: console });
// Read from/write to file
store.readFromFile('./baileys_store.json');
setInterval(() => {
store.writeToFile('./baileys_store.json');
}, 10_000);
const sock = makeWASocket({ });
store.bind(sock.ev);
// Use store data
sock.ev.on('chats.upsert', () => {
console.log('Chats in store:', store.chats.all());
});Click to expand code
// Implement your own store using databases like MongoDB, PostgreSQL, etc.
class MyCustomStore {
async saveMessage(key, message) {
await yourDatabase.messages.insertOne({ key, message });
}
async loadMessage(key) {
return await yourDatabase.messages.findOne({ key });
}
// Implement other store methods...
}
const myStore = new MyCustomStore();Click to expand code
const {
getContentType,
areJidsSameUser,
isJidGroup,
isJidBroadcast,
isJidStatusBroadcast,
jidNormalizedUser,
generateMessageID,
generateWAMessageContent,
downloadContentFromMessage,
getAggregateVotesInPollMessage,
proto
} = require('@whiskeysockets/baileys');
// Message type detection
const messageType = getContentType(message);
// JID validation
if (isJidGroup(jid)) {
console.log('This is a group JID');
}
// Download content
const stream = await downloadContentFromMessage(message.imageMessage, 'image');Click to expand code
// Enable debug logging
const sock = makeWASocket({
logger: console, // Simple logging
// logger: P({ level: 'debug' }), // Detailed logging with pino
});
// Custom WebSocket event handling
sock.ws.on('CB:edge_routing', (node) => {
console.log('Edge routing event:', node);
});- Cache Group Metadata: Always cache group metadata to reduce API calls
- Implement Proper Store: Use databases instead of in-memory stores for production
- Handle Reconnections: Implement robust reconnection logic
- Rate Limiting: Respect WhatsApp's rate limits to avoid bans
- Error Handling: Wrap socket calls in try-catch blocks
- Never Hardcode Credentials: Use environment variables
- Secure Auth Storage: Encrypt authentication data in databases
- Input Validation: Validate all inputs before processing
- Regular Updates: Keep the package updated for security fixes
Click to expand code
// Auto-reconnect pattern
async function connectWithRetry(maxRetries = 5) {
for (let i = 0; i < maxRetries; i++) {
try {
await connectToWhatsApp();
break;
} catch (error) {
console.log(`Connection attempt ${i + 1} failed:`, error.message);
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
}
// Message processing queue
class MessageQueue {
constructor(sock) {
this.sock = sock;
this.queue = [];
this.processing = false;
}
async add(message) {
this.queue.push(message);
if (!this.processing) this.process();
}
async process() {
this.processing = true;
while (this.queue.length > 0) {
const message = this.queue.shift();
try {
await this.sock.sendMessage(message.jid, message.content);
await new Promise(resolve => setTimeout(resolve, 1000)); // Rate limiting
} catch (error) {
console.error('Failed to send message:', error);
}
}
this.processing = false;
}
}Disclaimer: This project is NOT affiliated with, authorized, maintained, sponsored, or endorsed by WhatsApp LLC or any of its affiliates or subsidiaries.
The official WhatsApp website can be found at https://whatsapp.com. "WhatsApp" as well as related names, marks, emblems, and images are registered trademarks of their respective owners.
- This library is meant for legitimate automation purposes only
- Do NOT use for spamming, bulk messaging, or harassment
- Respect WhatsApp's rate limits and terms of service
- Users are solely responsible for how they use this tool
- The maintainer assumes NO liability for misuse or damages
- Obtain Consent: Only message users who have explicitly consented
- Respect Privacy: Do not collect or misuse personal data
- Limit Frequency: Avoid excessive messaging that could be considered spam
- Provide Value: Ensure your automation provides genuine utility
- Monitor Usage: Regularly audit your usage patterns
- Documentation: First, check this README and the official Baileys documentation
- GitHub Issues: For bug reports and feature requests, please use the GitHub Issues page
- Contact Directly: For urgent matters or specific questions, reach out via WhatsApp: +254735342808
- Community: Consider joining relevant developer communities for broader support
Response Time: The developer typically responds within 24-48 hours on business days.
Distributed under the MIT License. See the LICENSE file in the repository for more information.
This project is based on the excellent work of:
- Baileys by WhiskeySockets
- Signal Protocol implementations
- Various open-source contributors
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (git checkout -b feature/AmazingFeature)
- Commit your changes (git commit -m 'Add some AmazingFeature')
- Push to the branch (git push origin feature/AmazingFeature)
- Open a Pull Request
π Crafted with β€οΈ by π±π‘_ππ₯π’π§ππ¨π§ [Dev]
Empowering developers with powerful WhatsApp automation tools
If this project helped you, consider starring the repository! β