Skip to Content
Introduction

Zaileys

One framework. Two WhatsApp APIs. Zero rewrites.

Zaileys is a type-safe, batteries-included WhatsApp framework for Node.js and TypeScript. Write your bot once against a single chainable builder and fully-typed events — then run it on either provider by flipping one option:

The send(jid).text() builder, the on('text' | 'image' | 'reaction' | …) events, commands, middleware, plugins, storage, broadcast() and scheduleAt()all identical across both providers. New to Zaileys? Start with Choose Your Provider.

Hello world

The exact same bot logic — only the Client config differs.

import { Client } from 'zaileys' // Default provider — logs in with a QR you scan from your phone. const client = new Client() client.on('qr', ({ qrString }) => console.log('Scan this QR:', qrString)) client.on('connect', ({ me }) => console.log('Connected as', me.id)) client.on('text', async (msg) => { await msg.reply(`Hello ${msg.senderName ?? ''}! You said: ${msg.text}`) })

Scan the printed QR from WhatsApp → Linked Devices and every text gets a reply. No boilerplate, no manual decoding, no any.

By default the Client connects on construction (autoConnect: true), so handlers registered synchronously after new Client() are wired up before the first event arrives. Opt out with new Client({ autoConnect: false }) and call await client.connect() yourself. See Configuration and the Client reference.

Prefer a pairing code over scanning a QR on the unofficial provider? Provide your number:

const client = new Client({ authType: 'pairing', phoneNumber: '6281234567890' }) client.on('pairing-code', ({ code }) => console.log('Enter this code on your phone:', code))

Which provider should I use?

If you want to…Use
Build a personal-account bot, prototype, or automate your own number fastUnofficial (WhatsApp Web)
Use groups, communities, channels, polls, presence, edit/deleteUnofficial — these don’t exist on the Cloud API
Run a compliant business channel with no ban riskOfficial (Meta Cloud API)
Send OTP, marketing, or utility template messages at scaleOfficial
Message users who never texted you first (business-initiated)Official — via approved templates

Full side-by-side breakdown, ToS notes, and a migration guide on Choose Your Provider.

Why Zaileys

  • Two providers, one codebase — the unofficial WhatsApp Web engine and the official Meta Cloud API behind the same Client. Switch with a single option; your handlers never change. See Choose Your Provider.
  • Typed eventsclient.on('text' | 'image' | 'reaction' | 'button-click' | 'group-update' | …), each with a fully-typed payload and IntelliSense. No raw Baileys decoding, no any. See Events.
  • One chainable builderclient.send(jid).text(…).reply(quoted).mentions([…]) resolves to the sent message key when awaited. See Sending Messages.
  • Auto lifecycle — QR or pairing-code login, auto-reconnect with backoff, clean logout, and an optional ignoreMe filter so the bot never replies to itself. See Configuration.
  • Rich & interactive out of the box — native buttons, lists, and carousels, plus Meta-AI-style rich responses written as plain markdown. See Interactive Messages and Rich Responses.
  • Command framework — register client.command('ping', …) routers with alias support and composable middleware. See Commands.
  • Automation — rate-limited broadcast() to many recipients and scheduleAt() for timed sends. See Automation.
  • Pluggable storage — independent auth and message stores with file, memory, sqlite, redis, postgres, and convex adapters. See Storage Adapters.
  • Media processing — lazy image / video / audio / sticker handling, with an optional sharp accelerator that falls back to a pure-JS path automatically. See Media.
  • Runs everywhere — dual ESM/CJS build with .d.ts + .d.cts types; verified on Node, Bun, Deno, and Termux. See Runtimes.
  • Modern foundation — Baileys 7.0.0-rc13 (includes the CVE-2026-48063 spoofing patch), built and type-checked with the native TypeScript 7 compiler.

Install

npm i zaileys

Requires Node.js v20+. The file auth store is the zero-config default — nothing else to install to get started. Other storage backends and the sharp media accelerator are optional peer dependencies; install only the ones you use. Full details on the Installation page.

What you can build

Send anything

await client.send(jid).text('Hello there') await client.send(jid).image('https://example.com/photo.jpg', { caption: 'Nice shot' }) await client.send(jid).poll('Pick one', ['Red', 'Green', 'Blue']) await client.send(jid).album([ { type: 'image', src: './a.jpg' }, { type: 'image', src: './b.jpg' }, ])

A JID is a WhatsApp address: 628xxxxxxxxxx@s.whatsapp.net for a person, xxxxxxxxxx@g.us for a group. Inside an event handler you usually just call msg.reply(…) or client.send(msg.senderId).

Interactive messages

Reply, URL, copy, and call buttons — plus lists and carousels — render natively on personal accounts. Taps come back as typed button-click / list-select events.

await client.send(jid).buttons( [ { id: 'yes', text: 'Yes' }, { type: 'url', text: 'Open docs', url: 'https://github.com/zeative/zaileys' }, { type: 'copy', text: 'Copy code', code: 'ZAILEYS-2026' }, ], { title: 'Pick one', text: 'Tap a button below' }, ) client.on('button-click', (ctx) => console.log('tapped:', ctx.buttonId))

See Interactive Messages for lists, carousels, and every button variant.

Rich responses, written as markdown

Send ordinary markdown — headings, fenced code, tables, and images — and Zaileys renders it as a clean Meta-AI-style response.

await client.send(jid).text( ['*Daily brief* ☕', '', '```ts', "console.log('shipped')", '```'].join('\n'), { rich: true }, )

See Rich Responses for the full directive set.

A command router with middleware

import { Client, type Middleware } from 'zaileys' const client = new Client({ commandPrefix: ['/', '!'] }) const logging: Middleware = async (ctx, next) => { console.log(`[command] ${ctx.command} from ${ctx.senderId}`) await next() } client.use(logging) client.command('ping', async (ctx) => ctx.reply('pong')) client.command('weather', async (ctx) => { const city = ctx.args[0] await ctx.reply(city ? `Weather in ${city}: sunny, 28°` : 'Usage: /weather <city>') })

See Commands for aliases, prefixes, and middleware composition.

Broadcast and schedule

await client.broadcast( ['6281111111111@s.whatsapp.net', '6282222222222@s.whatsapp.net'], (b) => b.text('Maintenance tonight at 22:00.'), { rateLimitPerSec: 5, onProgress: (done, total) => console.log(`${done}/${total}`) }, ) await client.scheduleAt(new Date('2026-12-31T23:59:00'), (b) => b.text('Happy New Year! 🎉'), )

See Automation for rate limiting, progress reporting, and persistent schedules.

Build your first bot

Install zaileys

Add the package with your favourite manager (see Install above) on Node.js v20+.

Create a client and register handlers

new Client() connects automatically. Register your qr, connect, and message handlers immediately after construction.

Authenticate

Run the script and scan the printed QR from WhatsApp → Linked Devices, or pass { authType: 'pairing', phoneNumber } and enter the pairing-code.

Send and receive

Use msg.reply(…) or client.send(jid) to respond. Add commands, buttons, and storage as you grow.

The Getting Started guide walks through each step in detail.

Feature matrix

Legend — 🔗 Unofficial (WhatsApp Web) · ☁️ Official (Meta Cloud API) · 🔗☁️ both.

CapabilityProvidersWhat you getGuide
Connection lifecycle🔗☁️Auto-connect, QR + pairing-code login (unofficial) or token auth (official), reconnect, clean logoutClient · Config
Typed events🔗☁️text, image, reaction, button-click, group-update, and moreEvents
Send builder🔗☁️Chainable text / image / video / audio / document / poll / album · reply · mentionsSending Messages
Media🔗☁️Lazy image/video/audio/sticker processing, optional sharp acceleratorMedia
Interactive UI🔗☁️Buttons (reply/url/copy/call), lists, carouselsInteractive
Rich responses🔗Markdown → Meta-AI-style messages (code, tables, images, directives)Rich Responses
Command framework🔗☁️client.command() routers, aliases, configurable prefixes, middlewareCommands
Automation🔗☁️Rate-limited broadcast(), scheduleAt(), presence controlAutomation
Templates & campaigns☁️Template CRUD, OTP/marketing/utility sends, message-status trackingOfficial Cloud API
Flows & commerce☁️WhatsApp Flows, catalog products, orders, analyticsOfficial Cloud API
Groups & channels🔗Groups, communities, newsletters (channels), presence, edit/deleteGroups
Storage adapters🔗☁️file, memory, sqlite, redis, postgres, convex for auth & messagesStorage
Cross-runtime🔗☁️Dual ESM/CJS, full types; Node, Bun, Deno, TermuxRuntimes

Next steps

💡

Looking for runnable code? Every feature has a matching script in the examples/ folder.

Last updated on