@chatunity/baileys
v1.1.2
Published
whatsapp api by ChatUnity
Maintainers
Readme
ChatUnity Baileys - TypeScript & Node.js Based
Important Note
This library was created by combining multiple libraries together. We thank @realvare for the library and frequent updates ❤️
Responsibility and License Information
The developers of Baileys and its maintainers cannot be held responsible for misuse of the application, as indicated in the MIT License.
The team does not approve any use that violates WhatsApp's Terms of Service. Every user is invited to act responsibly and use the tool only for its intended purposes.
- Baileys does not require Selenium or any browser to work with WhatsApp Web: it uses a WebSocket directly.
- Avoiding Selenium or Chromium saves approximately half a gigabyte of RAM.
- Baileys supports both the multi-device version and the web version of WhatsApp.
[!IMPORTANT]
The original repository was removed by the main author – development continues officially in this new community-maintained version.
Getting Started
You can check out and run the example available in example.ts to see practical usage of the library.
The script demonstrates the most common use cases.
To run it:
cd path/to/Baileysyarnyarn example
Installation
Use the stable version:
yarn add @chatunitycenter/baileysUse the edge version (no guarantee of stability, but latest fixes + features)
yarn add github:chatunitycenter/baileysThen import in your code using:
import makeWASocket from '@chatunitycenter/baileys'Connecting Account
WhatsApp provides a multi-device system that allows Baileys to authenticate as a second WhatsApp client via QR code or Pairing Code scanned from the app on your phone.
[!NOTE] Here you'll find a simple event handling example
[!TIP] You can view all supported socket configurations here (Recommended)
Connect with QR-CODE
[!TIP] If you connect via QR-CODE, you can customize the browser name using the
Browserconstant. Several predefined configurations are available, viewable here.
import makeWASocket from '@chatunitycenter/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!
Connect with Pairing Code
[!IMPORTANT] Pairing Code is not Mobile API; it's a method to connect WhatsApp Web without QR-CODE. You can only connect with one device, see here
The phone number cannot have +, (), or -, only numbers. You must provide country code.
import makeWASocket from '@chatunitycenter/baileys'
const chatunity = makeWASocket({
printQRInTerminal: false // must be false
})
if (!chatunity.authState.creds.registered) {
const number = 'XXXXXXXXXXX'
const code = await chatunity.requestPairingCode(number)
console.log(code)
}Receive Full History
- Set
syncFullHistorytotrue - Use a desktop browser configuration to receive more message history:
const chatunity = makeWASocket({
browser: Browsers.macOS('Desktop'),
syncFullHistory: true
})Socket Configuration
Cache Group Metadata
If you use Baileys for groups, we recommend setting cachedGroupMetadata in socket config:
const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false})
const chatunity = makeWASocket({
cachedGroupMetadata: async (jid) => groupCache.get(jid)
})
chatunity.ev.on('groups.update', async ([event]) => {
const metadata = await chatunity.groupMetadata(event.id)
groupCache.set(event.id, metadata)
})
chatunity.ev.on('group-participants.update', async (event) => {
const metadata = await chatunity.groupMetadata(event.id)
groupCache.set(event.id, metadata)
})Improve Retry System & Decrypt Poll Votes
To improve message sending, retrying on errors, and decrypt poll votes, set up a store with getMessage config:
const chatunity = makeWASocket({
getMessage: async (key) => await getMessageFromStore(key)
})Receive Notifications in WhatsApp App
To receive notifications in the WhatsApp app, set markOnlineOnConnect to false:
const chatunity = makeWASocket({
markOnlineOnConnect: false
})Saving & Restoring Sessions
You don't need to scan the QR code every time you connect. Load credentials to log back in:
import makeWASocket, { useMultiFileAuthState } from '@chatunitycenter/baileys'
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
const chatunity = makeWASocket({ auth: state })
chatunity.ev.on('creds.update', saveCreds)[!IMPORTANT]
useMultiFileAuthStateis a utility function to help save the auth state in a folder. This serves as a good guide for implementing auth & key states for SQL/NoSQL databases, which is recommended for production systems.
[!NOTE] When messages are received/sent, auth keys need updating. You must save updated keys. The
useMultiFileAuthStatefunction handles this automatically, but for other implementations you must be careful with key state management.
Alternative Auth Methods
import makeWASocket, { useSingleFileAuthState, useMongoFileAuthState } from '@chatunitycenter/baileys'
// Single File Auth
const { state, saveState } = await useSingleFileAuthState('./auth_info_baileys.json')
const chatunity = makeWASocket({ auth: state, printQRInTerminal: true })
chatunity.ev.on('creds.update', saveState)
// MongoDB Auth
import { MongoClient } from "mongodb"
const connectAuth = async() => {
const client = new MongoClient('mongoURL')
await client.connect()
const collection = client.db("@itchatunitychann").collection("sessions")
return collection
}
const Authentication = await connectAuth()
const { state, saveCreds } = await useMongoFileAuthState(Authentication)
const chatunity = makeWASocket({ auth: state, printQRInTerminal: true })
chatunity.ev.on('creds.update', saveCreds)Handling Events
Baileys uses the EventEmitter syntax for events with full TypeScript support.
[!IMPORTANT] See all available events here
const chatunity = makeWASocket()
chatunity.ev.on('messages.upsert', ({ messages }) => {
console.log('got messages', messages)
})Example to Start
import makeWASocket, { DisconnectReason, useMultiFileAuthState } from '@chatunitycenter/baileys'
import { Boom } from '@hapi/boom'
async function connectToWhatsApp () {
const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
const chatunity = makeWASocket({
auth: state,
printQRInTerminal: true
})
chatunity.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')
}
})
chatunity.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 chatunity.sendMessage(m.key.remoteJid!, { text: 'Hello World' })
}
})
chatunity.ev.on('creds.update', saveCreds)
}
connectToWhatsApp()[!IMPORTANT] In
messages.upsert, use a loop likefor (const message of event.messages)to handle all messages in the array.
Decrypt Poll Votes
Poll votes are encrypted by default and handled in messages.update:
import pino from "pino"
import { makeInMemoryStore, getAggregateVotesInPollMessage } from '@chatunitycenter/baileys'
const logger = pino({ timestamp: () => `,"time":"${new Date().toJSON()}"` }).child({ class: "@Itchatunitychann" })
logger.level = "fatal"
const store = makeInMemoryStore({ logger })
async function getMessage(key){
if (store) {
const msg = await store.loadMessage(key.remoteJid, key.id)
return msg?.message
}
return { conversation: "Itchatunityi Kawaiii" }
}
chatunity.ev.on("messages.update", async (chatUpdate) => {
for(const { key, update } of chatUpdate) {
if(update.pollUpdates && key.fromMe) {
const pollCreation = await getMessage(key)
if(pollCreation) {
const pollUpdate = await getAggregateVotesInPollMessage({
message: pollCreation,
pollUpdates: update.pollUpdates,
})
const toCmd = pollUpdate.filter(v => v.voters.length !== 0)[0]?.name
if (toCmd == undefined) return
console.log(toCmd)
}
}
}
})Decrypt Event Response
Event responses are encrypted by default and handled in messages.update:
import { jidNormalizedUser, getAggregateResponsesInEventMessage } from '@chatunitycenter/baileys'
chatunity.ev.on("messages.update", async ([chatUpdate]) => {
const eventResponses = chatUpdate.update?.eventResponses
const agregate = getAggregateResponsesInEventMessage({ eventResponses }, jidNormalizedUser(chatunity.user.lid))
console.log(agregate)
})Summary of Events on First Connection
connection.updateis fired requesting socket restart- History messages are received in
messaging.history-set
Implementing a Data Store
Baileys does not include built-in storage for chats, contacts, or messages. However, a simple in-memory implementation is provided:
[!IMPORTANT] We highly recommend building your own data store, as storing entire chat history in memory wastes RAM.
import makeWASocket, { makeInMemoryStore } from '@chatunitycenter/baileys'
const store = makeInMemoryStore({ })
store.readFromFile('./baileys_store.json')
setInterval(() => {
store.writeToFile('./baileys_store.json')
}, 10_000)
const chatunity = makeWASocket({ })
store.bind(chatunity.ev)
chatunity.ev.on('chats.upsert', () => {
console.log('got chats', store.chats.all())
})
chatunity.ev.on('contacts.upsert', () => {
console.log('got contacts', Object.values(store.contacts))
})WhatsApp IDs Explained
id(also calledjid) is the WhatsApp ID of the person or group you're messaging.- Format for people:
[country code][phone number]@s.whatsapp.net- Example:
[email protected] - Format for groups:
[email protected]
- Example:
- Broadcast lists:
[timestamp of creation]@broadcast - Stories:
status@broadcast
- Format for people:
Utility Functions
getContentType- returns the content type for any messagegetDevice- returns the device from a messagemakeCacheableSignalKeyStore- speeds up auth storedownloadContentFromMessage- downloads content from any message
Sending Messages
Send all types of messages with a single function:
await chatunity.sendMessage(jid, content, options)Non-Media Messages
Text Message
await chatunity.sendMessage(jid, { text: 'hello world' })Quote Message
await chatunity.sendMessage(jid, { text: 'hello world' }, { quoted: message })Mention User
await chatunity.sendMessage(jid, {
text: '@12345678901',
mentions: ['[email protected]']
})Forward Messages
const msg = getMessageFromStore()
await chatunity.sendMessage(jid, { forward: msg, force: true })Location Message
await chatunity.sendMessage(jid, {
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221
}
})Live Location Message
await chatunity.sendMessage(jid, {
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221
},
live: true
})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 chatunity.sendMessage(id, {
contacts: {
displayName: 'Itchatunitychann',
contacts: [{ vcard }]
}
})Reaction Message
await chatunity.sendMessage(jid, {
react: {
text: '💖',
key: message.key
}
})Pin Message
await chatunity.sendMessage(jid, {
pin: {
type: 1, // 2 to remove
time: 86400, // 24h in seconds
key: Key
}
})Keep Message
await chatunity.sendMessage(jid, {
keep: {
key: Key,
type: 1
}
})Poll Message
await chatunity.sendMessage(jid, {
poll: {
name: 'My Poll',
values: ['Option 1', 'Option 2'],
selectableCount: 1,
toAnnouncementGroup: false
}
})Poll Result Message
await chatunity.sendMessage(jid, {
pollResult: {
name: 'Hi',
values: [['Option 1', 1000], ['Option 2', 2000]]
}
})Call Message
await chatunity.sendMessage(jid, {
call: {
name: 'Hey',
type: 1 // 2 for video
}
})Event Message
await chatunity.sendMessage(jid, {
event: {
isCanceled: false,
name: 'Holiday together!',
description: 'Who wants to come along?',
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221,
name: 'Location name'
},
call: 'audio',
startTime: number,
endTime: number,
extraGuestsAllowed: true
}
})Order Message
await chatunity.sendMessage(jid, {
order: {
orderId: '574xxx',
thumbnail: 'your_thumbnail',
itemCount: 'your_count',
status: 'INQUIRY',
surface: 'CATALOG',
message: 'your_caption',
orderTitle: "your_title",
sellerJid: 'your_jid',
token: 'your_token',
totalAmount1000: 'your_amount',
totalCurrencyCode: 'IDR'
}
})Product Message
await chatunity.sendMessage(jid, {
product: {
productImage: { url: 'your_url' },
productId: 'your_id',
title: 'your_title',
description: 'your_description',
currencyCode: 'IDR',
priceAmount1000: 'your_amount',
url: 'your_url',
productImageCount: 'your_imageCount'
},
businessOwnerJid: 'your_jid'
})Payment Message
await chatunity.sendMessage(jid, {
payment: {
note: 'Hi!',
currency: 'IDR',
amount: '10000',
expiry: 0
}
})Payment Invite Message
await chatunity.sendMessage(id, {
paymentInvite: {
type: 1,
expiry: 0
}
})Admin Invite Message
await chatunity.sendMessage(jid, {
adminInvite: {
jid: '123xxx@newsletter',
name: 'newsletter_name',
caption: 'Please be my channel admin',
expiration: 86400
}
})Group Invite Message
await chatunity.sendMessage(jid, {
groupInvite: {
jid: '[email protected]',
name: 'group_name',
caption: 'Please Join My WhatsApp Group',
code: 'code_invite',
expiration: 86400
}
})Sticker Pack Message
await chatunity.sendMessage(jid, {
stickerPack: {
name: 'Hiii',
publisher: 'By Itchatunitychann',
description: 'Hello',
cover: Buffer,
stickers: [{
sticker: { url: 'https://example.com/1234kjd.webp' },
emojis: ['❤'],
isLottie: false,
isAnimated: false
}]
}
})Share Phone Number Message
await chatunity.sendMessage(jid, { sharePhoneNumber: {} })Request Phone Number Message
await chatunity.sendMessage(jid, { requestPhoneNumber: {} })Button Reply Message
// List
await chatunity.sendMessage(jid, {
buttonReply: {
name: 'Hi',
description: 'description',
rowId: 'ID'
},
type: 'list'
})
// Plain
await chatunity.sendMessage(jid, {
buttonReply: {
displayText: 'Hi',
id: 'ID'
},
type: 'plain'
})
// Template
await chatunity.sendMessage(jid, {
buttonReply: {
displayText: 'Hi',
id: 'ID',
index: 'number'
},
type: 'template'
})
// Interactive
await chatunity.sendMessage(jid, {
buttonReply: {
body: 'Hi',
nativeFlows: {
name: 'menu_options',
paramsJson: JSON.stringify({ id: 'ID', description: 'description' }),
version: 1
}
},
type: 'interactive'
})Buttons Message
await chatunity.sendMessage(jid, {
text: 'This is a button message!',
footer: 'Hello World!',
buttons: [{
buttonId: 'Id1',
buttonText: { displayText: 'Button 1' }
}, {
buttonId: 'Id2',
buttonText: { displayText: 'Button 2' }
}]
})Buttons List Message
await chatunity.sendMessage(jid, {
text: 'This is a list!',
footer: 'Hello World!',
title: 'Amazing list title',
buttonText: 'View list',
sections: [{
title: 'Section 1',
rows: [{
title: 'Option 1',
rowId: 'option1'
}, {
title: 'Option 2',
rowId: 'option2',
description: 'Description'
}]
}]
})Buttons Product List Message
await chatunity.sendMessage(jid, {
text: 'This is a list!',
footer: 'Hello World!',
title: 'Product list',
buttonText: 'View list',
productList: [{
title: 'This is a title',
products: [{ productId: '1234' }, { productId: '5678' }]
}],
businessOwnerJid: '[email protected]',
thumbnail: 'https://example.com/image.jpg'
})Buttons Cards Message
await chatunity.sendMessage(jid, {
text: 'Body Message',
title: 'Title Message',
cards: [{
image: { url: 'https://example.com/image.jpg' },
title: 'Card Title',
body: 'Card Body',
footer: 'Card Footer',
buttons: [{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Button',
id: 'ID'
})
}]
}]
})Buttons Interactive Message
await chatunity.sendMessage(jid, {
text: 'Interactive message',
title: 'Title',
footer: 'Footer',
interactiveButtons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Click Me!',
id: 'your_id'
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: 'Follow',
url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
})
},
{
name: 'cta_call',
buttonParamsJson: JSON.stringify({
display_text: 'Call',
phone_number: '628xxx'
})
},
{
name: 'open_webview',
buttonParamsJson: JSON.stringify({
title: 'Follow',
link: { url: 'https://example.com' }
})
}
]
})Buttons Interactive Message PIX
await chatunity.sendMessage(jid, {
text: '',
interactiveButtons: [{
name: 'payment_info',
buttonParamsJson: JSON.stringify({
payment_settings: [{
type: "pix_static_code",
pix_static_code: {
merchant_name: 'Your Name',
key: '[email protected]',
key_type: 'EMAIL'
}
}]
})
}]
})Buttons Interactive Message PAY
await chatunity.sendMessage(jid, {
text: '',
interactiveButtons: [{
name: 'review_and_pay',
buttonParamsJson: JSON.stringify({
currency: 'IDR',
total_amount: { value: '999999999', offset: '100' },
reference_id: '45XXXXX',
type: 'physical-goods',
order: {
status: 'completed',
items: [{
name: 'Product',
amount: { value: '999999999', offset: '100' },
quantity: '1'
}]
}
})
}]
})Status Mentions Message
const jids = ['[email protected]', '[email protected]']
// Text
await chatunity.sendStatusMentions(
{
text: 'Hello Everyone :3',
font: 2
},
jids
)
// Image
await chatunity.sendStatusMentions(
{ image: { url: 'https://example.com/image.jpg' } },
jids
)
// Video
await chatunity.sendStatusMentions(
{ video: { url: 'https://example.com/video.mp4' } },
jids
)Shop Message
await chatunity.sendMessage(jid, {
text: 'Body',
title: 'Title',
footer: 'Footer',
shop: {
surface: 1,
id: 'https://example.com'
},
viewOnce: true
})Collection Message
await chatunity.sendMessage(jid, {
text: 'Body',
title: 'Title',
footer: 'Footer',
collection: {
bizJid: 'jid',
id: 'https://example.com',
version: 1
},
viewOnce: true
})Media Messages
Sending media (video, stickers, images) is easier and more efficient.
[!NOTE] You can pass
{ stream: Stream },{ url: Url }, orBufferdirectly. See more here
[!TIP] Use Stream or Url to save memory
GIF Message
await chatunity.sendMessage(jid, {
video: fs.readFileSync('Media/gif.mp4'),
caption: 'hello world',
gifPlayback: true
})Video Message
await chatunity.sendMessage(id, {
video: { url: './Media/video.mp4' },
caption: 'hello world'
})Video PTV Message
await chatunity.sendMessage(id, {
video: { url: './Media/video.mp4' },
ptv: true
})Audio Message
Audio needs to be converted to OGG format with ffmpeg:
ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.oggawait chatunity.sendMessage(jid, {
audio: { url: './Media/audio.mp3' },
mimetype: 'audio/mp4'
})Image Message
await chatunity.sendMessage(id, {
image: { url: './Media/image.png' },
caption: 'hello world'
})Album Message
await chatunity.sendMessage(id, {
album: [{
image: { url: 'https://example.com/image.jpg' },
caption: 'Caption'
}, {
video: { url: 'https://example.com/video.mp4' },
caption: 'Caption'
}]
})View Once Message
await chatunity.sendMessage(id, {
image: { url: './Media/image.png' },
viewOnce: true,
caption: 'hello world'
})Link Previews
By default, WhatsApp does not generate link previews when sent from web. Baileys provides this functionality.
To enable link previews, add link-preview-js to your project:
yarn add link-preview-jsThen send a link:
await chatunity.sendMessage(jid, {
text: 'Hi, this was sent using https://github.com/whiskeysockets/baileys'
})AI Icon Feature
await chatunity.sendMessage(jid, { text: 'Hi' }, { ai: true })
// With relay
await chatunity.relayMessage(jid, { extendedTextMessage: { text: 'Hi' } }, { AI: true })Modifying Messages
Delete Messages (for everyone)
const msg = await chatunity.sendMessage(jid, { text: 'hello world' })
await chatunity.sendMessage(jid, { delete: msg.key })Editing Messages
await chatunity.sendMessage(jid, { edit: msg.key, text: 'edited message' })Working with Media
Thumbnail in Media Messages
Thumbnails can be generated automatically for images & stickers if you add jimp or sharp:
yarn add jimp
# or
yarn add sharpFor videos, install ffmpeg on your system.
Downloading Media Messages
import { createWriteStream } from 'fs'
import { downloadMediaMessage, getContentType } from '@chatunitycenter/baileys'
chatunity.ev.on('messages.upsert', async ({ messages }) => {
for (const m of messages) {
if (!m.message) return
const messageType = getContentType(m)
if (messageType === 'imageMessage') {
const stream = await downloadMediaMessage(m, 'stream', {}, {
logger,
reuploadRequest: chatunity.updateMediaMessage
})
stream.pipe(createWriteStream('./my-download.jpeg'))
}
}
})Re-upload Media Message to WhatsApp
const downloadedContent = await downloadMediaMessage(...)
const uploadedUrl = await chatunity.uploadMedia(downloadedContent)