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