npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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.

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.

npm version TypeScript Node.js License

⚠️ 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-wpp

Prerequisites

  • 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

  1. Session Management — Create one manager per phone number
  2. Error Handling — Always check response.status
  3. Rate Limiting — Avoid sending too many messages in short time
  4. Graceful Shutdown — Call logout() before exit
  5. Event Processing — Keep listeners fast, use queues for heavy work
  6. License Validation — Ensure license.json is valid and accessible
  7. Connection Monitoring — Listen to onConnectionStatus events

Troubleshooting

QR Code Not Appearing

  • Ensure qrCode: true in 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

  1. Reuse instances — One SessionManager per phone number
  2. Batch messages — Send multiple messages efficiently
  3. Monitor events — Use onConnectionStatus to detect disconnections
  4. Cache metadata — Store group/contact info locally
  5. 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

License

ISC

Support

For issues and questions:

  • Check existing GitHub issues
  • Review example usage in repository
  • Consult the logging system for debugging