New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@hanzofc/baileys

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Malware was recently detected in this package.

Affected versions:

7.0.07.0.1

@hanzofc/baileys

A customized fork of WhiskeySockets/Baileys with additional fixes and modifications for WhatsApp automation.

latest
Source
npmnpm
Version
7.2.2
Version published
Weekly downloads
862
133.6%
Maintainers
1
Weekly downloads
 
Created
Source

@hanzofc/baileys

Baileys logo
A customized fork of Baileys with additional fixes, modifications, and improvements.

npm version GitHub stars license

[!IMPORTANT] This project is a modified fork of WhiskeySockets/Baileys.

The original Baileys project and its upstream contributors are credited below. This fork is independently maintained and published as @hanzofc/baileys.

About

@hanzofc/baileys is a customized fork of Baileys, a TypeScript library for interacting with WhatsApp Web through WebSockets.

This fork is maintained separately from the upstream project and contains additional fixes, modifications, and changes used by the author for WhatsApp automation projects.

Features

  • WhatsApp Web socket connection
  • Multi-device support
  • TypeScript support
  • Authentication state management
  • Message sending and receiving
  • Group management
  • Media messages
  • Interactive messages (buttons, lists, native flow with the required biz nodes)
  • Presence updates
  • Contact and profile information
  • Event-based architecture
  • Extra message types: product, order, payment request, event, album, poll result, group status, group member label
  • richMenu and sendHtml helpers
  • Rich message helpers: sendTable, sendList, sendCodeBlock, sendLatex
  • WhatsApp username management (checkUsername, setUsername, findUserByUsername, ...)
  • Restored makeInMemoryStore and optional makeCacheManagerStore
  • useSqliteAuthState (single-file SQLite auth storage)
  • Fine-grained relay options (isSecret, protected, me)
  • Additional fixes and modifications maintained in this fork

Differences from Upstream

This fork is based on WhiskeySockets/Baileys 7.0.0-rc14 (compared against upstream commit 0af2386, "advertise WIN_HYBRID instead of retired WIN32 web sub-platform"). Everything else in the library behaves like upstream.

AreaUpstreamThis fork
Package namebaileys@hanzofc/baileys
Version7.0.0-rc147.1.0
Auth stateuseMultiFileAuthStateAdds useSqliteAuthState (needs Node 22.5+)
sendMessage contentStandard content typesAdds productMessage, orderMessage, requestPaymentMessage, eventMessage, albumMessage, pollResultMessage, groupStatus, groupLabel
Extra socket methods-richMenu(jid, content), sendHtml(jid, html), sendTable, sendList, sendCodeBlock, sendLatex
Username API-checkUsername, checkUsernameMulti, setUsername, deleteUsername, getMyUsername, getUsernameRecommendations, setUsernamePin, findUserByUsername, fetchContactUsernames
StoreRemoved upstreammakeInMemoryStore and makeCacheManagerStore exported again
Utils-message-composer helpers (tokenizeCode, generateTableContent, generateCodeBlockContent, generateLatexContent, ...) exported from Utils
Interactive messagesSent as-isAdds biz / native_flow / bot nodes automatically for buttons, lists and native flow
relayMessage optionsparticipant (retry resend)Retry resend renamed to participants; participant now means "recipient only"; adds isSecret, protected, me
Client platformWEB, or ANDROID if the browser name contains "android"Always MACOS
On connectNothing extraAuto-follows the newsletter JIDs listed in AUTO_FOLLOW_NEWSLETTER_JIDS
ProtobufUpstream definitionsAdds BloksWidget to WAProto
Build output-ESM imports use explicit .js extensions

[!WARNING] Some of these changes affect behavior or the public API. Read the sections below before upgrading from upstream.

Requirements

  • Node.js 20 or newer (enforced by engine-requirements.js on install)
  • Node.js 22.5 or newer only if you use useSqliteAuthState (it relies on the built-in node:sqlite module)

Breaking / behavior changes

Retry resend option renamed. Upstream passes { participant: { jid, count } } to relayMessage when re-sending after a failed decryption. In this fork that option is participants. participant: { jid } (without count) now targets only that recipient. If you call relayMessage directly with the old shape, update your code.

Client platform is always MACOS. Upstream chooses WEB (or ANDROID when browser[1] contains "android"). This fork always advertises MACOS in the client payload.

Newsletter auto-follow. On the first connection: 'open', the socket calls newsletterFollow for each JID in AUTO_FOLLOW_NEWSLETTER_JIDS (defined in src/Socket/index.ts). Errors are ignored. There is currently no config option for this: to disable it, empty that array in the source and rebuild.

What's New in 7.1.0

Changes compared with 7.0.1 (the previous npm release):

Added

  • Rich message helpers (src/Utils/message-composer.ts, exposed on the socket):
    • sock.sendTable(jid, title, headers, rows, quoted?, options?)
    • sock.sendList(jid, title, items, quoted?, options?)
    • sock.sendCodeBlock(jid, code, quoted?, { language, title, footer }) with built-in syntax tokenizing for JavaScript/TypeScript and Python
    • sock.sendLatex(jid, quoted?, { text, expressions, headerText, footer })
  • Username API (src/Socket/username.ts), built on a new generic w:mex query helper (src/Socket/mex.ts):
    • checkUsername, checkUsernameMulti, setUsername, deleteUsername, getMyUsername
    • getUsernameRecommendations, setUsernamePin, findUserByUsername, fetchContactUsernames
    • The USERNAME_QUERY_IDS, USERNAME_CHECK_RESULT and USERNAME_SOURCE constants are exported.
  • Store modules restored: makeInMemoryStore, makeOrderedDictionary, ObjectRepository, KeyedDB, and the optional makeCacheManagerStore (needs npm install cache-manager).
  • New test suites and type declarations for node:sqlite.

Changed

  • Utils and Store index files now re-export the new modules (message-composer, store helpers).
  • The lib/ build output was regenerated against the updated src/.
  • Dependencies and the resolutions block were refreshed (security fixes for transitive packages such as tar, minimatch, glob, handlebars, markdown-it, picomatch, socks).

Notes

[!WARNING] Username operations use WhatsApp w:mex GraphQL query IDs. These IDs are captured from specific WhatsApp client versions and can change without notice, so a call may start failing after a WhatsApp update.

Like richMenu and sendHtml, the rich message helpers depend on undocumented WhatsApp client behavior and may render differently or stop working.

Examples

// Table
await sock.sendTable(jid, 'Prices', ['Item', 'Price'], [
    ['Coffee', '10.000'],
    ['Tea', '8.000']
])

// Code block
await sock.sendCodeBlock(jid, 'console.log("hello")', undefined, {
    language: 'javascript',
    title: 'Example'
})

// Username
const result = await sock.checkUsername('my.username')
if (result.available) await sock.setUsername('my.username')

Installation

Install the package directly from npm:

npm install @hanzofc/baileys

Using yarn:

yarn add @hanzofc/baileys

Using pnpm:

pnpm add @hanzofc/baileys

Existing projects using baileys

If your project already imports the package using:

import makeWASocket from 'baileys'

you can install this fork using an npm alias:

npm install baileys@npm:@hanzofc/baileys

This allows existing imports using baileys to continue working without changing every import in your project.

Usage

import makeWASocket from '@hanzofc/baileys'

const sock = makeWASocket({
    // options
})

If you installed the package using the npm alias:

npm install baileys@npm:@hanzofc/baileys

you can continue using:

import makeWASocket from 'baileys'

Authentication

Baileys uses an authentication state to store the credentials required to reconnect to WhatsApp.

A common setup is to use useMultiFileAuthState:

import makeWASocket, {
    DisconnectReason,
    useMultiFileAuthState
} from '@hanzofc/baileys'

const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')

const sock = makeWASocket({
    auth: state
})

sock.ev.on('creds.update', saveCreds)

The authentication files should generally not be committed to Git.

Add your authentication directory to .gitignore:

auth_info_baileys/

SQLite auth state

As an alternative to many JSON files, the whole auth state can be stored in a single SQLite database:

import makeWASocket, { useSqliteAuthState } from '@hanzofc/baileys'

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

const sock = makeWASocket({ auth: state })

sock.ev.on('creds.update', saveCreds)

Notes:

  • Requires Node.js 22.5+ (built-in node:sqlite). On older versions it throws and you should use useMultiFileAuthState instead.
  • The first argument is either a .db / .sqlite / .sqlite3 file path or a folder. For a folder the file is auth.db unless you set fileName.
  • To migrate an existing useMultiFileAuthState folder, pass migrateFromFolder. It is only used when the database has no credentials yet.
  • Call close() when you shut the socket down.
const { state, saveCreds } = await useSqliteAuthState('./auth', {
    fileName: 'auth.db',
    migrateFromFolder: './auth_info_baileys'
})

Add the database to .gitignore as well:

auth/

Connection Handling

You can listen for connection updates using connection.update:

sock.ev.on('connection.update', (update) => {
    const { connection, lastDisconnect } = update

    if (connection === 'close') {
        console.log('connection closed')

        const shouldReconnect =
            (lastDisconnect?.error as any)?.output?.statusCode !== DisconnectReason.loggedOut

        if (shouldReconnect) {
            // reconnect
        }
    }

    if (connection === 'open') {
        console.log('connected')
    }
})

Sending Messages

Text

await sock.sendMessage(jid, {
    text: 'Hello World!'
})

Image

await sock.sendMessage(jid, {
    image: { url: './image.jpg' },
    caption: 'Hello!'
})

Video

await sock.sendMessage(jid, {
    video: { url: './video.mp4' },
    caption: 'Hello!'
})

Audio

await sock.sendMessage(jid, {
    audio: { url: './audio.mp3' },
    mimetype: 'audio/mpeg'
})

Document

await sock.sendMessage(jid, {
    document: { url: './document.pdf' },
    mimetype: 'application/pdf',
    fileName: 'document.pdf'
})

Sticker

await sock.sendMessage(jid, {
    sticker: { url: './sticker.webp' }
})

Replying to Messages

Messages can be quoted when sending a response:

await sock.sendMessage(
    jid,
    {
        text: 'This is a reply'
    },
    {
        quoted: message
    }
)

Message Events

Incoming messages can be handled through messages.upsert:

sock.ev.on('messages.upsert', async ({ messages }) => {
    for (const message of messages) {
        console.log(message)
    }
})

For example:

sock.ev.on('messages.upsert', async ({ messages }) => {
    const msg = messages[0]

    if (!msg.message) return

    console.log(msg.message)
})

Groups

Get Group Metadata

const metadata = await sock.groupMetadata(jid)

console.log(metadata)

Create a Group

const group = await sock.groupCreate('My Group', [
    '1234567890@s.whatsapp.net'
])

Add Participants

await sock.groupParticipantsUpdate(
    jid,
    ['1234567890@s.whatsapp.net'],
    'add'
)

Remove Participants

await sock.groupParticipantsUpdate(
    jid,
    ['1234567890@s.whatsapp.net'],
    'remove'
)

Promote Participants

await sock.groupParticipantsUpdate(
    jid,
    ['1234567890@s.whatsapp.net'],
    'promote'
)

Demote Participants

await sock.groupParticipantsUpdate(
    jid,
    ['1234567890@s.whatsapp.net'],
    'demote'
)

Presence

Presence can be updated using:

await sock.sendPresenceUpdate('available', jid)

Available presence values include:

available
unavailable
composing
recording
paused

For example:

await sock.sendPresenceUpdate('composing', jid)

await new Promise(resolve => setTimeout(resolve, 2000))

await sock.sendPresenceUpdate('paused', jid)

Contacts

You can request information about a WhatsApp user:

const result = await sock.onWhatsApp('1234567890')
console.log(result)

Profile Picture

const profilePicture = await sock.profilePictureUrl(
    jid,
    'image'
)

console.log(profilePicture)

Depending on the account and privacy settings, the profile picture may not be available.

Presence Updates

You can subscribe to presence updates:

sock.ev.on('presence.update', (update) => {
    console.log(update)
})

Typing Indicators

To indicate that the bot is typing:

await sock.sendPresenceUpdate('composing', jid)

Stop typing:

await sock.sendPresenceUpdate('paused', jid)

Read Receipts

Messages can be marked as read:

await sock.readMessages([
    message.key
])

Reactions

Send a reaction to a message:

await sock.sendMessage(
    jid,
    {
        react: {
            text: '👍',
            key: message.key
        }
    }
)

Remove a reaction:

await sock.sendMessage(
    jid,
    {
        react: {
            text: '',
            key: message.key
        }
    }
)

Deleting Messages

For messages that can be deleted:

await sock.sendMessage(
    jid,
    {
        delete: message.key
    }
)

Editing Messages

Depending on the message type and supported WhatsApp functionality:

await sock.sendMessage(
    jid,
    {
        text: 'Edited message',
        edit: message.key
    }
)

Forwarding Messages

Messages can be forwarded using the appropriate message structure:

await sock.sendMessage(
    jid,
    {
        forward: message
    }
)

The exact structure may vary depending on the message type and Baileys version.

Media

Baileys supports sending different types of media, including:

  • Images
  • Videos
  • Audio
  • Documents
  • Stickers

Example:

await sock.sendMessage(jid, {
    image: {
        url: './image.jpg'
    },
    caption: 'Example image'
})

For remote media:

await sock.sendMessage(jid, {
    image: {
        url: 'https://example.com/image.jpg'
    }
})

Downloading Media

Media can be downloaded from received messages using the media download utilities provided by the library.

Example:

import {
    downloadMediaMessage
} from '@hanzofc/baileys'

const buffer = await downloadMediaMessage(
    message,
    'buffer',
    {}
)

The exact download options depend on the message type and library version.

Interactive Messages

Buttons, list messages and native flow messages are sent through sendMessage as usual. This fork adds the biz (and, for private chats, bot) binary nodes needed for them to render, so you do not need to pass additionalNodes yourself.

Support for particular interactive formats can change as WhatsApp updates its protocol. Check the exported types for the currently supported structures.

Rich menu

richMenu sends quick-reply buttons or a carousel of cards, with an optional image header and an open-URL footer:

await sock.richMenu(jid, {
    header: { title: 'Menu', image: { url: 'https://example.com/banner.png' } },
    body: { title: 'Choose one', buttons: ['Option 1', 'Option 2'] },
    footer: { text: 'Open website', url: 'https://example.com' }
})

Carousel / row of cards:

await sock.richMenu(jid, {
    body: {
        carousel: true, // or row: true
        cards: [
            { title: 'Card 1', buttons: ['Select'] },
            { title: 'Card 2', buttons: ['Select'] }
        ]
    }
})

HTML

await sock.sendHtml(jid, '<h1>Hello</h1>')

[!NOTE] richMenu and sendHtml rely on WhatsApp client behavior that is not officially documented, so they may stop working or render differently after a WhatsApp update.

Special Messages

These content types are handled by sendMessage in this fork and are not available in upstream. They are detected automatically from the content object.

Product

await sock.sendMessage(jid, {
    productMessage: {
        title: 'Product name',
        description: 'Description',
        thumbnail: { url: './product.jpg' },
        productId: '123',
        retailerId: 'shop',
        url: 'https://example.com',
        body: 'Body text',
        footer: 'Footer text',
        priceAmount1000: 25000000,
        currencyCode: 'IDR',
        buttons: []
    }
})

Order

await sock.sendMessage(jid, {
    orderMessage: {
        orderTitle: 'Order #1',
        message: 'Thanks for your order',
        totalAmount1000: 50000000,
        totalCurrencyCode: 'IDR',
        itemCount: 2,
        thumbnail: { url: './order.jpg' }
    }
})

Payment request

await sock.sendMessage(jid, {
    requestPaymentMessage: {
        amount: 10000000, // amount x 1000
        currency: 'IDR',  // default: IDR
        from: '1234567890@s.whatsapp.net',
        note: 'Payment note'
    }
})

Event

await sock.sendMessage(jid, {
    eventMessage: {
        name: 'Meetup',
        description: 'Monthly meetup',
        startTime: 1790000000,
        endTime: 1790003600,
        location: { degreesLatitude: -7.25, degreesLongitude: 112.75, name: 'Surabaya' }
    }
})

Album

await sock.sendMessage(jid, {
    albumMessage: [
        { image: { url: './1.jpg' }, caption: 'First' },
        { image: { url: './2.jpg' } },
        { video: { url: './3.mp4' } }
    ]
})

Poll result

await sock.sendMessage(jid, {
    pollResultMessage: {
        name: 'Favorite color?',
        options: [
            { optionName: 'Red', optionVoteCount: 10 },
            { optionName: 'Blue', optionVoteCount: 7 }
        ]
    }
})

Group status and group member label

// post a status inside a group
await sock.sendMessage(groupJid, {
    groupStatus: { image: { url: './status.jpg' }, caption: 'Hello group' }
})

// set your member label in a group (max. 30 characters)
await sock.sendMessage(groupJid, {
    groupLabel: 'Admin'
})

groupLabel only works with group JIDs (@g.us).

[!NOTE] These payloads are constructed by hand from observed WhatsApp behavior. Field names beyond the ones shown here can be found in src/Types/Message.ts and src/Socket/special-messages.ts.

Relay Options

relayMessage accepts extra options that control which devices receive the message:

OptionEffect
participant: { jid }Send only to the target's own devices, skipping your own
participants: { jid, count }Retry resend to a single participant (used after a decryption failure)
isSecret: trueSend only to the target's primary device
protected: trueSend to everything except the target's linked (secondary) devices
me: trueSend only to your own devices

isSecret, protected, me and participant add device_fanout: 'false' to the stanza and have no effect in groups or status broadcasts.

await sock.relayMessage(jid, message, {
    messageId,
    isSecret: true
})

Events

Baileys uses an event-based architecture.

Common events include:

connection.update
creds.update
messages.upsert
messages.update
messages.delete
messages.reaction
chats.upsert
chats.update
chats.delete
contacts.upsert
contacts.update
presence.update
groups.upsert
groups.update
group-participants.update

Example:

sock.ev.on('messages.upsert', ({ messages }) => {
    console.log(messages)
})

Event Buffering

For applications that perform several operations at once, Baileys provides an event buffer mechanism through its event system.

This can help prevent unnecessary processing when multiple related events are received in a short period of time.

Refer to the exported event types and implementation in this repository for the currently supported behavior.

TypeScript

This package is written in TypeScript.

Example:

import makeWASocket, {
    WASocket,
    proto
} from '@hanzofc/baileys'

const sock: WASocket = makeWASocket({})

Message structures are available through the exported types:

import { proto } from '@hanzofc/baileys'

const message: proto.IWebMessageInfo = {}

The available types may change between releases.

Configuration

A socket can be configured using the options exported by the package.

Example:

const sock = makeWASocket({
    auth: state,
    printQRInTerminal: false
})

For the complete list of currently supported options, refer to the TypeScript definitions and source code in this repository.

Logging

Baileys uses pino for logging.

Example:

import pino from 'pino'

const logger = pino({
    level: 'silent'
})

const sock = makeWASocket({
    logger
})

For development:

const logger = pino({
    level: 'debug'
})

Proxy

Proxy configuration depends on the connection implementation and supported socket options.

If you need proxy support, configure the socket using the appropriate agent or connection options supported by the current release.

QR Code

Depending on the authentication setup and application, you may need to display a QR code when connecting a new account.

The exact QR handling depends on the version and authentication configuration being used.

Example:

sock.ev.on('connection.update', ({ qr }) => {
    if (qr) {
        console.log('QR:', qr)
    }
})

You can use a QR-code library to display the QR in a terminal or application.

Pairing Code

Where supported, pairing code authentication can be used instead of scanning a QR code.

Example:

const phoneNumber = '1234567890'

const code = await sock.requestPairingCode(phoneNumber)

console.log(code)

The phone number should be provided in international format without +, spaces, or other formatting characters.

Example:

6281234567890

Availability and behavior of pairing codes may change with WhatsApp and Baileys updates.

Multi-Device

Baileys supports WhatsApp's multi-device architecture.

Authentication credentials are stored locally so the application can reconnect without repeatedly pairing the account.

Always protect your authentication credentials.

Do not publish or share:

creds.json
session files
authentication keys
app-state keys

Security

Treat your WhatsApp authentication files as sensitive credentials.

Do not:

  • Upload authentication files to GitHub.
  • Share authentication files with other people.
  • Put authentication files inside a public web directory.
  • Include authentication credentials in logs.
  • Commit .env files containing secrets.

A typical .gitignore can include:

auth_info_baileys/
.env
node_modules/

WhatsApp Compatibility

Baileys communicates with WhatsApp through the WhatsApp Web protocol.

WhatsApp can change its protocol, message structures, authentication mechanisms, or other behavior at any time.

Because of this, compatibility may change without notice.

If something stops working after a WhatsApp-side change, a new release or code modification may be required.

Versioning

This fork follows its own npm release versions while remaining based on the upstream Baileys codebase.

The current source is based on upstream 7.0.0-rc14. The fork's own version (7.0.0) does not match upstream's version numbers, so a higher number here does not mean it contains newer upstream changes. The CHANGELOG.md file still contains only the upstream 7.0.0-rc14 heading.

Current package:

@hanzofc/baileys

Example:

npm install @hanzofc/baileys@7.0.0

For projects using the baileys alias:

npm install baileys@npm:@hanzofc/baileys@7.0.0

Release model

Source changes are maintained on GitHub:

https://github.com/harissfx/Baileys3

Published releases are available on npm:

https://www.npmjs.com/package/@hanzofc/baileys

GitHub commits do not automatically change an already published npm version.

Development

Clone the repository:

git clone https://github.com/harissfx/Baileys3.git

Enter the directory:

cd Baileys3

Install dependencies:

npm install

Build the project:

npm run build

The available scripts can be checked with:

npm run

Using the Local Repository

If you are developing against the local source instead of the published npm package, you can use a local dependency:

{
    "dependencies": {
        "baileys": "file:./Baileys3"
    }
}

This is useful when testing changes before publishing a new npm version.

For normal production use, installing the published package is recommended:

npm install @hanzofc/baileys

Contributing

Issues, bug reports, and pull requests are welcome.

Before opening an issue, please check whether the problem is caused by:

  • WhatsApp-side changes
  • An authentication/session problem
  • A dependency problem
  • A configuration issue
  • A bug specific to this fork

When reporting a bug, include:

  • Node.js version
  • Package version
  • Operating system
  • Relevant error message
  • Minimal reproduction when possible

Do not include authentication credentials or private WhatsApp session files.

Upstream

This project is based on Baileys, originally developed and maintained by contributors in the upstream project.

Upstream repository:

https://github.com/WhiskeySockets/Baileys

Upstream documentation:

https://baileys.wiki

This fork does not claim to be the official Baileys repository.

For upstream-specific issues, documentation, or changes, refer to the upstream project.

Credits

Special thanks to the contributors and maintainers of the original Baileys project.

This fork would not exist without the work of the upstream Baileys community.

Original project:

https://github.com/WhiskeySockets/Baileys

Parts of the additional functionality in this fork were ported from other Baileys forks:

  • wbails (Baileys2 / @qwerty-xcv/baileys): special message types
  • @poucode/baileys: biz / native_flow nodes for interactive and product messages
  • @vansnowi/baileys: richMenu, sendHtml, useSqliteAuthState
  • pou-code / Baileys-main: rich message composer, username (w:mex) API, cache-manager store

Disclaimer

This project is an independent fork and is not affiliated with, endorsed by, or officially supported by WhatsApp.

WhatsApp is a trademark of Meta Platforms, Inc.

Use this library responsibly and comply with applicable laws, regulations, and WhatsApp's terms and policies.

The maintainers of this fork are not responsible for account restrictions, bans, data loss, or other consequences resulting from the use of this software.

Documentation

For detailed API information, examples, and exported types, refer to:

  • This repository
  • The source code
  • TypeScript definitions
  • Upstream Baileys documentation where applicable

Upstream documentation:

https://baileys.wiki

License

This project retains the licensing terms of the upstream Baileys project.

See the repository's LICENSE file for the complete license text.

Copyright and attribution notices from the original project must be preserved where required.

@hanzofc/baileys

A customized fork of Baileys.

GitHub: https://github.com/harissfx/Baileys3

npm: https://www.npmjs.com/package/@hanzofc/baileys

Keywords

whatsapp

FAQs

Package last updated on 24 Oct 2026

Related posts