easy-connect-wpp
v1.3.8
Published
Unofficial WhatsApp Client for Node.js powered by Baileys. Build scalable, event-driven WhatsApp integrations with full message support and automated reconnection.
Maintainers
Readme
easy-connect-wpp
Unofficial WhatsApp Client for Node.js powered by Baileys. Build scalable, event-driven WhatsApp integrations with full message support and automated reconnection.
⚠️ Disclaimer
This is an unofficial WhatsApp client library. It is not affiliated with WhatsApp Inc. or Meta Platforms. Use at your own risk and ensure compliance with WhatsApp's Terms of Service.
Features
✨ Unofficial WhatsApp Client — Reverse-engineered Baileys library
🚀 Automatic Initialization — Quick setup with QR code or pairing code
🎧 Event-Driven Architecture — Familiar callback pattern for all events
📨 Full Message Support — Text, images, videos, audio, documents, location, contacts, reactions
✅ Type-Safe — Full TypeScript support with comprehensive type definitions
🔄 Auto-Reconnect — Automatic reconnection with exponential backoff
👥 Group Management — Create, update, and manage WhatsApp groups
📊 Session Management — Persistent session storage and restoration
🛡️ License Validation — Built-in license verification system
Installation
npm install easy-connect-wppPrerequisites
- Node.js 18+
- Valid WhatsApp Account (with verified phone number)
- Modern Browser (for QR code scanning)
Quick Start
import { SessionManager } from 'easy-connect-wpp';
import { Session } from 'easy-connect-wpp/models/session';
// 1. Create session
const session: Session = {
session: 'my_session',
phoneNumber: '5511999999999',
licensePath: './license.json',
syncFullHistory: false,
pairingCode: false, // set to true for pairing code authentication
qrCode: true,
qrPrintTerminal: true,
};
const manager = new SessionManager();
// 2. Register listeners
manager.onQrCode((qrCode) => {
console.log('Scan QR code:', qrCode);
});
manager.onPairingCode((code) => {
console.log('Pairing code:', code);
});
manager.onMessage(async (message) => {
console.log(`Message from ${message.from}: ${message.content.conversation}`);
});
manager.onConnectionStatus((status) => {
console.log(`Connection status: ${status}`);
});
// 3. Create session
await manager.createSession(session);API Reference
SessionManager Constructor
const manager = new SessionManager();Session Configuration
interface Session {
session: string; // Unique session identifier
phoneNumber: string; // WhatsApp phone number (with country code)
licensePath: string; // Path to license.json file
syncFullHistory?: boolean; // Sync full chat history (default: false)
pairingCode?: boolean; // Use pairing code instead of QR (default: false)
qrCode?: boolean; // Enable QR code (default: true)
qrPrintTerminal?: boolean; // Print QR in terminal (default: false)
maxRetries?: number; // Max reconnection attempts (default: 10)
version?: [number, number, number]; // WA version override (optional)
}Methods
createSession(session: Session): Promise<void>
Initialize and connect WhatsApp session.
await manager.createSession(session);Sending Messages
sendText(identifier: string, message: string): Promise<Response>
Send a text message.
const phone = '5511999999999';
const message = 'Hello!';
const response = await manager.sendText(phone, message);
if (response.status === 200) {
console.log('Message sent:', response.id);
}sendTextEdit(identifier: string, message: string, messageId: string): Promise<Response>
Edit a previously sent text message.
const phone = '5511999999999';
const message = 'Hello (edited)';
const messageId = '3AF91FDF7463FFB0CFCA';
const response = await manager.sendTextEdit(phone, message, messageId);
if (response.status === 200) {
console.log('Message edited:', response.id);
}sendTextReply(identifier: string, message: string, options: Option): Promise<Response>
Send a reply to a specific message.
const phone = '5511999999999';
const message = 'Thanks!';
const options = {
content: JSON.stringify({
id: 'original_message_id',
fromMe: false,
remoteJid: '[email protected]',
content: originalMessageContent,
}),
};
const response = await manager.sendTextReply(phone, message, options);
if (response.status === 200) {
console.log('Reply sent:', response.id);
}sendTextStatus(identifiers: string[], message: string, backgroundColor?: string): Promise<Response>
Send a text status to multiple contacts.
const phones = ['5511999999999', '5511988888888'];
const message = 'My status!';
const backgroundColor = '#25D366';
const response = await manager.sendTextStatus(phones, message, backgroundColor);
if (response.status === 200) {
console.log('Status sent');
}sendImage(identifier: string, content: string, option: ImageOption): Promise<Response>
Send an image with optional caption.
const phone = '5511999999999';
const content = 'https://example.com/image.jpg';
const option = { caption: 'Check this out!' };
const response = await manager.sendImage(phone, content, option);
if (response.status === 200) {
console.log('Image sent:', response.id);
}sendVideo(identifier: string, content: string, option: VideoOption): Promise<Response>
Send a video with optional caption.
const phone = '5511999999999';
const content = 'https://example.com/video.mp4';
const option = { caption: 'My video', ptv: false };
const response = await manager.sendVideo(phone, content, option);
if (response.status === 200) {
console.log('Video sent:', response.id);
}sendAudio(identifier: string, content: string, option?: AudioOption): Promise<Response>
Send an audio file.
const phone = '5511999999999';
const content = 'https://example.com/audio.mp3';
const option = { mimetype: 'audio/mpeg' };
const response = await manager.sendAudio(phone, content, option);
if (response.status === 200) {
console.log('Audio sent:', response.id);
}sendVoice(identifier: string, content: string, option?: AudioOption): Promise<Response>
Send a voice message.
const phone = '5511999999999';
const content = 'https://example.com/voice.ogg';
const response = await manager.sendVoice(phone, content);
if (response.status === 200) {
console.log('Voice sent:', response.id);
}sendDocument(identifier: string, content: string, option: FileOption): Promise<Response>
Send a document with optional filename.
const phone = '5511999999999';
const content = 'https://example.com/document.pdf';
const option = { filename: 'Report.pdf', caption: 'Here is your report' };
const response = await manager.sendDocument(phone, content, option);
if (response.status === 200) {
console.log('Document sent:', response.id);
}sendLocation(identifier: string, latitude: number, longitude: number): Promise<Response>
Send a location.
const phone = '5511999999999';
const latitude = -23.5505;
const longitude = -46.6333;
const response = await manager.sendLocation(phone, latitude, longitude);
if (response.status === 200) {
console.log('Location sent:', response.id);
}sendContact(identifier: string, contactName: string, contactPhone: string, contactPhotoUrl?: string): Promise<Response>
Send a contact card.
const phone = '5511999999999';
const contactName = 'John Doe';
const contactPhone = '5511988888888';
const contactPhotoUrl = null;
const response = await manager.sendContact(phone, contactName, contactPhone, contactPhotoUrl);
if (response.status === 200) {
console.log('Contact sent:', response.id);
}sendForward(identifier: string, options: Option): Promise<Response>
Forward a message.
const phone = '5511999999999';
const options = {
content: JSON.stringify({
id: 'original_message_id',
fromMe: false,
remoteJid: '[email protected]',
content: messageContent,
}),
};
const response = await manager.sendForward(phone, options);
if (response.status === 200) {
console.log('Message forwarded:', response.id);
}sendReaction(identifier: string, reaction: string, messageId: string): Promise<Response>
Send a reaction emoji to a message.
const phone = '5511999999999';
const reaction = '👍';
const messageId = '3AF91FDF7463FFB0CFCA';
const response = await manager.sendReaction(phone, reaction, messageId);
if (response.status === 200) {
console.log('Reaction sent:', response.id);
}deleteMessageForEveryone(identifier: string, messageId: string): Promise<Response>
Delete a message for everyone.
const phone = '5511999999999';
const messageId = '3AF91FDF7463FFB0CFCA';
const response = await manager.deleteMessageForEveryone(phone, messageId);
if (response.status === 200) {
console.log('Message deleted for everyone');
}deleteMessageForMe(identifier: string, messageId: string): Promise<Response>
Delete a message only for you.
const phone = '5511999999999';
const messageId = '3AF91FDF7463FFB0CFCA';
const response = await manager.deleteMessageForMe(phone, messageId);
if (response.status === 200) {
console.log('Message deleted for you');
}markReadAll(identifier: string): Promise<Response>
Mark all messages in a chat as read.
const phone = '5511999999999';
const response = await manager.markReadAll(phone);
if (response.status === 200) {
console.log('All messages marked as read');
}setPresence(identifier: string, type: 'unavailable' | 'available' | 'composing' | 'recording' | 'paused'): Promise<Response>
Set presence status (typing indicator).
const phone = '5511999999999';
const type = 'composing';
const response = await manager.setPresence(phone, type);
if (response.status === 200) {
console.log('Presence updated');
}Group Management
groupCreate(name: string, description: string, type?: 'group' | 'community'): Promise<Response>
Create a group or community.
const name = 'My Group';
const description = 'Group description';
const type = 'group';
const result = await manager.groupCreate(name, description, type);
if (result.status === 200) {
console.log('Group created:', result.content.id);
}groupUpdate(identifier: string, name: string, description: string, type?: 'group' | 'community'): Promise<Response>
Update group name and description.
const groupId = 'group_id_here';
const name = 'New Name';
const description = 'New Description';
const response = await manager.groupUpdate(groupId, name, description, 'group');
if (response.status === 200) {
console.log('Group updated');
}groupUpdateSettings(identifier: string, type: 'group' | 'community', setting: 'announcement' | 'not_announcement' | 'locked' | 'unlocked'): Promise<Response>
Update group settings.
const groupId = 'group_id_here';
const type = 'group';
const setting = 'announcement';
const response = await manager.groupUpdateSettings(groupId, type, setting);
if (response.status === 200) {
console.log('Settings updated');
}groupParticipantAdd(identifier: string, participant: string): Promise<Response>
Add a participant to a group.
const groupId = 'group_id_here';
const participant = '5511999999999';
const response = await manager.groupParticipantAdd(groupId, participant);
if (response.status === 200) {
console.log('Participant added');
}groupParticipantRemove(identifier: string, participant: string): Promise<Response>
Remove a participant from a group.
const groupId = 'group_id_here';
const participant = '5511999999999';
const response = await manager.groupParticipantRemove(groupId, participant);
if (response.status === 200) {
console.log('Participant removed');
}getGroupMetadata(identifier: string): Promise<Response>
Get group information.
const groupId = 'group_id_here';
const response = await manager.getGroupMetadata(groupId);
if (response.status === 200) {
const metadata = response.content;
console.log('Group name:', metadata.subject);
}getGroupInviteCode(identifier: string): Promise<Response>
Get group invite code and link.
const groupId = 'group_id_here';
const response = await manager.getGroupInviteCode(groupId);
if (response.status === 200) {
const { code, url } = response.content;
console.log('Invite link:', url);
}Media Management
downloadMedia(options: Option): Promise<Response>
Download media from WhatsApp (returns buffer).
const options = { content: JSON.stringify(messageObject) };
const response = await manager.downloadMedia(options);
if (response.status === 200) {
const buffer = response.content;
console.log('Media downloaded:', buffer.length, 'bytes');
}downloadMediaAndSave(options: Option, directory: string): Promise<Response>
Download media and save to file.
const options = { content: JSON.stringify(messageObject) };
const directory = './downloads/media.jpg';
const response = await manager.downloadMediaAndSave(options, directory);
if (response.status === 200) {
console.log('Media saved to:', directory);
}Profile Management
getPicture(identifier: string): Promise<Response>
Get profile picture URL.
const phone = '5511999999999';
const response = await manager.getPicture(phone);
if (response.status === 200) {
const picUrl = response.content;
console.log('Profile picture:', picUrl);
}updateProfilePicture(identifier: string, content: string): Promise<Response>
Update profile picture from URL, buffer, or stream.
const phone = '5511999999999';
const content = 'https://example.com/profile.jpg';
const response = await manager.updateProfilePicture(phone, content);
if (response.status === 200) {
console.log('Profile picture updated');
}removeProfilePicture(identifier: string): Promise<Response>
Remove profile picture.
const phone = '5511999999999';
const response = await manager.removeProfilePicture(phone);
if (response.status === 200) {
console.log('Profile picture removed');
}onWhatsApp(identifier: string): Promise<Response>
Check if a phone number is registered on WhatsApp.
const phone = '5511999999999';
const response = await manager.onWhatsApp(phone);
if (response.exists) {
console.log('Number is on WhatsApp');
} else {
console.log('Number not found on WhatsApp');
}Event Listeners
onMessage(callback: (message: EventResponse) => void): void
Listen for incoming messages.
manager.onMessage((message) => {
console.log(`Type: ${message.type}`);
console.log(`From: ${message.from}`);
console.log(`IsGroup: ${message.isgroup}`);
if (message.type === 'conversation') {
console.log(`Text: ${message.content.conversation}`);
} else if (message.type === 'imageMessage') {
console.log(`Image caption: ${message.content.imageMessage?.caption}`);
}
});onMessageAck(callback: (ack: any) => void): void
Listen for message acknowledgments.
manager.onMessageAck((ack) => {
// Status: PENDING (1), SERVER_ACK (2), DELIVERY_ACK (3), READ (4), PLAYED (5)
console.log(`Message ${ack.id}: ${ack.status}`);
});onMessageUpdate(callback: (message: any) => void): void
Listen for message updates.
manager.onMessageUpdate((message) => {
console.log('Message updated:', message);
});onConnectionStatus(callback: (status: ConnectionState) => void): void
Listen for connection changes.
manager.onConnectionStatus((status) => {
console.log(`Connection: ${status}`);
// ConnectionState: NOT_LOGGED, CONNECTING, CONNECTED, DISCONNECTED
});onQrCode(callback: (qr: string) => void): void
Listen for QR code updates.
manager.onQrCode((qr) => {
console.log('New QR code generated');
// Display in UI
});onPairingCode(callback: (code: string) => void): void
Listen for pairing code updates.
manager.onPairingCode((code) => {
console.log(`Pairing code: ${code}`);
});onChatsUpsert(callback: (chats: any) => void): void
Listen for chat updates.
manager.onChatsUpsert((chats) => {
console.log('Chats updated:', chats);
});onContactsUpsert(callback: (contacts: any) => void): void
Listen for contact updates.
manager.onContactsUpsert((contacts) => {
console.log('Contacts updated:', contacts);
});onGroupsUpsert(callback: (groups: any) => void): void
Listen for group updates.
manager.onGroupsUpsert((groups) => {
console.log('Groups updated:', groups);
});onGroupParticipantsUpdate(callback: (event: any) => void): void
Listen for group participant changes.
manager.onGroupParticipantsUpdate((event) => {
console.log(`${event.action}: ${event.participants}`);
});onBlocklistUpdate(callback: (event: any) => void): void
Listen for blocklist changes.
manager.onBlocklistUpdate((event) => {
console.log('Blocklist updated:', event);
});onCall(callback: (calls: any) => void): void
Listen for incoming calls.
manager.onCall((calls) => {
console.log('Call received:', calls);
});Complete Example
import { SessionManager } from 'easy-connect-wpp';
import { Session } from 'easy-connect-wpp/models/session';
async function main() {
const session: Session = {
session: 'my_session',
phoneNumber: '5511999999999',
licensePath: './license.json',
qrCode: true,
qrPrintTerminal: true,
};
const manager = new SessionManager();
// Handle messages
manager.onMessage(async (message) => {
if (message.type === 'conversation') {
console.log(`📨 ${message.from}: ${message.content.conversation}`);
// Reply
await manager.sendText(message.from, 'Thanks! 👋');
} else if (message.type === 'imageMessage') {
console.log(`📸 Image received from ${message.from}`);
// Send reaction
await manager.sendReaction(message.from, '👍', message.id);
}
});
// Handle acknowledgments
manager.onMessageAck((ack) => {
console.log(`✔️ Message ${ack.id}: ${ack.status}`);
});
// Handle QR code
manager.onQrCode((qr) => {
console.log('📱 Scan QR code to login');
// Display in UI or use terminal
});
// Connection status
manager.onConnectionStatus((status) => {
console.log(`🔌 ${status}`);
});
// Graceful shutdown
process.on('SIGINT', async () => {
console.log('\n👋 Closing...');
await manager.logout();
process.exit(0);
});
// Create session and connect
await manager.createSession(session);
console.log('🚀 Running...');
}
main().catch(console.error);Authentication Methods
QR Code (Recommended)
const session: Session = {
session: 'my_session',
phoneNumber: '5511999999999',
licensePath: './license.json',
qrCode: true,
qrPrintTerminal: true,
pairingCode: false,
};
manager.onQrCode((qr) => {
// Display QR in UI or mobile app
});
await manager.createSession(session);Pairing Code
const session: Session = {
session: 'my_session',
phoneNumber: '5511999999999',
licensePath: './license.json',
pairingCode: true,
qrCode: false,
};
manager.onPairingCode((code) => {
console.log(`Enter code in WhatsApp: ${code}`);
});
await manager.createSession(session);License
This library requires a valid license file. Place your license.json in the specified path.
licensePath: './license.json';Error Handling
All methods return a Response object:
const response = await manager.sendText('5511999999999', 'Hello');
if (response.status === 200) {
console.log('Success:', response.content);
} else {
console.error('Error:', response.message);
}Common Error Codes
- 400 — Bad request or invalid parameters
- 401 — Unauthorized (invalid license)
- 404 — Phone not found on WhatsApp
- 500 — Internal server error
Best Practices
- Session Management — Create one manager per phone number
- Error Handling — Always check response.status
- Rate Limiting — Avoid sending too many messages in short time
- Graceful Shutdown — Call logout() before exit
- Event Processing — Keep listeners fast, use queues for heavy work
- License Validation — Ensure license.json is valid and accessible
- Connection Monitoring — Listen to onConnectionStatus events
Troubleshooting
QR Code Not Appearing
- Ensure
qrCode: truein session config - Check terminal output or UI integration
- Verify browser environment for QR display
Session Not Persisting
- Check
tokens/instance-${phoneNumber}/directory exists - Verify write permissions
- Ensure session name is consistent
Messages Not Sending
- Validate recipient phone number format
- Check connection status before sending
- Verify license is valid
Reconnection Issues
- Check network connectivity
- Review max retries setting
- Monitor onConnectionStatus events
Performance Tips
- Reuse instances — One SessionManager per phone number
- Batch messages — Send multiple messages efficiently
- Monitor events — Use onConnectionStatus to detect disconnections
- Cache metadata — Store group/contact info locally
- Clean shutdown — Proper logout frees resources
Disclaimer
This library is not affiliated with WhatsApp Inc. or Meta Platforms. It's a reverse-engineered implementation based on Baileys. Users are responsible for compliance with WhatsApp's Terms of Service. Use at your own risk.
Related Projects
- Baileys — The underlying protocol implementation
- easy-connect-official-wpp-rc — Official WhatsApp Cloud API client
License
ISC
Support
For issues and questions:
- Check existing GitHub issues
- Review example usage in repository
- Consult the logging system for debugging
