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

@kangwifiinc/baileys

v5.1.17

Published

WhatsApp library — ringan, multi-fitur, tahan lama. Client API di atas Baileys 7: QR/pairing, auto-reconnect, state-machine recovery, MessageBuilder, CommandSystem, Automation, Plugins, Media/Sticker helpers. 1 dependency.

Readme

@kangwifiinc/baileys

Library WhatsApp — ringan, multi-fitur, tahan lama.

Satu Client di atas Baileys 7: login QR/pairing, auto-reconnect tahan-banting, MessageBuilder fluent, CommandSystem (arg-parser ala CLI), Wizard percakapan multi-langkah, AI-rich cards, A2UI widget, media/sticker, LID⇄JID, plugin system, dan util zero-dep.

  • 1 dependency inti. Tools berat (sharp, ffmpeg, qrcode-terminal) bersifat optional peer — dimuat hanya saat dipakai.
  • 95 unit test + tes integrasi koneksi nyata ke server WhatsApp (QR terbit, pairing code, kirim konten interaktif).

Instalasi

npm i @kangwifiinc/baileys

# opsional — pasang sesuai kebutuhan:
npm i sharp                          # gambar & sticker statis
npm i ffmpeg-static fluent-ffmpeg    # sticker/video animasi
npm i qrcode-terminal                # QR ASCII di terminal

Tanpa semua peer opsional di atas, Client tetap jalan penuh (QR dicetak sebagai URL; fungsi yang butuh sharp/ffmpeg menolak dengan pesan jelas, bukan crash).

Quick start

import { Client, FileAuthStore } from '@kangwifiinc/baileys';

const client = new Client({
 sessionId: 'bot',
 auth: new FileAuthStore({ basePath: './auth' }),
 ownerIds: ['[email protected]'],
 autoRead: true,          // tanda-tangan baca otomatis
 autoRejectCall: true,    // tolak panggilan masuk
});

client.on('connect', ({ me }) => console.log('online:', me.id));
client.on('text', msg => console.log('pesan:', msg.text));

QR muncul di terminal → scan lewat WhatsApp → Perangkat Tertaut.

Pairing code (tanpa scan QR)

const client = new Client({ authType: 'pairing', phoneNumber: '6281234567890' });
client.on('pairing-code', ({ code }) => console.log('kode:', code));
// atau manual: await client.requestPairingCode('62812…'[, custom8]);

MessageBuilder

await client.send(jid).text('Halo!').reply(message).mentions([user]).send();
await client.send(jid).image(buf, { caption: 'Lihat ini!' }).send();
await client.send(jid).voice(buf).send();                       // voice note
await client.send(jid).document(buf, { fileName: 'a.pdf' }).send();
await client.send(jid).poll('Makan apa?', ['Nasi', 'Mie']).send();
await client.send(jid).location(-6.208, 106.845, { name: 'Jakarta' }).send();
await client.send(jid).viewOnce(); // dsb.

// thenable — tanpa .send() pun jalan
await client.send(jid).text('auto-send saat di-await');

Builder lain: ButtonBuilder, ListBuilder, CarouselBuilder, PollBuilder, RichTextBuilder, NativeFlowBuilder, AIRichBuilder, A2UI.

CommandSystem (+ arg-parser ala CLI)

import { CommandSystem } from '@kangwifiinc/baileys';

const cmd = new CommandSystem(client.socket, { prefix: ['!', '/'], ownerIds: ['…'] });

cmd.command('ping', ctx => ctx.reply('pong! 🏓'));
cmd.command('kick', { adminOnly: true, cooldown: 5000, aliases: ['remove'] }, async ctx => {
 // ctx.args / ctx.positionals / ctx.flags tersedia + getter bertipe:
 const days = ctx.getNum('days', 0);      // kick --days=7 → 7
 if (ctx.getBool('soft')) { /* … */ }
 const target = ctx.mentions[0] ?? ctx.quoted?.sender;
 if (target) await ctx.sock.groupParticipantsUpdate(ctx.jid, [target], 'remove');
});

cmd.use(async (ctx, next) => { console.log(ctx.sender, ctx.command); await next(); });
cmd.installHelp().attach();          // "!help" otomatis

Atau langsung lewat client (ter-pasang saat connect):

client.command('ping', ctx => ctx.reply('pong'));
client.middleware(logger);

Guards: adminOnly, ownerOnly, groupOnly, privateOnly, cooldown, rateLimit, hidden. Ban/unban per JID.

Parser berdiri sendiri (bisa dipakai di luar command):

import { parseArgs, str, num, bool, arr } from '@kangwifiinc/baileys';
const { flags, positionals, rest } = parseArgs('add --name="John Doe" -vv file -- tail');
str(flags, 'name');          // 'John Doe'
bool(flags, 'v');            // true (cluster -vv)
arr(flags, 'tag');           // untuk --tag a --tag b

Wizard (percakapan multi-langkah)

client.wizard()
 .flow('daftar', {
 trigger: '!daftar',
 timeoutMs: 5 * 60_000,
 steps: [
 { ask: 'Nama?', key: 'nama', validate: v => v.length >= 2 ? { ok: true, value: v } : { ok: false, error: 'terlalu pendek' } },
 { ask: 'Umur?', key: 'umur', validate: v => /^\d+$/.test(v) ? { ok: true, value: +v } : { ok: false, error: 'harus angka' } },
 ],
 onFinish: (data, ctx) => ctx.send(`Selesai ${data.nama}, umur ${data.umur}!`),
 })
 .attach();

Per-chat state, validasi tiap jawaban, kata batal (batal/cancel/stop/keluar), timeout idle otomatis.

AI-rich & kartu interaktif

import { AIRichBuilder, md } from '@kangwifiinc/baileys';

const card = new AIRichBuilder()
 .title('🤖 wazo AI')
 .answer(md.heading('Ringkasan') + '\n' + md.bullet('poin ' + md.bold('tebal')) + '\n\n' + md.code('ping()', 'py'))
 .footer('via wazo')
 .reply('Mantap', 'like')
 .url('Buka', 'https://www.npmjs.com/package/@kangwifiinc/baileys');

await client.send(jid).raw(card.build()).send();   // AI-rich asli (richResponseMessage)
await card.sendAsText(client.socket, jid);          // fallback: teks berformat WA
  • AIRichBuilder menghasilkan AI-rich WhatsApp sejati (botForwardedMessage.richResponseMessage + messageContextInfo.botMetadata).
  • NativeFlowBuilder / ListBuilder → kartu native_flow (quick-reply / URL / copy-code / single_select).
  • parseRichText & toWhatsAppMarkdown → konversi markdown → markup WA.

Rendering kartu interaktif/AI bergantung pada jenis akun WhatsApp. Payload valid & diterima server, tapi WhatsApp terutama menampilkan widget dari akun Business/bot resmi; dari akun personal, banyak klien merender teks fallback. Pakai .toText()/.sendAsText() untuk hasil yang selalu tampil.

A2UI (widget Bloks)

import { A2UI } from '@kangwifiinc/baileys';

const ui = new A2UI();
const title = ui.text('🧩 Widget', { variant: 'h1' });
const pic   = ui.image('https://…/a.jpg');
const btn   = ui.button(ui.text('Buka'), { action: { type: 'openUrl', url: 'https://…' } });
ui.root([ ui.column([title, pic, btn]) ]);

await client.sendA2UI(jid, ui, {
 bodyText: 'Halo', footer: 'wazo',
 buttons: [{ name: 'cta_url', params: { display_text: 'Info', url: 'https://…' } }],
});

A2UI/Bloks memakai bloksWidget. Protobuf Baileys rilis saat ini belum punya field tersebut → sendA2UI melempar error jelas (bukan diam-diam jadi teks), kecuali { allowFallback: true }. Untuk mengaktifkan penuh, tambal protobuf:

npx @kangwifiinc/baileys          # (opsional) atau:
node_modules/.bin/wazo-proto-update

updateBaileysProto() (di-export) mengunduh WAProto yang memuat pesan Bloks, memvalidasi (menolak file kecil / yang berisi API berbahaya), lalu menulis ke node_modules/@whiskeysockets/baileys/WAProto. Opt-in, tak pernah otomatis.

Cek kemampuan protomu kapan pun:

import { baileysCapabilities } from '@kangwifiinc/baileys';
const caps = await baileysCapabilities();
// { nativeFlow, singleSelect, poll, messageSecret, bloksWidget, isAIGenerated, … }

LID ⇄ JID

WhatsApp memigrasi dari JID nomor (…@s.whatsapp.net) ke "LID" (…@lid).

import { isLidJid, toLidJid, toPnJid, jidToLid, lidToJid, supportsLidMapping } from '@kangwifiinc/baileys';

isLidJid('62812@lid');                 // true
toLidJid('62812-34');                  // '6281234@lid'
supportsLidMapping(client.socket);     // ada map LID di akun ini?
await jidToLid('[email protected]', client.socket); // '6281234@lid' (butuh map)
await lidToJid('6281234@lid', client.socket);            // PN (butuh reverse map)

Format murni selalu tersedia; pemetaan penuh butuh map LID yang sudah disinkron kontak akun.

Media & sticker (EXIF asli)

import { MediaHelper, StickerHelper, fetchBuffer } from '@kangwifiinc/baileys';

const img = await fetchBuffer('https://…/a.jpg');            // native fetch, tanpa axios
const sticker = await StickerHelper.fromImage(img.buffer, { pack: 'Pack', author: 'bot', categories: ['😀'] });
await client.send(jid).sticker(sticker).send();

StickerHelper.extractMetadata(sticker);  // { pack: 'Pack', author: 'bot', … } — round-trip nyata
await StickerHelper.fromText('Halo', { pack: 'T' });          // teks → WebP
await StickerHelper.fromVideo(buf, { pack: 'A' });            // video → animasi

MediaHelper: resizeImage, toWebP, toJPEG/PNG, compress, createThumbnail, addWatermark, blur, grayscale, rotate, flip, getMetadata, formatSize.

Automation

import { AutoRead, AutoRejectCall, AutoPresence, AutoDelete, Broadcast, Scheduler } from '@kangwifiinc/baileys';

new AutoRead(client.socket, { excludeGroups: true }).start();
new AutoRejectCall(client.socket).start();
new Broadcast(client.socket, 800).sendText(jids, 'Halo!', { onProgress: (d, t) => console.log(`${d}/${t}`) });
new Scheduler(client.socket).schedule(jid, { text: 'meeting' }, 60 * 60_000);

Plugin system

import { definePlugin, PluginLoader } from '@kangwifiinc/baileys';
export default definePlugin({ name: 'echo', version: '1.0.0', onMessage(msg, ctx) { /* … */ } });
await new PluginLoader(client.socket).loadFromDir('./plugins');

Koneksi tahan-banting

const client = new Client({ sessionId: 'bot', reconnect: { initialDelayMs: 1000, maxDelayMs: 30000 } });
client.on('state-change', ({ prev, next }) => console.log(prev, '→', next));
client.on('reconnecting', ({ branch, action, delayMs }) => console.log(`recovery ${branch}: ${action} (${delayMs}ms)`));
  • Connection state machine — transisi legal saja, tiap perubahan jadi event.
  • Multi-branch recovery — immediate-retry → stream-reconnect → backoff → key-refresh → signal-prekey-fetch → full-reauth; creds dibersihkan otomatis saat shouldClearAuth (logged-out/forbidden/bad-session).
  • AuthGuard — laju pairing-code dibatasi agar tak kena-ban WhatsApp.
  • Rich event decoders — reaksi, edit, hapus, poll-vote, button/list-select.

Performa & footprint

  • Idle (sesi aktif, tanpa trafik): ~60–64 MB RSS — didominasi Baileys + baseline Node; kode wazo sendiri hanya beberapa MB. Stabil, tanpa kebocoran (terverifikasi flat 3 menit).
  • lightweight: true — store kecil, syncFullHistory:false, markOnlineOnConnect:false.
  • MemoryMessageStore({ cap }) — riwayat dibatasi (default 500), FIFO.
  • Saran VPS kecil: node --max-old-space-size=64 bot.js.

Utilitas bawaan (zero-dep)

retry, sleep, debounce, throttle, PromiseQueue, RateLimiter, IdempotencyCache, CircuitBreaker, LruCache, RecoveryPlan, createReconnectStrategy, mapDisconnectReason/shouldReconnect/shouldClearAuth, AuthGuard, normalizePhoneNumber/validateE164, helper JID (phoneNumberToJid, normalizeUserJid, buildVcard, jidsEqual), MIME via magic-byte, dan deteksi kapabilitas proto.

Pengembangan

npm run build            # tsc → dist/ (CJS + deklarasi tipe)
npm test                 # 95 unit + media + sistem unik (offline)
npm run test:esm         # smoke import ESM
npm run test:integration # koneksi nyata WhatsApp: QR + pairing (butuh internet)
npm run test:all         # semuanya

Batasan jujur (dari sisi WhatsApp, bukan library)

  • Kartu interaktif/AI/A2UI terkirim valid (server terima), tapi render di klien terutama untuk pengirim Business/bot resmi; akun personal sering hanya menampilkan teks. Solusi: .toText()/.sendAsText().
  • isAIGenerated badge & bloksWidget butuh WAProto terbaru (di luar rilis @whiskeysockets/baileys saat ini) — sediakan updateBaileysProto()/bin.
  • LID→JID penuh butuh map kontak yang disinkron.

Lisensi

MIT