@ms-nicky/baileys
WhatsApp API library using WebSocket technology (multi-device).
Fork of WhiskeySockets/Baileys with:
- Pairing code fixes (canonical browser label, server response wait, 515 auto-reconnect)
- Auto version detection from WPPConnect
- Built-in VoIP calling (WebRTC / baileys-caller)
Installation
npm install github:ms-nicky/baileys
Or in package.json:
"@whiskeysockets/baileys": "github:ms-nicky/baileys"
Quick Start
Pairing Code (Recommended)
const { default: makeWASocket, useMultiFileAuthState, fetchLatestWaWebVersion, makeCacheableSignalKeyStore } = require('@ms-nicky/baileys')
const pino = require('pino')
async function start() {
const { version } = await fetchLatestWaWebVersion()
const { state, saveCreds } = await useMultiFileAuthState('auth_info')
const sock = makeWASocket({
version,
auth: {
creds: state.creds,
keys: makeCacheableSignalKeyStore(state.keys, pino({ level: 'silent' })),
},
printQRInTerminal: false,
browser: ['Linux', 'Chrome', ''],
})
sock.ev.on('creds.update', saveCreds)
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
if (connection === 'open') console.log('✓ Connected')
if (connection === 'close') {
const code = lastDisconnect?.error?.output?.statusCode
if (code === 515) start()
else if (code !== 401) setTimeout(start, 5000)
}
})
const code = await sock.requestPairingCode('62812xxxxxxx')
console.log(`Pairing code: ${code}`)
}
start()
Using the included pair script
node pair.js 62812xxxxxxx
node pair.js 62812xxxxxxx ELAINA13
Auto-reconnects after pairing is accepted (handles 515 stream error).
Key Features
Auto Version Detection
Fetches latest WA version from WPPConnect, falls back to hardcoded.
const { version, isLatest } = await fetchLatestWaWebVersion()
Pairing Code
- Validates international format (rejects leading
0)
- Waits for Noise handshake + server response (
query with 30s timeout)
- Custom pairing code support (exactly 8 chars)
- Canonical browser/OS label (WhatsApp rejects non-standard labels)
- Raw binary nonce (not hex string)
- Auto-reconnect on 515
const code = await sock.requestPairingCode('62812xxxxxxx')
const code = await sock.requestPairingCode('62812xxxxxxx', 'MYCODE13')
405 Error Recovery
Automatically detects 405 Method Not Allowed and retries the connection.
VoIP / Voice Calling
Built-in WebRTC voice calling using the official WhatsApp WASM stack.
Powered by baileys-caller.
Usage
const { createVoipClient, CallState } = require('@ms-nicky/baileys')
const client = await createVoipClient({ authDir: 'auth_info' })
const call = await client.call('62812xxxxxxx', { durationMs: 60000 })
call.on('ringing', () => console.log('• ringing'))
call.on('connected', () => console.log('✓ connected'))
call.on('ended', (reason) => console.log('• ended:', reason))
call.mute(true)
call.end()
call.waitForEnd()
client.disconnect()
Test Script
node call-test.js
node call-test.js 62812xxxxxxx
CALL_DURATION=60000 node call-test.js
CallState
CallState.Idle
CallState.Calling
CallState.PreacceptReceived
CallState.ReceivedCall
CallState.AcceptSent
CallState.AcceptReceived
CallState.Active
CallState.ActiveElsewhere
CallState.Ending
SendMessage
Text
await sock.sendMessage(jid, { text: 'Hello World' })
Image
await sock.sendMessage(jid, { image: { url: 'https://example.com/image.jpg' }, caption: 'Caption' })
Video
await sock.sendMessage(jid, { video: { url: 'https://example.com/video.mp4' }, caption: 'Caption' })
Audio
await sock.sendMessage(jid, { audio: { url: 'https://example.com/audio.mp3' }, mimetype: 'audio/mp4', ptt: true })
Document
await sock.sendMessage(jid, { document: fs.readFileSync('./file.pdf'), mimetype: 'application/pdf', fileName: 'file.pdf' })
Sticker
await sock.sendMessage(jid, { sticker: { url: 'https://example.com/image.webp' } })
Location
await sock.sendMessage(jid, { location: { degreesLatitude: -6.2, degreesLongitude: 106.8 } })
Contact
await sock.sendMessage(jid, { contacts: { displayName: 'Alice', contacts: [{ vcard: 'BEGIN:VCARD\nVERSION:3.0\nFN:Alice\nEND:VCARD' }] } })
Poll
await sock.sendMessage(jid, {
poll: {
name: 'Pilihan',
values: ['A', 'B', 'C'],
selectableCount: 1
}
})
List
await sock.sendMessage(jid, {
list: {
title: 'Menu',
text: 'Pilih opsi:',
buttonText: 'Lihat',
sections: [{
title: 'Section',
rows: [{ title: 'Option 1', description: 'Desc', rowId: 'opt1' }]
}]
}
})
Buttons
await sock.sendMessage(jid, {
buttons: [
{ buttonId: 'btn1', buttonText: { displayText: 'Button 1' }, type: 1 }
],
header: 'Header',
text: 'Text',
footer: 'Footer'
})
Additional Features
Album Message (Multiple Images)
await sock.sendMessage(jid, {
albumMessage: [
{ image: fs.readFileSync('./img1.jpg'), caption: 'Photo 1' },
{ image: { url: 'https://example.com/img.jpg' }, caption: 'Photo 2' }
]
})
Interactive Message
await sock.sendMessage(jid, {
interactiveMessage: {
header: 'Header',
title: 'Title',
footer: 'Footer',
buttons: [{
name: 'cta_copy',
buttonParamsJson: JSON.stringify({ display_text: 'Copy Code', id: '123', copy_code: 'ABC123' })
}]
}
})
Native Flow Message
await sock.sendMessage(jid, {
interactiveMessage: {
header: 'Header',
title: 'Title',
footer: 'Footer',
nativeFlowMessage: {
messageParamsJson: JSON.stringify({ bottom_sheet: { in_thread_buttons_limit: 2, list_title: 'Menu', button_title: 'Pilih' } }),
buttons: [{
name: 'single_select',
buttonParamsJson: JSON.stringify({ title: 'Pilih Opsi', sections: [{ title: 'Section', rows: [{ title: 'Option 1', id: 'opt1' }] }] })
}]
}
}
})
Event Message
await sock.sendMessage(jid, {
eventMessage: {
isCanceled: false,
name: 'Event Name',
description: 'Description',
location: { degreesLatitude: 0, degreesLongitude: 0, name: 'Location' },
startTime: String(Math.floor(Date.now() / 1000)),
endTime: String(Math.floor(Date.now() / 1000) + 3600)
}
})
Poll Result Message
await sock.sendMessage(jid, {
pollResultMessage: {
name: 'Poll Name',
pollVotes: [
{ optionName: 'A', optionVoteCount: '10' },
{ optionName: 'B', optionVoteCount: '5' }
]
}
})
Product Message
await sock.sendMessage(jid, {
productMessage: {
title: 'Product',
description: 'Description',
thumbnail: { url: 'https://example.com/img.jpg' },
productId: 'PROD001',
retailerId: 'RETAIL001',
priceAmount1000: 50000,
currencyCode: 'IDR',
buttons: [{ name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: 'Buy Now', url: 'https://example.com/buy' }) }]
}
})
Request Payment Message
await sock.sendMessage(jid, {
requestPaymentMessage: {
currency: 'IDR',
amount: 100000,
from: m.sender,
background: { id: '100', fileLength: '0', width: 1000, height: 1000, mimetype: 'image/webp', placeholderArgb: 0xFF00FFFF, textArgb: 0xFFFFFFFF, subtextArgb: 0xFFAA00FF }
}
})
Status Mention
await sock.sendStatusMention('Hello', jid)
Group Functions
const group = await sock.groupCreate('Group Name', [participant1, participant2])
await sock.groupUpdateSubject(jid, 'New Subject')
await sock.groupUpdateDescription(jid, 'New Description')
await sock.groupParticipantsUpdate(jid, [participant1], 'add')
await sock.groupParticipantsUpdate(jid, [participant1], 'remove')
await sock.groupParticipantsUpdate(jid, [participant1], 'promote')
await sock.groupParticipantsUpdate(jid, [participant1], 'demote')
await sock.groupLeave(jid)
const code = await sock.groupInviteCode(jid)
await sock.groupRevokeInviteCode(jid)
await sock.groupSettingUpdate(jid, 'announcement')
await sock.groupSettingUpdate(jid, 'locked')
await sock.groupToggleEphemeral(jid, 86400)
await sock.setLabelGroup(jid, 'label')
Newsletter
const info = await sock.newsletterFromUrl('https://whatsapp.com/channel/...')
console.log(info)
Utility Functions
const result = await sock.checkWhatsApp(jid)
await sock.updateBlockStatus(jid, 'block')
await sock.updateBlockStatus(jid, 'unblock')
await sock.updateProfileStatus('New status')
await sock.updateProfileName('New Name')
await sock.updateProfilePicture(jid, { url: 'https://example.com/photo.jpg' })
await sock.removeProfilePicture(jid)
const profile = await sock.getBusinessProfile(jid)
Events
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
if (connection === 'open') console.log('Connected')
if (connection === 'close') {
}
})
sock.ev.on('messages.upsert', ({ messages, type }) => {
})
sock.ev.on('presence.update', ({ id, presences }) => {
})
sock.ev.on('groups.update', (groups) => {
})
sock.ev.on('creds.update', saveCreds)
Contact
License
MIT