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

heisbroken-baileys

v1.0.0

Published

Baileys-compatible WhatsApp Multi-Device API (from scratch implementation)

Downloads

162

Readme

██████╗ ██████╗ ███╗ ██╗███████╗██████╗ ██╔════╝ ██╔═══██╗████╗ ██║██╔════╝██╔══██╗ ██║ ███╗██║ ██║██╔██╗ ██║█████╗ ██████╔╝ ██║ ██║██║ ██║██║╚██╗██║██╔══╝ ██╔══██╗ ╚██████╔╝╚██████╔╝██║ ╚████║███████╗██║ ██║ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝

LONER — From-scratch WhatsApp Web API Version: 1.0.0 | Package: @loner/baileys | License: MIT | Node: >=18.0.0

A complete WhatsApp Multi-Device API implementation built from the protocol level up. Not a wrapper around Baileys.


📚 Table of Contents


🚀 Quick Start

npm install heisbroken-baileys
# or install directly from GitHub
# npm install loner/baileys
const { makeWASocket, useMultiFileAuthState } = require('@loner/baileys')

async function start() {
  // Baileys-style auth usage
  const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
  const sock = makeWASocket({
    auth: state,
    printQRInTerminal: true,
  })

  sock.ev.on('creds.update', saveCreds)
  sock.ev.on('messages.upsert', ({ messages }) => {
    const msg = messages[0]
    const text = msg.message?.conversation || ''
    console.log(`Received: ${text}`)
    
    if (text === '!ping') {
      sock.sendMessage(msg.key.remoteJid, { text: 'Pong!' })
    }
  })
  
  sock.ev.on('connection.update', ({ connection }) => {
    if (connection === 'open') console.log('✅ Connected!')
  })
  
  await sock.connect()
}

start()

📦 Documenting this on npm

npm automatically shows this README.md on your package page, so keep this file as your main documentation source.

Recommended package metadata

  • description: one-line summary shown in search/listings
  • keywords: helps discovery
  • homepage, repository, bugs: adds links on npm page
  • files: controls what gets published

Publish/update flow

npm login
npm version patch
npm publish --access public

For scoped packages like @loner/baileys, use --access public the first time.


📖 API Reference

makeWASocket(config)

Creates a WhatsApp socket connection. Returns a sock object with all messaging methods.

Parameters:

| Param | Type | Default | Description | |-------|------|---------|-------------| | config.auth | { state, auth } | null | Auth state from useMultiFileAuthState() | | config.authDir | string | './loner_auth' | Directory for auth files | | config.url | string | 'wss://web.whatsapp.com/ws/chat' | WebSocket URL | | config.reconnectInterval | number | 5000 | Reconnect delay (ms) | | config.maxRetries | number | 10 | Max reconnect attempts | | config.logLevel | string | 'info' | Logger level |

Returns: sock object with methods below:


useMultiFileAuthState(authDir)

Creates a multi-file auth state for session persistence.

const { state, saveCreds, auth } = await useMultiFileAuthState('./auth')

Returns:

| Property | Type | Description | |----------|------|-------------| | state.creds | object\|null | Stored credentials (null if new) | | state.keys | object\|null | Stored keys (null if new) | | saveCreds | function | Call to persist credentials | | auth | AuthManager | Auth manager instance |


sock.sendMessage(jid, content, opts)

Send any message type. The content object determines the type.

Text message:

await sock.sendMessage('[email protected]', { text: 'Hello!' })

Text with quoted message:

await sock.sendMessage(jid, { text: 'Reply text' }, { quoted: msg })

Image message:

await sock.sendMessage(jid, { 
  image: 'https://example.com/image.jpg',
  caption: 'Nice pic!'
})

Video message:

await sock.sendMessage(jid, { 
  video: 'https://example.com/video.mp4',
  caption: 'Check this out'
})

Audio message:

await sock.sendMessage(jid, { audio: 'https://example.com/audio.mp3' })

Buttons (Quick Reply)

Send interactive buttons:

await sock.sendMessage(jid, {
  text: 'Choose an option:',
  buttons: [
    { id: 'opt1', text: 'Option 1' },
    { id: 'opt2', text: 'Option 2' },
    { id: 'opt3', text: 'Option 3' },
  ]
})

List Messages

Send a list with sections and rows:

await sock.sendMessage(jid, {
  text: 'Select from the list:',
  sections: [
    {
      title: 'Section 1',
      rows: [
        { id: 'row1', title: 'Row 1', description: 'Description 1' },
        { id: 'row2', title: 'Row 2', description: 'Description 2' },
      ]
    },
    {
      title: 'Section 2', 
      rows: [
        { id: 'row3', title: 'Row 3' },
      ]
    }
  ],
  buttonText: 'View Options'
})

Poll Messages

Send a poll:

await sock.sendMessage(jid, {
  poll: {
    name: 'What is your favorite language?',
    options: ['JavaScript', 'Python', 'Go', 'Rust']
  }
})

Location Messages

Send a location:

await sock.sendMessage(jid, {
  location: {
    latitude: 6.5244,
    longitude: 3.3792,
    name: 'Lagos, Nigeria'
  }
})

Contact Messages

Send a contact (vCard):

await sock.sendMessage(jid, {
  contacts: [{ name: 'John Doe', phone: '2348012345678' }]
})

sock.sendReaction(jid, messageId, emoji)

React to a message:

await sock.sendReaction(jid, 'MESSAGE_ID', '👍')

sock.editMessage(jid, messageId, newText)

Edit a sent message:

await sock.editMessage(jid, 'MESSAGE_ID', 'Edited text')

sock.deleteMessage(jid, messageId)

Delete a message for everyone:

await sock.deleteMessage(jid, 'MESSAGE_ID')

sock.readMessages([msgKey])

Mark messages as read:

await sock.readMessages([{ remoteJid: jid, id: 'MSG_ID' }])

sock.sendPresenceUpdate(type, jid)

Update presence:

sock.sendPresenceUpdate('available')              // Online
sock.sendPresenceUpdate('unavailable')             // Offline
sock.sendPresenceUpdate('composing', jid)          // Typing
sock.sendPresenceUpdate('recording', jid)          // Recording voice

👥 Group Operations

// Create a group
await sock.groupCreate('Group Name', ['[email protected]'])

// Get group metadata
await sock.groupMetadata(jid)

// Update subject/description
await sock.groupUpdateSubject(jid, 'New Name')
await sock.groupUpdateDescription(jid, 'Description')

// Manage participants
await sock.groupParticipantsUpdate(jid, ['[email protected]'], 'add')
await sock.groupParticipantsUpdate(jid, ['[email protected]'], 'remove')
await sock.groupParticipantsUpdate(jid, ['[email protected]'], 'promote')
await sock.groupParticipantsUpdate(jid, ['[email protected]'], 'demote')

// Invite codes
await sock.groupGetInviteCode(jid)
await sock.groupRevokeInviteCode(jid)
await sock.groupAcceptInvite('CODE')

// Settings
await sock.groupSettingUpdate(jid, 'announcement')  // Only admins can send
await sock.groupSettingUpdate(jid, 'restrict')        // Only admins can edit info
await sock.groupToggleEphemeral(jid, 86400)           // Disappearing messages

👤 Contact Operations

// Block/unblock
await sock.block('[email protected]')
await sock.unblock('[email protected]')

// Profile
await sock.updateProfilePicture(jid, url)
await sock.removeProfilePicture(jid)
await sock.updateProfileStatus('My status')

// Business profile
await sock.updateBusinessProfile({ description, website, email })

🔗 Pairing

Phone Number Pairing

const result = await sock.requestPairingCode('2348012345678')
console.log('Code:', result.code)
// User enters this code in WhatsApp > Link a Device > Link Using Phone Number

QR Code

The QR data is emitted via the qr event:

sock.ev.on('qr', (qrData) => {
  console.log('Scan this QR:', qrData)
  // Display QR code in terminal or web
})

📡 Events

sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {})
sock.ev.on('messages.upsert', ({ messages, type }) => {})
sock.ev.on('presence.update', (node) => {})
sock.ev.on('receipt', (node) => {})
sock.ev.on('notification', (node) => {})
sock.ev.on('stream.error', (node) => {})
sock.ev.on('group.update', (node) => {})
sock.ev.on('picture.change', (node) => {})
sock.ev.on('status.update', (node) => {})
sock.ev.on('qr', (qrData) => {})
sock.ev.on('challenge', (data) => {})
sock.ev.on('iq_result', (node) => {})

connection.update Event

| Property | Type | Description | |----------|------|-------------| | connection | string | 'connecting', 'open', 'close' | | lastDisconnect.error | Error | The error that caused disconnect | | lastDisconnect.date | Date | When the disconnect happened |

messages.upsert Event

| Property | Type | Description | |----------|------|-------------| | messages | Array | Array of message objects | | messages[].key | object | { remoteJid, fromMe, id, participant } | | messages[].message | object | Message content (conversation, imageMessage, etc.) | | messages[].messageType | string | Type of message | | messages[].messageTimestamp | number | Unix timestamp | | type | string | Upsert type ('notify', etc.) |


📋 Message Types

const { WAMessageType } = require('@loner/baileys')

WAMessageType.text       // 'text'
WAMessageType.image      // 'image'
WAMessageType.video      // 'video'
WAMessageType.audio      // 'audio'
WAMessageType.document   // 'document'
WAMessageType.sticker    // 'sticker'
WAMessageType.poll       // 'poll'
WAMessageType.location   // 'location'
WAMessageType.contact    // 'contact'
WAMessageType.reaction   // 'reaction'
WAMessageType.list       // 'list'
WAMessageType.buttons    // 'buttons'
WAMessageType.liveLocation // 'live_location'

🔌 Disconnect Reasons

const { DisconnectReason } = require('@loner/baileys')

DisconnectReason.connectionClosed      // 'connectionClosed'
DisconnectReason.connectionLost        // 'connectionLost'
DisconnectReason.connectionReplaced    // 'connectionReplaced'
DisconnectReason.timedOut              // 'timedOut'
DisconnectReason.loggedOut             // 'loggedOut'
DisconnectReason.badSession            // 'badSession'
DisconnectReason.restartRequired       // 'restartRequired'

🧩 Feature Modules

Access advanced managers directly for full control:

const sock = makeWASocket()

// Group manager
sock.groupManager.getMetadata(jid)
sock.groupManager.create('Name', [participants])
sock.groupManager.setSubject(jid, 'New Name')
sock.groupManager.setDescription(jid, 'Desc')
sock.groupManager.setAnnouncement(jid, true)
sock.groupManager.setDisappearingMessages(jid, 86400)

// Contact manager
sock.contactManager.block(jid)
sock.contactManager.setStatus('My status')
sock.contactManager.setProfilePicture(jid, url)
sock.contactManager.getBusinessProfile(jid)

// Presence manager
sock.presenceManager.online()
sock.presenceManager.offline()
sock.presenceManager.typing(jid)
sock.presenceManager.recording(jid)

// Receipt manager
sock.receiptManager.read(jid, [messageIds])
sock.receiptManager.react(jid, messageId, '👍')
sock.receiptManager.editMessage(jid, messageId, 'new text')
sock.receiptManager.deleteForEveryone(jid, messageId)

// Media manager
sock.mediaManager.encryptMedia(data, 'image')
sock.mediaManager.downloadFromUrl(url)

// Newsletter manager
sock.newsletterManager.getNewsletterInfo(jid)
sock.newsletterManager.subscribe(jid)
sock.newsletterManager.unsubscribe(jid)

// Story manager
sock.storyManager.postText('Status update')
sock.storyManager.postImage(url, { caption: 'Nice' })
sock.storyManager.postVideo(url)

// Chat operations
sock.chatManager.mute(jid, 86400)
sock.chatManager.archive(jid)
sock.chatManager.pin(jid)
sock.chatManager.markUnread(jid)

// Label manager
sock.labelManager.getAll()
sock.labelManager.create('VIP', 3)
sock.labelManager.addToChat(labelId, jid)

// Business manager
sock.businessManager.getCatalog(jid)
sock.businessManager.getProduct(productId, jid)
sock.businessManager.updateProfile({ description, website })

// Device manager
sock.deviceManager.getDevices()
sock.deviceManager.removeDevice(deviceId)

// App state manager
sock.appStateManager.sync(['regular', 'regular_low'])
sock.appStateManager.patch([{ collection: 'regular', value: {} }])

// Multi-device pairing
sock.multiDeviceManager.requestPairingCode('2348012345678')

// History sync
sock.historySync.requestSync()
sock.historySync.getChats()

🏗 Architecture

loner/
├── index.js              # Public API — makeWASocket(), useMultiFileAuthState()
├── src/
│   ├── binary/           # WhatsApp binary protocol (encoder, decoder, tokens)
│   ├── crypto/           # X25519 ECDH, AES-256-CBC, HMAC-SHA256, HKDF
│   ├── socket/           # WebSocket connection manager + keep-alive
│   ├── auth/             # QR login, phone pairing, credential persistence
│   ├── messages/         # Message builders, location, receipts
│   ├── groups/           # Group management (create, manage, settings)
│   ├── contacts/         # Block, profile, business, privacy
│   ├── presence/         # Online/typing/recording indicators
│   ├── media/            # Encrypted media upload/download
│   ├── newsletter/       # Channels/newsletter support
│   ├── stories/          # Status posts & privacy
│   ├── chat/             # Mute, archive, pin, clear
│   ├── labels/           # Create, manage, assign labels
│   ├── business/         # Catalog, products, collections
│   ├── device/           # List/remove linked devices
│   ├── appstate/         # App state sync
│   └── sync/             # History sync

🧪 Testing

npm test

Tests cover: binary protocol round-trip, crypto operations, message builders, auth manager, full API surface.


📄 License

MIT — built from scratch, not a fork. Use freely.