@lynovratech/baileys
v1.0.13
Published
A WebSockets library for interacting with WhatsApp Web - lynovra fork with JID-first and dual ESM/CJS support
Readme
Fork by whiskeysockets/baileys — Modified & maintained by lynovratech
🔀 About This Fork
This is @lynovratech/baileys — a fork of the original whiskeysockets/baileys with the following modifications:
- ✅ Dual module support: both ESM (
import) and CJS (require) in one package - ✅ TypeScript compatibility fixes
- ✅ Stays in sync with upstream whiskeysockets/baileys updates
📦 Install
npm install @lynovratech/baileysOr as a drop-in replacement for the original:
npm install baileys@npm:@lynovratech/baileys🔧 Module Support
ESM (import)
import makeWASocket, { useMultiFileAuthState } from '@lynovratech/baileys'CJS (require)
const { default: makeWASocket, useMultiFileAuthState } = require('@lynovratech/baileys')[!CAUTION] NOTICE OF BREAKING CHANGE.
As of 7.0.0, multiple breaking changes were introduced into the library.
Please check out https://whiskey.so/migrate-latest for more information.
Important Note
This is a temporary README.md, the new guide is in development and will this file will be replaced with .github/README.md (already a default on GitHub).
New guide link: https://baileys.wiki
Get Support
If you'd like business to enterprise-level support from Rajeh, the current maintainer of Baileys, you can book a video chat. Book a 1 hour time slot by contacting him on Discord or pre-ordering here. The earlier you pre-order the better, as his time slots usually fill up very quickly. He offers immense value per hour and will answer all your questions before the time runs out.
If you are a business, we encourage you to contribute back to the high development costs of the project and to feed the maintainers who dump tens of hours a week on this. You can do so by booking meetings or sponsoring below. All support, even in bona fide / contribution hours, is welcome by businesses of all sizes. This is not condoning or endorsing businesses to use the library. See the Disclaimer below.
Sponsor
If you'd like to financially support this project, you can do so by supporting the current maintainer here.
Disclaimer
This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or its affiliates. The official WhatsApp website can be found at whatsapp.com. "WhatsApp" as well as related names, marks, emblems and images are registered trademarks of their respective owners.
The maintainers of Baileys do not in any way condone the use of this application in practices that violate the Terms of Service of WhatsApp. The maintainers of this application call upon the personal responsibility of its users to use this application in a fair way, as it is intended to be used. Use at your own discretion. Do not spam people with this. We discourage any stalkerware, bulk or automated messaging usage.
- Baileys does not require Selenium or any other browser to be interface with WhatsApp Web, it does so directly using a WebSocket.
- Not running Selenium or Chromium saves you like half a gig of ram :/
- Baileys supports interacting with the multi-device & web versions of WhatsApp.
- Thank you to @pokearaujo for writing his observations on the workings of WhatsApp Multi-Device. Also, thank you to @Sigalor for writing his observations on the workings of WhatsApp Web and thanks to @Rhymen for the go implementation.
[!IMPORTANT] The original repository had to be removed by the original author - we now continue development in this repository here. This is the only official repository and is maintained by the community. Join the Discord here
Example
Do check out & run example.ts to see an example usage of the library. The script covers most common use cases. To run the example script, download or clone the repo and then type the following in a terminal:
cd path/to/Baileysyarnyarn example
Install
Use the stable version:
npm install @lynovratech/baileysUse the edge version (no guarantee of stability, but latest fixes + features):
npm install github:lynovratech/baileysThen import your code using:
import makeWASocket from '@lynovratech/baileys'Links
Index
- Connecting Account
- Important Notes About Socket Config
- Save Auth Info
- Handling Events
- Implementing a Data Store
- Whatsapp IDs Explain
- Utility Functions
- Sending Messages
- Modify Messages
- Manipulating Media Messages
- Reject Call
- Send States in Chat
- Modifying Chats
- User Querys
- Change Profile
- Groups
- Privacy
- Broadcast Lists & Stories
- Writing Custom Functionality
Connecting Account
WhatsApp provides a multi-device API that allows Baileys to be authenticated as a second WhatsApp client by scanning a QR code or Pairing Code with WhatsApp on your phone.
[!NOTE] Here is a simple example of event handling
[!TIP] You can see all supported socket configs here (Recommended)
Starting socket with QR-CODE
[!TIP] You can customize browser name if you connect with QR-CODE, with
Browserconstant, we have some browsers config, see here
import makeWASocket from '@lynovratech/baileys'
const sock = makeWASocket({
browser: Browsers.ubuntu('My App'),
printQRInTerminal: true
})If the connection is successful, you will see a QR code printed on your terminal screen, scan it with WhatsApp on your phone and you'll be logged in!
Starting socket with Pairing Code
[!IMPORTANT] Pairing Code isn't Mobile API, it's a method to connect Whatsapp Web without QR-CODE, you can connect only with one device, see here
The phone number can't have + or () or -, only numbers, you must provide country code
import makeWASocket from '@lynovratech/baileys'
const sock = makeWASocket({
printQRInTerminal: false
})
if (!sock.authState.creds.registered) {
const number = 'XXXXXXXXXXX'
const code = await sock.requestPairingCode(number)
console.log(code)
}Receive Full History
- Set
syncFullHistoryastrue - Baileys, by default, use chrome browser config
- If you'd like to emulate a desktop connection (and receive more message history), use this browser setting:
const sock = makeWASocket({
...otherOpts,
browser: Browsers.macOS('Desktop'),
syncFullHistory: true
})Important Notes About Socket Config
Caching Group Metadata (Recommended)
If you use baileys for groups, we recommend you to set
cachedGroupMetadatain socket config:const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false}) const sock = makeWASocket({ cachedGroupMetadata: async (jid) => groupCache.get(jid) }) sock.ev.on('groups.update', async ([event]) => { const metadata = await sock.groupMetadata(event.id) groupCache.set(event.id, metadata) }) sock.ev.on('group-participants.update', async (event) => { const metadata = await sock.groupMetadata(event.id) groupCache.set(event.id, metadata) })
Improve Retry System & Decrypt Poll Votes
const sock = makeWASocket({
getMessage: async (key) => await getMessageFromStore(key)
})Receive Notifications in Whatsapp App
const sock = makeWASocket({
markOnlineOnConnect: false
})Saving & Restoring Sessions
import makeWASocket, { useMultiFileAuthState } from '@lynovratech/baileys'
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
const sock = makeWASocket({ auth: state })
sock.ev.on('creds.update', saveCreds)[!IMPORTANT]
useMultiFileAuthStateis a utility function to help save the auth state in a single folder, this function serves as a good guide to help write auth & key states for SQL/no-SQL databases, which I would recommend in any production grade system.
Handling Events
Baileys uses the EventEmitter syntax for events. They're all nicely typed up, so you shouldn't have any issues with an Intellisense editor like VS Code.
[!IMPORTANT] The events are these, it's important you see all events
const sock = makeWASocket()
sock.ev.on('messages.upsert', ({ messages }) => {
console.log('got messages', messages)
})Example to Start
import makeWASocket, { DisconnectReason, useMultiFileAuthState } from '@lynovratech/baileys'
import { Boom } from '@hapi/boom'
async function connectToWhatsApp () {
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
})
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect } = update
if(connection === 'close') {
const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
console.log('connection closed due to ', lastDisconnect.error, ', reconnecting ', shouldReconnect)
if(shouldReconnect) {
connectToWhatsApp()
}
} else if(connection === 'open') {
console.log('opened connection')
}
})
sock.ev.on('messages.upsert', event => {
for (const m of event.messages) {
console.log(JSON.stringify(m, undefined, 2))
console.log('replying to', m.key.remoteJid)
await sock.sendMessage(m.key.remoteJid!, { text: 'Hello Word' })
}
})
sock.ev.on('creds.update', saveCreds)
}
connectToWhatsApp()Decrypt Poll Votes
sock.ev.on('messages.update', event => {
for(const { key, update } of event) {
if(update.pollUpdates) {
const pollCreation = await getMessage(key)
if(pollCreation) {
console.log(
'got poll update, aggregation: ',
getAggregateVotesInPollMessage({
message: pollCreation,
pollUpdates: update.pollUpdates,
})
)
}
}
}
})Summary of Events on First Connection
- When you connect first time,
connection.updatewill be fired requesting you to restart sock - Then, history messages will be received in
messaging.history-set
Implementing a Data Store
import makeWASocket, { makeInMemoryStore } from '@lynovratech/baileys'
const store = makeInMemoryStore({ })
store.readFromFile('./baileys_store.json')
setInterval(() => {
store.writeToFile('./baileys_store.json')
}, 10_000)
const sock = makeWASocket({ })
store.bind(sock.ev)
sock.ev.on('chats.upsert', () => {
console.log('got chats', store.chats.all())
})
sock.ev.on('contacts.upsert', () => {
console.log('got contacts', Object.values(store.contacts))
})Whatsapp IDs Explain
idis the WhatsApp ID, calledjidtoo, of the person or group you're sending the message to.- It must be in the format
[country code][phone number]@s.whatsapp.net- Example for people:
[email protected]. - For groups, it must be in the format
[email protected].
- Example for people:
- For broadcast lists, it's
[timestamp of creation]@broadcast. - For stories, the ID is
status@broadcast.
- It must be in the format
Utility Functions
getContentType, returns the content type for any messagegetDevice, returns the device from messagemakeCacheableSignalKeyStore, make auth store more fastdownloadContentFromMessage, download content from any message
Sending Messages
const jid: string
const content: AnyMessageContent
const options: MiscMessageGenerationOptions
sock.sendMessage(jid, content, options)Non-Media Messages
Text Message
await sock.sendMessage(jid, { text: 'hello word' })Quote Message (works with all types)
await sock.sendMessage(jid, { text: 'hello word' }, { quoted: message })Mention User (works with most types)
await sock.sendMessage(
jid,
{
text: '@12345678901',
mentions: ['[email protected]']
}
)Forward Messages
const msg = getMessageFromStore()
await sock.sendMessage(jid, { forward: msg })Location Message
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221
}
}
)Contact Message
const vcard = 'BEGIN:VCARD\n'
+ 'VERSION:3.0\n'
+ 'FN:Jeff Singh\n'
+ 'ORG:Ashoka Uni;\n'
+ 'TEL;type=CELL;type=VOICE;waid=911234567890:+91 12345 67890\n'
+ 'END:VCARD'
await sock.sendMessage(
id,
{
contacts: {
displayName: 'Jeff',
contacts: [{ vcard }]
}
}
)Reaction Message
await sock.sendMessage(
jid,
{
react: {
text: '💖',
key: message.key
}
}
)Pin Message
| Time | Seconds | |-------|----------------| | 24h | 86.400 | | 7d | 604.800 | | 30d | 2.592.000 |
await sock.sendMessage(
jid,
{
pin: {
type: 1,
time: 86400,
key: message.key
}
}
)Poll Message
await sock.sendMessage(
jid,
{
poll: {
name: 'My Poll',
values: ['Option 1', 'Option 2'],
selectableCount: 1,
toAnnouncementGroup: false
}
}
)Sending Messages with Link Previews
- Add
link-preview-jsas a dependency:npm install link-preview-js - Send a link:
await sock.sendMessage(
jid,
{
text: 'Hi, this was sent using https://github.com/ahcmaddevan/baileys'
}
)Media Messages
Gif Message
await sock.sendMessage(
jid,
{
video: fs.readFileSync('Media/ma_gif.mp4'),
caption: 'hello word',
gifPlayback: true
}
)Video Message
await sock.sendMessage(
id,
{
video: { url: './Media/ma_gif.mp4' },
caption: 'hello word',
ptv: false
}
)Audio Message
await sock.sendMessage(
jid,
{
audio: { url: './Media/audio.mp3' },
mimetype: 'audio/mp4'
}
)Image Message
await sock.sendMessage(
id,
{
image: { url: './Media/ma_img.png' },
caption: 'hello word'
}
)View Once Message
await sock.sendMessage(
id,
{
image: { url: './Media/ma_img.png' },
viewOnce: true,
caption: 'hello word'
}
)Modify Messages
Deleting Messages (for everyone)
const msg = await sock.sendMessage(jid, { text: 'hello word' })
await sock.sendMessage(jid, { delete: msg.key })Editing Messages
await sock.sendMessage(jid, {
text: 'updated text goes here',
edit: response.key,
})Manipulating Media Messages
Downloading Media Messages
import { createWriteStream } from 'fs'
import { downloadMediaMessage, getContentType } from '@lynovratech/baileys'
sock.ev.on('messages.upsert', async ({ messages: [m] }) => {
if (!m.message) return
const messageType = getContentType(m)
if (messageType === 'imageMessage') {
const stream = await downloadMediaMessage(
m,
'stream',
{ },
{
logger,
reuploadRequest: sock.updateMediaMessage
}
)
const writeStream = createWriteStream('./my-download.jpeg')
stream.pipe(writeStream)
}
})Re-upload Media Message to Whatsapp
await sock.updateMediaMessage(msg)Reject Call
await sock.rejectCall(callId, callFrom)Send States in Chat
Reading Messages
const key: WAMessageKey
await sock.readMessages([key])Update Presence
await sock.sendPresenceUpdate('available', jid)Modifying Chats
Archive a Chat
const lastMsgInChat = await getLastMessageInChat(jid)
await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)Mute/Unmute a Chat
| Time | Miliseconds | |-------|-----------------| | Remove | null | | 8h | 86.400.000 | | 7d | 604.800.000 |
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
await sock.chatModify({ mute: null }, jid)Mark a Chat Read/Unread
const lastMsgInChat = await getLastMessageInChat(jid)
await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)Delete a Message for Me
await sock.chatModify(
{
clear: {
messages: [{ id: 'ATWYHDNNWU81732J', fromMe: true, timestamp: '1654823909' }]
}
},
jid
)Delete a Chat
const lastMsgInChat = await getLastMessageInChat(jid)
await sock.chatModify({
delete: true,
lastMessages: [{ key: lastMsgInChat.key, messageTimestamp: lastMsgInChat.messageTimestamp }]
}, jid)Star/Unstar a Message
await sock.chatModify({
star: {
messages: [{ id: 'messageID', fromMe: true }],
star: true
}
}, jid)Disappearing Messages
| Time | Seconds | |-------|----------------| | Remove | 0 | | 24h | 86.400 | | 7d | 604.800 | | 90d | 7.776.000 |
await sock.sendMessage(jid, { disappearingMessagesInChat: WA_DEFAULT_EPHEMERAL })
await sock.sendMessage(jid, { text: 'hello' }, { ephemeralExpiration: WA_DEFAULT_EPHEMERAL })
await sock.sendMessage(jid, { disappearingMessagesInChat: false })User Querys
Check If ID Exists in Whatsapp
const [result] = await sock.onWhatsApp(jid)
if (result.exists) console.log (`${jid} exists on WhatsApp, as jid: ${result.jid}`)Query Chat History (groups too)
const msg = await getOldestMessageInChat(jid)
await sock.fetchMessageHistory(50, msg.key, msg.messageTimestamp)Fetch Status
const status = await sock.fetchStatus(jid)
console.log('status: ' + status)Fetch Profile Picture (groups too)
const ppUrl = await sock.profilePictureUrl(jid)
const ppUrlHigh = await sock.profilePictureUrl(jid, 'image')Fetch Bussines Profile
const profile = await sock.getBusinessProfile(jid)
console.log('business description: ' + profile.description + ', category: ' + profile.category)Fetch Someone's Presence
sock.ev.on('presence.update', console.log)
await sock.presenceSubscribe(jid)Change Profile
Change Profile Status
await sock.updateProfileStatus('Hello World!')Change Profile Name
await sock.updateProfileName('My name')Change Display Picture (groups too)
await sock.updateProfilePicture(jid, { url: './new-profile-picture.jpeg' })Remove display picture (groups too)
await sock.removeProfilePicture(jid)Groups
Create a Group
const group = await sock.groupCreate('My Fab Group', ['[email protected]', '[email protected]'])
console.log('created group with id: ' + group.gid)
await sock.sendMessage(group.id, { text: 'hello there' })Add/Remove or Demote/Promote
await sock.groupParticipantsUpdate(
jid,
['[email protected]', '[email protected]'],
'add' // 'remove' | 'demote' | 'promote'
)Change Subject (name)
await sock.groupUpdateSubject(jid, 'New Subject!')Change Description
await sock.groupUpdateDescription(jid, 'New Description!')Change Settings
await sock.groupSettingUpdate(jid, 'announcement')
await sock.groupSettingUpdate(jid, 'not_announcement')
await sock.groupSettingUpdate(jid, 'unlocked')
await sock.groupSettingUpdate(jid, 'locked')Leave a Group
await sock.groupLeave(jid)Get Invite Code
const code = await sock.groupInviteCode(jid)
console.log('group code: ' + code)Revoke Invite Code
const code = await sock.groupRevokeInvite(jid)
console.log('New group code: ' + code)Join Using Invitation Code
const response = await sock.groupAcceptInvite(code)
console.log('joined to: ' + response)Query Metadata
const metadata = await sock.groupMetadata(jid)
console.log(metadata.id + ', title: ' + metadata.subject + ', description: ' + metadata.desc)Get All Participating Groups Metadata
const response = await sock.groupFetchAllParticipating()
console.log(response)Toggle Ephemeral
await sock.groupToggleEphemeral(jid, 86400)Change Add Mode
await sock.groupMemberAddMode(jid, 'all_member_add') // or 'admin_add'Privacy
Block/Unblock User
await sock.updateBlockStatus(jid, 'block')
await sock.updateBlockStatus(jid, 'unblock')Get Privacy Settings
const privacySettings = await sock.fetchPrivacySettings(true)
console.log('privacy settings: ' + privacySettings)Get BlockList
const response = await sock.fetchBlocklist()
console.log(response)Update LastSeen Privacy
await sock.updateLastSeenPrivacy('all') // 'contacts' | 'contact_blacklist' | 'none'Update Online Privacy
await sock.updateOnlinePrivacy('all') // 'match_last_seen'Update Profile Picture Privacy
await sock.updateProfilePicturePrivacy('all') // 'contacts' | 'contact_blacklist' | 'none'Update Status Privacy
await sock.updateStatusPrivacy('all') // 'contacts' | 'contact_blacklist' | 'none'Update Read Receipts Privacy
await sock.updateReadReceiptsPrivacy('all') // 'none'Update Groups Add Privacy
await sock.updateGroupsAddPrivacy('all') // 'contacts' | 'contact_blacklist'Update Default Disappearing Mode
await sock.updateDefaultDisappearingMode(86400)Broadcast Lists & Stories
Send Broadcast & Stories
await sock.sendMessage(
jid,
{
image: { url: url },
caption: caption
},
{
backgroundColor: backgroundColor,
font: font,
statusJidList: statusJidList,
broadcast: true
}
)Query a Broadcast List's Recipients & Name
const bList = await sock.getBroadcastListInfo('1234@broadcast')
console.log (`list name: ${bList.name}, recps: ${bList.recipients}`)Writing Custom Functionality
Enabling Debug Level in Baileys Logs
const sock = makeWASocket({
logger: P({ level: 'debug' }),
})Register a Callback for Websocket Events
sock.ws.on('CB:edge_routing', (node: BinaryNode) => { })
sock.ws.on('CB:edge_routing,id:abcd', (node: BinaryNode) => { })
sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node: BinaryNode) => { })License
Copyright (c) 2025 Rajeh Taher/WhiskeySockets
Licensed under the MIT License. See LICENSE for full details.
🙏 Credits
- Original author: whiskeysockets/baileys & all contributors
- Fork & modifications: lynovratech
Powered by Lynovra Technology Solutions
