Package Exports
- neroxbails
- neroxbails/lib/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (neroxbails) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
💬 Baileys — API WhatsApp Indonesia

⚠️ SECURITY WARNING ⚠️
This is a private version of Baileys with enhanced security features. This repository is NOT for public use and contains proprietary security measures. Unauthorized access or distribution is strictly prohibited.
💖 Support
Jika project ini membantu Anda, berikan ⭐ di GitHub!
Made with ❤️ by @neroxkira
📖 Deskripsi
Baileys adalah pustaka JavaScript yang ringan dan powerful untuk terhubung dengan WhatsApp Web API melalui WebSocket. Memungkinkan Anda membuat bot WhatsApp, automasi, dan integrasi dengan mudah tanpa perlu WhatsApp Business API yang berbayar!
✨ Fitur Unggulan
- 🚀 Ringan & Cepat - Tanpa overhead TypeScript
- 🔄 Auto Reconnect - Koneksi stabil dengan auto-reconnect
- 📱 Multi Device - Mendukung WhatsApp Multi Device
- 🖼️ Media Support - Kirim gambar, video, audio, dokumen
- 🎯 Interactive Buttons - Tombol interaktif dan katalog produk
- 📊 Group Management - Kelola grup dengan mudah
- 🔐 Session Management - Simpan sesi untuk login otomatis
- 🆓 Gratis Selamanya - Open source dan gratis digunakan
🌐 Links
⚠️ Disclaimer
PENTING: Proyek ini TIDAK berafiliasi dengan WhatsApp Inc. atau Meta Platforms Inc.
🚫 Dilarang untuk:
- Spam massal
- Stalking atau harassment
- Melanggar Terms of Service WhatsApp
- Aktivitas ilegal lainnya
⚖️ Segala bentuk penyalahgunaan adalah tanggung jawab pengguna sepenuhnya.
📦 Instalasi
📋 Requirements
Node.js versi 18 atau lebih tinggi
NPM, Yarn, atau PNPM
🔧 Install Package
# NPM
npm install neroxbails
# Yarn
yarn add neroxbails
# PNPM
pnpm add neroxbails
🚀 Quick Start
1️⃣ Koneksi dengan QR Code (ESM)
import makeWASocket, { Browsers } from 'neroxbails'
const socket = makeWASocket({
browser: Browsers.ubuntu('Safari'),
printQRInTerminal: true
})
console.log('🔍 Scan QR code di terminal untuk login!')
2️⃣ Koneksi dengan QR Code (CommonJS)
const { default: makeWASocket, Browsers } = require('neroxbails')
const socket = makeWASocket({
browser: Browsers.ubuntu('Safari'),
printQRInTerminal: true
})
console.log('🔍 Scan QR code di terminal untuk login!')
⚠️ Catatan: Pastikan
package.json
TIDAK mengandung"type": "module"
untuk CommonJS
3️⃣ Koneksi dengan Pairing Code (Tanpa QR)
import makeWASocket from 'neroxbails'
const socket = makeWASocket({
printQRInTerminal: false
})
// Login tanpa scan QR code
if (!socket.authState.creds.registered) {
const phoneNumber = '628123456789' // Nomor tanpa + atau -
const pairingCode = await socket.requestPairingCode(phoneNumber)
console.log('🔢 Kode Pairing:', pairingCode)
console.log('📱 Masukkan kode di WhatsApp > Linked Devices > Link a Device')
}
🎯 Event Handling
📨 Menangani Pesan Masuk
socket.ev.on('messages.upsert', ({ messages }) => {
const message = messages[0]
if (!message.message) return
console.log('📨 Pesan baru:', message.message)
// Balas pesan otomatis
if (message.message.conversation === 'ping') {
socket.sendMessage(message.key.remoteJid, { text: '🏓 pong!' })
}
})
🔌 Status Koneksi
socket.ev.on('connection.update', ({ connection, lastDisconnect }) => {
if (connection === 'close') {
console.log('❌ Koneksi terputus. Reconnecting...')
// Logic untuk reconnect otomatis
} else if (connection === 'open') {
console.log('✅ Berhasil terhubung ke WhatsApp!')
} else if (connection === 'connecting') {
console.log('🔄 Sedang menghubungkan...')
}
})
💾 Session Management
🔐 Simpan Session untuk Auto Login
import makeWASocket, { useMultiFileAuthState } from 'neroxbails'
// Load session dari folder
const { state, saveCreds } = await useMultiFileAuthState('./auth_session')
const socket = makeWASocket({
auth: state,
printQRInTerminal: true
})
// Auto save credentials
socket.ev.on('creds.update', saveCreds)
console.log('💾 Session akan tersimpan otomatis')
🎨 Contoh Penggunaan Lanjutan
📸 Kirim Media
import fs from 'fs'
// Kirim gambar
await socket.sendMessage(chatId, {
image: fs.readFileSync('./gambar.jpg'),
caption: '🖼️ Ini adalah gambar'
})
// Kirim video
await socket.sendMessage(chatId, {
video: fs.readFileSync('./video.mp4'),
caption: '🎬 Video keren!'
})
// Kirim dokumen
await socket.sendMessage(chatId, {
document: fs.readFileSync('./dokumen.pdf'),
mimetype: 'application/pdf',
fileName: 'Document.pdf'
})
📝 Kirim Pesan dengan Format
// Pesan dengan format
await socket.sendMessage(chatId, {
text: `*Halo!* 👋
_Ini adalah pesan dengan format:_
• Poin 1
• Poin 2
• Poin 3
~Text tercoret~
\`\`\`javascript
console.log("Code block")
\`\`\`
Kunjungi: https://github.com/neroxkira`
})
👥 Manajemen Grup
// Buat grup baru
const group = await socket.groupCreate('Nama Grup 🚀', ['628xxx', '629xxx'])
console.log('📱 Grup dibuat:', group.id)
// Tambah anggota
await socket.groupParticipantsUpdate(groupId, ['628xxx'], 'add')
// Hapus anggota
await socket.groupParticipantsUpdate(groupId, ['628xxx'], 'remove')
// Jadikan admin
await socket.groupParticipantsUpdate(groupId, ['628xxx'], 'promote')
// Update info grup
await socket.groupUpdateDescription(groupId, 'Deskripsi grup baru 📝')
⚡ Optimasi Performance
🗄️ Group Metadata Caching
import NodeCache from 'node-cache'
const groupCache = new NodeCache({
stdTTL: 5 * 60, // 5 menit
useClones: false
})
const socket = makeWASocket({
cachedGroupMetadata: async (jid) => groupCache.get(jid)
})
// Auto update cache
socket.ev.on('groups.update', async ([event]) => {
const metadata = await socket.groupMetadata(event.id)
groupCache.set(event.id, metadata)
})
socket.ev.on('group-participants.update', async (event) => {
const metadata = await socket.groupMetadata(event.id)
groupCache.set(event.id, metadata)
})
📚 Sync Full History
const socket = makeWASocket({
browser: Browsers.ubuntu('Safari'), // Penting untuk full history
syncFullHistory: true, // Download semua riwayat chat
fireInitQueries: true,
})
🛠️ Konfigurasi Lengkap
import makeWASocket, {
Browsers,
useMultiFileAuthState,
fetchLatestBaileysVersion
} from 'neroxbails'
const { version } = await fetchLatestBaileysVersion()
const { state, saveCreds } = await useMultiFileAuthState('./auth')
const socket = makeWASocket({
version,
auth: state,
browser: Browsers.ubuntu('Safari'),
// Koneksi
connectTimeoutMs: 20000,
defaultQueryTimeoutMs: 20000,
keepAliveIntervalMs: 10000,
// QR & Pairing
printQRInTerminal: true,
qrTimeout: 40000,
// Performance
syncFullHistory: true,
markOnlineOnConnect: false,
emitOwnEvents: false,
// Media
generateHighQualityLinkPreview: true,
linkPreviewImageThumbnailWidth: 120,
// Custom functions
getMessage: async (key) => {
// Return message dari database Anda
return await getMessageFromDB(key)
}
})
socket.ev.on('creds.update', saveCreds)
💡 Tips & Best Practices
✅ Do's
- ✅ Selalu handle event
connection.update
untuk auto reconnect - ✅ Simpan session agar tidak perlu login berulang
- ✅ Gunakan cache untuk metadata grup yang sering diakses
- ✅ Handle error dengan try-catch pada setiap operasi
- ✅ Respect rate limits WhatsApp untuk avoid banned
- ✅ Update Baileys secara berkala untuk fix bug terbaru
❌ Don'ts
- ❌ Jangan spam pesan dalam jumlah besar
- ❌ Jangan expose credentials di public repository
- ❌ Jangan abaikan event handling yang penting
- ❌ Jangan lupa backup file session Anda
- ❌ Jangan gunakan untuk aktivitas ilegal
🆘 Troubleshooting
🔍 Masalah Umum
Masalah | Solusi |
---|---|
QR Code tidak muncul | Cek koneksi internet & pastikan printQRInTerminal: true |
Koneksi sering putus | Gunakan keepAliveIntervalMs dan implement auto-reconnect |
Session hilang | Backup folder auth_session secara berkala |
Pesan tidak terkirim | Cek format remoteJid dan pastikan nomor valid |
Error "Cannot find module" | Install ulang dependencies dengan npm install |
🐛 Debug Mode
import pino from 'pino'
const socket = makeWASocket({
logger: pino({ level: 'debug' }),
printQRInTerminal: true
})
🤝 Contributing
Kontribusi sangat diterima! Silakan:
- 🍴 Fork repository ini
- 🌿 Buat branch feature (
git checkout -b feature/AmazingFeature
) - 💾 Commit changes (
git commit -m 'Add some AmazingFeature'
) - 📤 Push ke branch (
git push origin feature/AmazingFeature
) - 🔄 Buat Pull Request
📄 License
Distributed unter der MIT License. Lihat LICENSE
file untuk informasi lebih lanjut.
📈 Stats
[!IMPORTANT]
Daftar lengkap event tersedia di sini.
Sangat penting untuk memahami setiap event yang bisa digunakan.
Contoh penggunaan listener untuk menangani pesan masuk:
import makeWASocket from 'neroxbails'
const sock = makeWASocket()
sock.ev.on('messages.upsert', ({ messages }) => {
console.log('Pesan diterima:', messages)
})
Menangani Event
Baileys menggunakan sistem EventEmitter untuk menangani interaksi WhatsApp secara real-time.
Semua event yang terjadi saat koneksi aktif akan dipancarkan melalui sock.ev.on(...)
, dan kamu bisa menangkap serta meresponsnya sesuai kebutuhan bot kamu.
[!IMPORTANT]
Daftar lengkap event tersedia di sini.
Disarankan untuk memahami struktur tiap event agar integrasi kamu lebih stabil dan efisien.
Contoh: Menangani Pesan Masuk
sock.ev.on('messages.upsert', async ({ messages, type }) => {
const msg = messages[0]
if (!msg.message) return
console.log('Pesan diterima:', msg.message)
})
type
bisa bernilainotify
,append
,replace
, atauremove
.- Kamu biasanya hanya perlu memproses
type === 'notify'
untuk pesan baru yang masuk.
Contoh: Menangani Pembaruan Koneksi
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
if (connection === 'close') {
console.log('Koneksi terputus.')
} else if (connection === 'open') {
console.log('Terhubung ke WhatsApp!')
}
})
- Event ini sangat penting untuk memantau status koneksi socket.
- Jika
connection === 'close'
, Kamu dapat mencoba reconnect otomatis.
Contoh: Deteksi Peserta Masuk/Keluar Grup
sock.ev.on('group-participants.update', async ({ id, participants, action }) => {
if (action === 'add') {
console.log('Anggota baru masuk:', participants)
} else if (action === 'remove') {
console.log('Anggota keluar:', participants)
}
})
id
: JID grupparticipants
: array nomor yang terlibataction
:'add' | 'remove' | 'promote' | 'demote'
Contoh: Pembaruan Metadata Grup
sock.ev.on('groups.update', async (updates) => {
for (let group of updates) {
console.log('Grup diperbarui:', group)
}
})
- Bisa digunakan untuk mendeteksi perubahan nama grup, gambar, deskripsi, dll.
Tips
- Event
messages.update
digunakan untuk mendeteksi status pesan seperti dibaca, diterima, atau gagal. - Event
messages.reaction
digunakan untuk menangkap reaksi (emoji) pada pesan kamu.
[!TIP]
Baileys tidak menyimpan cache pesan secara default.
Untuk menangani event dengan akurat (seperti retry atau polling), gunakangetMessage()
bersamastore
.
Jika kamu butuh event tambahan seperti reaction, presence, atau call offer, tinggal tambahkan listener-nya sesuai struktur BaileysEventMap.
Menyimpan & Memulihkan Sesi
Tentu kamu tidak ingin terus-menerus memindai QR code setiap kali ingin terkoneksi.
Kamu bisa menyimpan kredensial dan menggunakannya kembali saat login berikutnya:
import makeWASocket, { useMultiFileAuthState } from 'neroxbails'
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
// Akan menggunakan kredensial yang tersedia untuk koneksi ulang
// Jika kredensial valid ditemukan, akan langsung login tanpa QR
const sock = makeWASocket({ auth: state })
// Fungsi ini akan dipanggil setiap kali kredensial diperbarui
sock.ev.on('creds.update', saveCreds)
[!IMPORTANT]
useMultiFileAuthState
adalah fungsi utilitas untuk menyimpan state autentikasi dalam satu folder.
Fungsi ini juga dapat dijadikan dasar untuk menulis sistem autentikasi dan penyimpanan kunci pada database SQL atau NoSQL — sangat direkomendasikan untuk sistem berskala produksi.
Apa Isi Folder auth_info_baileys
?
Folder tersebut akan berisi beberapa file .json
seperti:
creds.json
— informasi kredensial utamakeys/
— berisi subfile kunci Signal: pre-keys, session, senderKey, dll.
Folder ini jangan pernah dimodifikasi atau dihapus secara manual.
Perlakukan seperti file token yang sangat sensitif.
Apa yang Terjadi Jika Folder Hilang?
Jika folder auth_info_baileys
dihapus:
- Kamu tidak bisa login ulang tanpa memindai QR lagi
- Semua sesi yang aktif akan invalid
- Signal akan membuat ulang semua sesi enkripsi end-to-end
Backup sangat disarankan jika kamu mengelola sesi penting.
Tips Backup & Restore
- Salin seluruh folder
auth_info_baileys
secara utuh. - Untuk restore, cukup salin folder kembali ke path yang sama sebelum memulai bot.
- Gunakan
.gitignore
agar folder ini tidak ikut di-push ke GitHub:auth_info_baileys/
Menyimpan Berdasarkan ID Pengguna (Multi-Akun)
Jika kamu mengelola banyak sesi pengguna (multi-client), buat direktori penyimpanan berdasarkan ID pengguna:
const { state, saveCreds } = await useMultiFileAuthState(`./sessions/${userId}`)
Dengan cara ini, kamu bisa memisahkan sesi tiap user tanpa saling bentrok.
Rekomendasi: kombinasikan dengan database seperti MongoDB/Redis untuk mencatat mapping antara userId dan path session-nya.
Contoh untuk Memulai
[!NOTE]
Contoh ini juga sudah mencakup penyimpanan kredensial secara otomatis
import makeWASocket, { DisconnectReason, useMultiFileAuthState } from 'neroxbails'
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('Koneksi terputus karena', lastDisconnect.error, ', mencoba sambung ulang:', shouldReconnect)
if (shouldReconnect) {
connectToWhatsApp()
}
} else if (connection === 'open') {
console.log('Koneksi berhasil dibuka')
}
})
sock.ev.on('messages.upsert', async (event) => {
for (const m of event.messages) {
console.log(JSON.stringify(m, undefined, 2))
console.log('Membalas ke', m.key.remoteJid)
await sock.sendMessage(m.key.remoteJid!, { text: 'Hello World' })
}
})
// Menyimpan kredensial setiap kali diperbarui
sock.ev.on('creds.update', saveCreds)
}
connectToWhatsApp()
Contoh Penggunaan useSingleFileAuthState
dan useMongoFileAuthState
import makeWASocket, {
useSingleFileAuthState,
useMongoFileAuthState
} from 'neroxbails'
// Autentikasi menggunakan file tunggal (Single File Auth)
const { state, saveState } = await useSingleFileAuthState('./auth_info_baileys.json')
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
})
sock.ev.on('creds.update', saveState)
// Autentikasi menggunakan MongoDB
import { MongoClient } from 'mongodb'
const connectAuth = async () => {
const client = new MongoClient('mongodb://localhost:27017')
await client.connect()
console.log('Berhasil terhubung ke MongoDB')
const collection = client.db('neroxbails').collection('sessions')
const { state, saveCreds } = await useMongoFileAuthState(collection)
const sock = makeWASocket({
auth: state,
printQRInTerminal: true
})
sock.ev.on('creds.update', saveCreds)
}
connectAuth()
[!IMPORTANT]
Dalam eventmessages.upsert
, sangat disarankan menggunakan perulanganfor (const message of event.messages)
untuk menangani semua pesan dalam array secara individual.
Hal ini mencegah pesan terlewat dan memudahkan logging/debugging.
[!TIP]
Kamu bisa menggabungkan pendekatan penyimpanan sesi (MultiFile
,SingleFile
, atauMongoDB
) dengan sistem login berbasis ID pengguna, sehingga mendukung banyak akun secara paralel.
Mendekripsi Suara Polling
Secara default, suara polling di WhatsApp dienkripsi dan diproses melalui event messages.update
.
import pino from 'pino'
import {
makeInMemoryStore,
getAggregateVotesInPollMessage
} from 'neroxbails'
const logger = pino({ timestamp: () => `,"time":"${new Date().toJSON()}"` }).child({ class: 'neroxbails' })
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: 'Polling Tidak Ditemukan'
}
}
sock.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) return
console.log('Pilihan terpilih:', toCmd)
// Tambahkan aksi lanjutan di sini
}
}
}
})
Penjelasan
store.loadMessage(jid, id)
digunakan untuk mengambil ulang isi pesan polling (karena hasil polling hanya berisi update, bukan isi awal).getAggregateVotesInPollMessage()
menggabungkan seluruhpollUpdates
dan menghasilkan daftar suara lengkap.- Sangat penting menggunakan
getMessage()
yang valid. Jika kamu tidak menyimpan store, dekripsi suara tidak akan berhasil.
[!TIP]
Untuk polling publik, kamu tidak perlu key khusus.
Tapi untuk polling private (atau jika polling berasal dari orang lain), pastikan kamu menyimpan pesan awalnya menggunakan store atau log pesan masuk.
Ringkasan Event Saat Koneksi Pertama
- Saat socket pertama kali terkoneksi, event
connection.update
akan dipicu.
Biasanya status koneksi akan masuk ke'open'
atau'close'
. - Setelah itu, WhatsApp akan mengirimkan riwayat pesan (history chat) melalui event:
messaging-history.set
- Riwayat tersebut berisi pesan-pesan dari sesi sebelumnya, termasuk polling yang belum terjawab.
[!IMPORTANT]
Untuk menangani polling, kamu wajib mengaturgetMessage()
di konfigurasimakeWASocket()
.
Ini memastikan Baileys bisa mendekripsi hasil polling dengan benar.
const sock = makeWASocket({
auth: state,
getMessage: async (key) => await getMessage(key)
})
Mengimplementasikan Data Store
Baileys tidak menyediakan sistem penyimpanan (storage) bawaan untuk chat, kontak, atau pesan.
Namun, tersedia implementasi sederhana menggunakan in-memory store. Store ini akan memantau pembaruan chat, pesan baru, dan perubahan lainnya agar data kamu tetap mutakhir.
[!IMPORTANT]
Sangat disarankan untuk membangun sistem penyimpanan sendiri.
Menyimpan seluruh riwayat chat di RAM akan memakan memori yang besar dan tidak efisien untuk jangka panjang.
Contoh Penggunaan Store
import makeWASocket, { makeInMemoryStore } from 'neroxbails'
// Store akan menyimpan data koneksi WhatsApp dalam memori
const store = makeInMemoryStore({})
// Membaca data dari file (jika tersedia)
store.readFromFile('./baileys_store.json')
// Menyimpan state ke file setiap 10 detik
setInterval(() => {
store.writeToFile('./baileys_store.json')
}, 10_000)
const sock = makeWASocket({})
// Store akan mulai mendengarkan event dari socket ini
// Jika socket diganti, store masih bisa digunakan ulang
store.bind(sock.ev)
sock.ev.on('chats.upsert', () => {
// Akses semua chat tersimpan
console.log('Data chat diterima:', store.chats.all())
})
sock.ev.on('contacts.upsert', () => {
// Akses semua kontak tersimpan
console.log('Kontak diperbarui:', Object.values(store.contacts))
})
Fitur Store
- Menyimpan chat, pesan, dan kontak sementara di memori.
- Mendukung pembacaan dan penulisan dari/ke file JSON.
- Bisa digunakan bersama beberapa koneksi (socket) sekaligus.
- Tersedia fungsi
loadMessages
,loadMessage
, danloadMessageFromContent
.
Kelebihan
- Cepat dan ringan untuk penggunaan kecil-menengah.
- Ideal untuk penggunaan lokal, testing, atau bot personal.
Kekurangan
- Data hilang saat proses dihentikan jika tidak ditulis ke file.
- Tidak cocok untuk data skala besar (ribuan pesan atau kontak).
- Tidak mendukung query kompleks (karena berbasis object literal di RAM).
Rekomendasi Produksi
Untuk sistem besar atau multi-user:
- Gunakan database seperti:
- MongoDB (untuk struktur fleksibel dan load besar)
- Redis (untuk cache cepat)
- PostgreSQL (untuk struktur relasional)
- Sinkronkan event seperti
messages.upsert
,chats.upsert
, dancontacts.upsert
ke penyimpanan permanen. - Gunakan store hanya sebagai cache atau layer middleware sementara.
[!TIP]
Store ini sangat berguna untuk keperluan seperti:
- Menyimpan polling
- Retry pesan
- Melacak status kontak dan grup
- Menyediakan command
.listchat
,.listgroup
, dll. dengan data real-time
Jika kamu menggunakan custom getMessage()
, store ini juga dapat dijadikan referensi lokal untuk mendekripsi polling dan mengirim ulang pesan.
Penjelasan Tentang WhatsApp ID
id
atau biasa disebut jugajid
adalah identitas WhatsApp dari seseorang atau grup yang menjadi tujuan pengiriman pesan.- Format ID harus sesuai dengan jenis akun tujuan:
Jenis Format ID WhatsApp
1. Pengguna Pribadi (User)
Format:
[kode negara][nomor telepon]@s.whatsapp.net
Contoh:
628123456789@s.whatsapp.net
2. Grup WhatsApp
Format:
[timestamp grup dibuat]-[random id]@g.us
Contoh:
1234567890-987654321@g.us
3. Broadcast (Daftar Siaran)
Format:
[timestamp]@broadcast
Contoh:
1685539347@broadcast
4. Status (Story)
Format:
status@broadcast
5. Newsletter (Channel WhatsApp)
Format:
[numeric id]@newsletter
Contoh:
120363025487665599@newsletter
TIP:
Kamu bisa mendapatkanjid
dari:
m.key.remoteJid
groupParticipantsUpdate
messages.upsert
, dll
CAUTION:
Jangan pernah mengubah formatjid
secara manual tanpa validasi.
Salah format bisa menyebabkan errorbad jid
atau pesan tidak terkirim.
Fungsi Utilitas (Utility Functions)
Baileys menyediakan beberapa fungsi utilitas penting yang sangat membantu saat mengembangkan bot:
getContentType(message)
Mengembalikan jenis konten dari pesan (misalnya:imageMessage
,conversation
,buttonsMessage
, dll).getDevice(jid)
Mengembalikan jenis perangkat yang digunakan pengirim (jika tersedia), contoh: Android, iPhone, Web.makeCacheableSignalKeyStore(authState)
Membungkus SignalKeyStore menjadi versi yang lebih efisien dan bisa di-cache, untuk performa autentikasi yang lebih cepat.downloadContentFromMessage(message, type)
Mengunduh media dari pesan (seperti gambar, video, dokumen).type
bisa berupa'image'
,'video'
,'audio'
,'document'
, dll.Contoh penggunaan:
const stream = await downloadContentFromMessage(msg.imageMessage, 'image') const buffer = Buffer.concat([]) for await (const chunk of stream) buffer.push(chunk)
[!NOTE]
Sebagian besar fungsi utilitas tidak dipanggil otomatis — Kamu harus menggunakannya sesuai kebutuhan, terutama saat menangani pesan media, format jid, atau decrypt konten.
Mengirim Pesan
- Semua jenis pesan dapat dikirim menggunakan satu fungsi saja, yaitu
sendMessage()
. - Lihat daftar jenis pesan yang didukung di sini
- Dan semua opsi pengiriman pesan di sini
Contoh:
const jid = '628XXXXXXXXX@s.whatsapp.net' // tujuan
const content = { text: 'Halo, ini pesan dari bot!' } // isi pesan
const options = { quoted: null } // opsi tambahan (misalnya: balasan)
await sock.sendMessage(jid, content, options)
Pesan Non-Media
Pesan Teks
await sock.sendMessage(jid, { text: 'Halo dunia' })
Pesan Balasan (Quote)
await sock.sendMessage(jid, { text: 'Ini balasan pesan kamu' }, { quoted: message })
Mention Pengguna (Tag)
Gunakan @nomor
dalam teks dan sertakan mentions
di payload.
await sock.sendMessage(
jid,
{
text: '@628XXXXXXXXX Hai Nerox!',
mentions: ['628XXXXXXXXX@s.whatsapp.net']
}
)
Meneruskan Pesan (Forward)
Butuh objek pesan (WAMessage
). Bisa didapat dari store atau pesan sebelumnya.
const msg = getMessageFromStore() // Kamu buat sendiri sesuai struktur
await sock.sendMessage(jid, { forward: msg, force: true })
Pesan Interaktif
Tombol Teks (Buttons)
await sock.sendMessage(jid, {
text: 'Pilih salah satu:',
buttons: [
{ buttonId: 'btn_1', buttonText: { displayText: 'Tombol 1' }, type: 1 },
{ buttonId: 'btn_2', buttonText: { displayText: 'Tombol 2' }, type: 1 }
],
footer: 'Contoh footer'
})
Daftar (List Message)
await sock.sendMessage(jid, {
text: 'Pilih dari daftar berikut:',
footer: 'Contoh footer',
title: 'Judul Daftar',
buttonText: 'Buka List',
sections: [
{
title: 'Menu 1',
rows: [
{ title: 'Opsi A', rowId: 'pilih_a' },
{ title: 'Opsi B', rowId: 'pilih_b' }
]
},
{
title: 'Menu 2',
rows: [
{ title: 'Opsi C', rowId: 'pilih_c' }
]
}
]
})
[!TIP]
Kamu bisa menggabungkan semua jenis pesan dengan opsi tambahan sepertiquoted
,mentions
,ephemeralExpiration
, dan lainnya untuk membuat interaksi bot yang lebih kaya dan interaktif.
Lokasi Biasa
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.200000,
degreesLongitude: 106.816666
}
}
)
Lokasi Langsung (Live Location)
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.200000,
degreesLongitude: 106.816666
},
live: true
}
)
Kirim Kontak (vCard)
const vcard =
'BEGIN:VCARD\n' +
'VERSION:3.0\n' +
'FN:Nerox\n' +
'ORG:ZERO DEV;\n' +
'TEL;type=CELL;type=VOICE;waid=628XXXXXXXXX:+62 831-4366-3697\n' +
'END:VCARD'
await sock.sendMessage(
jid,
{
contacts: {
displayName: 'Nerox',
contacts: [{ vcard }]
}
}
)
Pesan Reaksi (Reaction Message)
- Kamu perlu mengirimkan
key
dari pesan yang ingin diberikan reaksi.key
bisa diambil dari store atau menggunakan WAMessageKey.
await sock.sendMessage(
jid,
{
react: {
text: '🔥', // gunakan string kosong '' untuk menghapus reaksi
key: message.key
}
}
)
Pin Pesan (Pin Message)
- Kamu juga perlu memberikan
key
dari pesan yang ingin dipin.
Kamu dapat mengatur durasi pin berdasarkan waktu dalam detik.
Durasi | Detik |
---|---|
24 jam | 86.400 |
7 hari | 604.800 |
30 hari | 2.592.000 |
await sock.sendMessage(
jid,
{
pin: {
type: 1, // 1 untuk pin, 2 untuk unpin
time: 86400,
key: message.key
}
}
)
Menandai Pesan (Keep Message)
- Untuk menyimpan pesan tertentu agar tidak terhapus otomatis.
await sock.sendMessage(
jid,
{
keep: {
key: message.key,
type: 1 // 1 = simpan, 2 = batalkan simpan
}
}
)
Pesan Polling (Poll Message)
- Kirim polling ke grup atau kontak pribadi. Dapat menentukan apakah polling bersifat publik (announcement group).
await sock.sendMessage(
jid,
{
poll: {
name: 'Polling Hari Ini',
values: ['Opsi A', 'Opsi B', 'Opsi C'],
selectableCount: 1,
toAnnouncementGroup: false
}
}
)
Pesan Hasil Polling (Poll Result)
- Kirim hasil polling secara manual jika dibutuhkan. Cocok untuk sistem polling terintegrasi.
await sock.sendMessage(
jid,
{
pollResult: {
name: 'Hasil Polling',
values: [
['Opsi A', 120],
['Opsi B', 350],
['Opsi C', 75]
]
}
}
)
Pesan Panggilan (Call Message)
- Digunakan untuk mengirim notifikasi panggilan, bisa suara atau video.
await sock.sendMessage(
jid,
{
call: {
name: 'Hay',
type: 1 // 1 = suara, 2 = video
}
}
)
Pesan Event (Event Message)
- Cocok untuk mengumumkan acara atau undangan dengan detail lokasi dan waktu.
await sock.sendMessage(
jid,
{
event: {
isCanceled: false, // true jika dibatalkan
name: 'Liburan Bareng!',
description: 'Siapa yang mau ikut?',
location: {
degreesLatitude: 24.121231,
degreesLongitude: 55.1121221,
name: 'Pantai Sanur'
},
startTime: 1715000000,
endTime: 1715086400,
extraGuestsAllowed: true // apakah boleh bawa tamu
}
}
)
Pesan Pemesanan (Order Message)
- Digunakan untuk menampilkan detail pemesanan dari katalog bisnis WhatsApp.
await sock.sendMessage(
jid,
{
order: {
orderId: '574XXX',
thumbnail: 'your_thumbnail',
itemCount: 3,
status: 'INQUIRY', // atau ACCEPTED / DECLINED
surface: 'CATALOG',
message: 'Deskripsi pesanan',
orderTitle: 'Judul Pesanan',
sellerJid: '628xxx@s.whatsapp.net',
token: 'your_token',
totalAmount1000: '150000',
totalCurrencyCode: 'IDR'
}
}
)
Pesan Produk (Product Message)
- Menampilkan detail produk dari katalog bisnis.
await sock.sendMessage(
jid,
{
product: {
productImage: {
url: 'https://your-image.url/image.jpg'
},
productId: 'PRD-001',
title: 'Produk Spesial',
description: 'Deskripsi lengkap produk kamu di sini',
currencyCode: 'IDR',
priceAmount1000: '50000',
retailerId: 'nerox', // opsional
url: 'https://linkproduk.com', // opsional
productImageCount: 1,
firstImageId: 'img-001', // opsional
salePriceAmount1000: '45000',
signedUrl: 'https://your.signed.url' // opsional
},
businessOwnerJid: '628xxx@s.whatsapp.net'
}
)
Pesan Pembayaran (Payment Message)
- Digunakan untuk mengirimkan informasi pembayaran, cocok untuk chatbot belanja.
await sock.sendMessage(
jid,
{
payment: {
note: 'Hi!',
currency: 'IDR',
offset: 0,
amount: '10000',
expiry: 0,
from: '628xxxx@s.whatsapp.net',
image: {
placeholderArgb: '#222222',
textArgb: '#FFFFFF',
subtextArgb: '#AAAAAA'
}
}
}
)
Pesan Undangan Pembayaran (Payment Invite Message)
- Digunakan untuk mengundang pengguna lain melakukan pembayaran.
await sock.sendMessage(
jid,
{
paymentInvite: {
type: 1, // 1 = request, 2 = accept, 3 = decline (sesuaikan sesuai konteks)
expiry: 0
}
}
)
Pesan Undangan Admin Channel (Admin Invite Message)
- Meminta pengguna untuk menjadi admin di saluran (newsletter) kamu.
await sock.sendMessage(
jid,
{
adminInvite: {
jid: '123xxx@newsletter',
name: 'Channel Nerox',
caption: 'Tolong jadi admin channel saya ya!',
expiration: 86400, // dalam detik (24 jam)
jpegThumbnail: Buffer // opsional, bisa berupa buffer gambar
}
}
)
Undangan Grup WhatsApp (Group Invite Message)
- Mengirim undangan ke grup tertentu menggunakan kode undangan.
await sock.sendMessage(
jid,
{
groupInvite: {
jid: '123xxx@g.us',
name: 'Grup Dev Nerox',
caption: 'Ayo gabung ke grup WhatsApp kami!',
code: 'ABCD1234', // kode undangan grup
expiration: 86400,
jpegThumbnail: Buffer // opsional
}
}
)
Pesan Bagikan Nomor Telepon (Share Phone Number)
- Mengirim permintaan eksplisit untuk membagikan nomor telepon pengguna.
await sock.sendMessage(
jid,
{
sharePhoneNumber: {}
}
)
Pesan Permintaan Nomor Telepon (Request Phone Number)
- Meminta pengguna untuk membagikan nomor telepon mereka secara langsung.
await sock.sendMessage(
jid,
{
requestPhoneNumber: {}
}
)
Pesan Balasan Tombol (Button Reply Message)
- Digunakan untuk merespons interaksi tombol yang diklik pengguna. Tipe pesan dibedakan berdasarkan jenis tombol yang digunakan.
Tombol Tipe List
await sock.sendMessage(
jid,
{
buttonReply: {
name: 'Hai',
description: 'Deskripsi pilihan',
rowId: 'pilihan_1'
},
type: 'list'
}
)
Tombol Tipe Plain
await sock.sendMessage(
jid,
{
buttonReply: {
displayText: 'Halo',
id: 'plain_id'
},
type: 'plain'
}
)
Tombol Tipe Template
await sock.sendMessage(
jid,
{
buttonReply: {
displayText: 'Pilih Saya',
id: 'template_id',
index: 1
},
type: 'template'
}
)
Tombol Tipe Interactive (Native Flow)
await sock.sendMessage(
jid,
{
buttonReply: {
body: 'Mau pilih yang mana?',
nativeFlows: {
name: 'menu_options',
paramsJson: JSON.stringify({ id: 'menu_1', description: 'Deskripsi interaktif' }),
version: 1 // bisa juga 2 atau 3
}
},
type: 'interactive'
}
)
Pesan dengan Tombol (Buttons Message)
- Pesan biasa yang disertai hingga 3 tombol untuk respon cepat.
await sock.sendMessage(
jid,
{
text: 'Ini adalah pesan tombol!',
caption: 'Gunakan jika memakai gambar/video',
footer: 'Salam dari Nerox!',
buttons: [
{
buttonId: 'btn1',
buttonText: { displayText: 'Tombol 1' }
},
{
buttonId: 'btn2',
buttonText: { displayText: 'Tombol 2' }
},
{
buttonId: 'btn3',
buttonText: { displayText: 'Tombol 3' }
}
]
}
)
Pesan List Tombol (Buttons List Message)
- Hanya bisa digunakan di chat pribadi, bukan grup.
await sock.sendMessage(
jid,
{
text: 'Ini adalah daftar pilihan!',
footer: 'Dipersembahkan oleh Nerox',
title: 'Judul Daftar Pilihan',
buttonText: 'Klik untuk melihat opsi',
sections: [
{
title: 'Bagian 1',
rows: [
{ title: 'Opsi 1', rowId: 'opsi1' },
{ title: 'Opsi 2', rowId: 'opsi2', description: 'Deskripsi Opsi 2' }
]
},
{
title: 'Bagian 2',
rows: [
{ title: 'Opsi 3', rowId: 'opsi3' },
{ title: 'Opsi 4', rowId: 'opsi4', description: 'Deskripsi Opsi 4' }
]
}
]
}
)
Pesan Daftar Produk dengan Tombol (Buttons Product List Message)
- Hanya dapat digunakan di chat pribadi, bukan grup.
- Menampilkan daftar produk dari katalog bisnis WhatsApp kamu.
await sock.sendMessage(
jid,
{
text: 'Ini adalah daftar produk!',
footer: 'Dikirim oleh Nerox',
title: 'Pilih Produk Unggulan',
buttonText: 'Lihat Daftar Produk',
productList: [
{
title: 'Kategori Produk Utama',
products: [
{ productId: '1234' },
{ productId: '5678' }
]
}
],
businessOwnerJid: '628xxx@s.whatsapp.net',
thumbnail: 'https://example.jpg' // atau buffer gambar
}
)
Pesan Kartu dengan Tombol (Buttons Cards Message)
- Menampilkan beberapa kartu (card) interaktif dengan gambar atau video + tombol.
await sock.sendMessage(
jid,
{
text: 'Isi Utama Pesan',
title: 'Judul Utama',
subtile: 'Subjudul Opsional',
footer: 'Footer Pesan',
cards: [
{
image: { url: 'https://example.jpg' }, // bisa juga Buffer
title: 'Judul Kartu',
body: 'Isi Konten Kartu',
footer: 'Footer Kartu',
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Tombol Cepat',
id: 'ID_TOMBOL_1'
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: 'Kunjungi Website',
url: 'https://www.example.com'
})
}
]
},
{
video: { url: 'https://example.mp4' }, // bisa juga Buffer video
title: 'Judul Kartu Video',
body: 'Deskripsi Konten',
footer: 'Footer Kartu',
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Respon Cepat',
id: 'ID_TOMBOL_2'
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: 'Lihat Selengkapnya',
url: 'https://www.example.com'
})
}
]
}
]
}
)
Pesan Tombol Template (Buttons Template Message)
- Menampilkan tombol dengan tipe URL, panggilan, atau tombol balasan cepat.
await sock.sendMessage(
jid,
{
text: 'Ini adalah pesan template tombol!',
footer: 'Dikirim oleh Nerox',
templateButtons: [
{
index: 1,
urlButton: {
displayText: 'Ikuti Channel',
url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
}
},
{
index: 2,
callButton: {
displayText: 'Hubungi Saya!',
phoneNumber: '628xxxx'
}
},
{
index: 3,
quickReplyButton: {
displayText: 'Balas Cepat',
id: 'id-button-reply'
}
}
]
}
)
Pesan Tombol Interaktif (Interactive Buttons)
- Mendukung berbagai jenis tombol dan dapat digunakan dengan media.
await sock.sendMessage(
jid,
{
text: 'Ini pesan interaktif!',
title: 'Hai!',
subtitle: 'Subjudul di sini',
footer: 'Dikirim oleh Nerox',
interactiveButtons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'Klik Aku!',
id: 'id_kamu'
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: 'Kunjungi Channel',
url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y',
merchant_url: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
})
},
{
name: 'cta_copy',
buttonParamsJson: JSON.stringify({
display_text: 'Salin Link',
copy_code: 'https://whatsapp.com/channel/0029Vag9VSI2ZjCocqa2lB1y'
})
},
{
name: 'cta_call',
buttonParamsJson: JSON.stringify({
display_text: 'Telepon Saya',
phone_number: '628xxxx'
})
},
{
name: 'single_select',
buttonParamsJson: JSON.stringify({
title: 'Pilih Opsi',
sections: [
{
title: 'Pilihan Utama',
highlight_label: 'Rekomendasi',
rows: [
{
header: 'Header 1',
title: 'Opsi 1',
description: 'Deskripsi 1',
id: 'id1'
},
{
header: 'Header 2',
title: 'Opsi 2',
description: 'Deskripsi 2',
id: 'id2'
}
]
}
]
})
}
]
}
)
Versi dengan Media
Gambar
await sock.sendMessage(
jid,
{
image: { url: 'https://example.jpg' },
caption: 'Isi Pesan',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
Video
await sock.sendMessage(
jid,
{
video: { url: 'https://example.mp4' },
caption: 'Isi Video',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
Dokumen
await sock.sendMessage(
jid,
{
document: { url: 'https://example.jpg' },
mimetype: 'image/jpeg',
jpegThumbnail: await sock.resize('https://example.jpg', 320, 320),
caption: 'Isi Dokumen',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
Lokasi
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.2,
degreesLongitude: 106.8,
name: 'Nerox'
},
caption: 'Ayo ke sini!',
title: 'Lokasi Tujuan',
subtitle: 'Subjudul Lokasi',
footer: 'Peta lokasi',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
Produk
await sock.sendMessage(
jid,
{
product: {
productImage: { url: 'https://example.jpg' },
productId: '836xxx',
title: 'Produk Pilihan',
description: 'Deskripsi produk terbaik',
currencyCode: 'IDR',
priceAmount1000: '283000',
retailerId: 'Nerox',
url: 'https://example.com',
productImageCount: 1
},
businessOwnerJid: '628xxx@s.whatsapp.net',
caption: 'Produk baru tersedia!',
title: 'Nama Produk',
subtitle: 'Subjudul Produk',
footer: 'Info Produk',
interactiveButtons: [ /* tombol seperti di atas */ ],
hasMediaAttachment: false
}
)
Mention Status (Status Mentions Message)
- Digunakan untuk membuat status WhatsApp yang menyebut seseorang secara langsung.
await sock.sendStatusMentions(
jid,
{
image: {
url: 'https://example.com.jpg'
},
caption: 'Halo dari Nerox!'
}
)
Pesan Album (Send Album Message)
- Mengirim beberapa gambar atau video sebagai album (sekuens media). Bisa pakai
Buffer
atau URL.
await sock.sendAlbumMessage(
jid,
[
{
image: { url: 'https://example.jpg' },
caption: 'Gambar 1'
},
{
image: Buffer,
caption: 'Gambar 2'
},
{
video: { url: 'https://example.mp4' },
caption: 'Video 1'
},
{
video: Buffer,
caption: 'Video 2'
}
],
{
quoted: message, // opsional, untuk membalas pesan
delay: 2000 // jeda antar media (ms)
}
)
Pesan Toko (Shop Message)
- Digunakan untuk mengarahkan pengguna ke katalog atau produk dalam fitur bisnis WhatsApp.
Teks Saja
await sock.sendMessage(
jid,
{
text: 'Body pesan',
title: 'Judul Toko',
subtitle: 'Subjudul',
footer: 'Powered by Nerox',
shop: {
surface: 1,
id: 'https://example.com'
},
viewOnce: true
}
)
Gambar
await sock.sendMessage(
jid,
{
image: { url: 'https://example.jpg' },
caption: 'Deskripsi produk',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
Video
await sock.sendMessage(
jid,
{
video: { url: 'https://example.mp4' },
caption: 'Tonton videonya!',
title: 'Judul Video',
subtitle: 'Subjudul',
footer: 'Footer',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
Dokumen
await sock.sendMessage(
jid,
{
document: { url: 'https://example.jpg' },
mimetype: 'image/jpeg',
jpegThumbnail: await sock.resize('https://example.jpg', 320, 320),
caption: 'Lampiran dokumen',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Footer',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
Lokasi
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.2000,
degreesLongitude: 106.8166,
name: 'Lokasi Toko'
},
caption: 'Lihat lokasi kami!',
title: 'Judul Lokasi',
subtitle: 'Subjudul',
footer: 'Peta lokasi',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
Produk
await sock.sendMessage(
jid,
{
product: {
productImage: { url: 'https://example.jpg' },
productId: '836xxx',
title: 'Nama Produk',
description: 'Deskripsi produk menarik',
currencyCode: 'IDR',
priceAmount1000: '283000',
retailerId: 'Nerox',
url: 'https://example.com',
productImageCount: 1
},
businessOwnerJid: '628xxx@s.whatsapp.net',
caption: 'Lihat produk unggulan kami!',
title: 'Judul Produk',
subtitle: 'Subjudul Produk',
footer: 'Info produk',
shop: {
surface: 1,
id: 'https://example.com'
},
hasMediaAttachment: false,
viewOnce: true
}
)
Pesan Koleksi (Collection Message)
- Fitur ini digunakan untuk menampilkan koleksi katalog dari bisnis tertentu di WhatsApp.
Teks Saja
await sock.sendMessage(
jid,
{
text: 'Isi pesan',
title: 'Judul Koleksi',
subtitle: 'Subjudul',
footer: 'Dari Nerox',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
viewOnce: true
}
)
Gambar
await sock.sendMessage(
jid,
{
image: { url: 'https://example.jpg' },
caption: 'Koleksi Gambar',
title: 'Judul Koleksi',
subtitle: 'Subjudul',
footer: 'Katalog Nerox',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
hasMediaAttachment: false,
viewOnce: true
}
)
Video
await sock.sendMessage(
jid,
{
video: { url: 'https://example.mp4' },
caption: 'Koleksi Video',
title: 'Judul Video',
subtitle: 'Subjudul',
footer: 'Video Katalog',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
hasMediaAttachment: false,
viewOnce: true
}
)
Dokumen
await sock.sendMessage(
jid,
{
document: { url: 'https://example.jpg' },
mimetype: 'image/jpeg',
jpegThumbnail: await sock.resize('https://example.jpg', 320, 320),
caption: 'Dokumen Katalog',
title: 'Judul Dokumen',
subtitle: 'Subjudul',
footer: 'Lampiran Koleksi',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
hasMediaAttachment: false,
viewOnce: true
}
)
Lokasi
await sock.sendMessage(
jid,
{
location: {
degreesLatitude: -6.2,
degreesLongitude: 106.8,
name: 'Lokasi Bisnis'
},
caption: 'Lihat lokasi koleksi',
title: 'Judul Lokasi',
subtitle: 'Subjudul',
footer: 'Lokasi Katalog',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
hasMediaAttachment: false,
viewOnce: true
}
)
Produk
await sock.sendMessage(
jid,
{
product: {
productImage: { url: 'https://example.jpg' },
productId: '836xxx',
title: 'Nama Produk',
description: 'Deskripsi produk',
currencyCode: 'IDR',
priceAmount1000: '283000',
retailerId: 'Nerox',
url: 'https://example.com',
productImageCount: 1
},
businessOwnerJid: '628xxx@s.whatsapp.net',
caption: 'Koleksi Produk',
title: 'Judul',
subtitle: 'Subjudul',
footer: 'Produk Katalog',
collection: {
bizJid: '628xxx@s.whatsapp.net',
id: 'https://example.com',
version: 1
},
hasMediaAttachment: false,
viewOnce: true
}
)
Mengirim Pesan dengan Pratinjau Link (Link Preview)
- Secara default, WhatsApp Web tidak menampilkan pratinjau link.
- Namun, Baileys menyediakan fungsi pembangkit preview link otomatis.
- Untuk mengaktifkannya, install dulu dependensinya dengan:
yarn add link-preview-js
- Contoh kirim pesan dengan pratinjau link:
await sock.sendMessage(
jid,
{
text: 'Hai! Ini dikirim dari https://github.com/whiskeysockets/baileys'
}
)
Pesan Media (Media Messages)
Mengirim media (gambar, video, audio, stiker) jauh lebih efisien dengan Baileys.
[!NOTE]
Kamu bisa menggunakanBuffer
,{ stream }
, atau{ url }
.
Lihat lebih lengkap di dokumentasi media
[!TIP]
Gunakan stream atau url langsung agar lebih hemat memori.
Pesan GIF (video pendek)
WhatsApp tidak mendukung file
.gif
, maka harus dikirim dalam bentuk.mp4
dengan flaggifPlayback: true
await sock.sendMessage(
jid,
{
video: fs.readFileSync('Media/ma_gif.mp4'),
caption: 'Halo dari GIF!',
gifPlayback: true
}
)
Pesan Video
await sock.sendMessage(
jid,
{
video: { url: './Media/ma_video.mp4' },
caption: 'Ini videonya'
}
)
Pesan Video PTV (Picture to Video / video bulat WA)
await sock.sendMessage(
jid,
{
video: { url: './Media/ma_video.mp4' },
ptv: true
}
)
Pesan Audio
Agar audio kompatibel di semua perangkat, sebaiknya gunakan
ffmpeg
dengan pengaturan berikut:
ffmpeg -i input.mp4 -avoid_negative_ts make_zero -ac 1 output.ogg
await sock.sendMessage(
jid,
{
audio: { url: './Media/audio.ogg' },
mimetype: 'audio/ogg; codecs=opus'
}
)
Pesan Gambar
await sock.sendMessage(
jid,
{
image: { url: './Media/ma_img.png' },
caption: 'Halo dari gambar!'
}
)
Pesan View Once
Fitur View Once memungkinkan media hanya bisa dilihat satu kali.
await sock.sendMessage(
jid,
{
image: { url: './Media/ma_img.png' },
viewOnce: true,
caption: 'Media hanya bisa dilihat sekali'
}
)
Memodifikasi Pesan
Menghapus Pesan (Untuk Semua Orang)
- Digunakan untuk menarik pesan yang sudah dikirim (delete for everyone).
const msg = await sock.sendMessage(jid, { text: 'Halo dunia' })
await sock.sendMessage(jid, { delete: msg.key })
Catatan:
Untuk menghapus pesan hanya untuk diri sendiri, gunakanchatModify
(lihat bagian Modifikasi Chat).
Mengedit Pesan
- Kamu dapat mengedit isi pesan yang telah dikirim sebelumnya, selama masih berada dalam konteks yang diizinkan oleh WhatsApp.
await sock.sendMessage(jid, {
text: 'Teks yang sudah diperbarui di sini',
edit: response.key
})
Memanipulasi Pesan Media
Menambahkan Thumbnail pada Media
- Thumbnail (gambar pratinjau) untuk gambar dan stiker bisa dihasilkan secara otomatis jika kamu menambahkan salah satu dari dependency berikut:
yarn add jimp
# atau
yarn add sharp
- Untuk video, kamu juga bisa menghasilkan thumbnail otomatis, tapi pastikan kamu sudah install
ffmpeg
di sistem kamu.
Contoh penggunaan otomatis biasanya tidak perlu kamu atur manual — Baileys akan meng-generate thumbnail bila dependensi sudah tersedia.
Mengunduh Media dari Pesan (Downloading Media Messages)
Jika kamu ingin menyimpan media yang diterima dari pengguna:
import { createWriteStream } from 'fs'
import { downloadMediaMessage, getContentType } from 'neroxbails'
sock.ev.on('messages.upsert', async ({ messages }) => {
let m = messages[0]
if (!m.message) return // jika tidak ada media atau isi pesan
let messageType = getContentType(m.message) // deteksi tipe pesan (image, video, audio, dll)
if (messageType === 'imageMessage') {
let stream = await downloadMediaMessage(
m,
'stream', // bisa juga 'buffer' kalau ingin langsung di-handle tanpa file
{},
{
logger,
reuploadRequest: sock.updateMediaMessage // agar bisa reupload jika file sudah tidak ada
}
)
let file = createWriteStream('./downloaded-image.jpeg')
stream.pipe(file)
}
})
Re-upload Media ke WhatsApp
Jika media sudah dihapus dari server WhatsApp, kamu bisa minta perangkat pengirim untuk melakukan reupload:
await sock.updateMediaMessage(msg)
Fitur ini penting saat media gagal diunduh karena sudah tidak tersedia di server WhatsApp.
Menolak Panggilan (Reject Call)
- Kamu bisa mendapatkan
callId
dancallFrom
dari eventcall
.
await sock.rejectCall(callId, callFrom)
Mengirim Status ke Chat (Send States in Chat)
Menandai Pesan Dibaca (Reading Messages)
- Kamu harus menandai pesan satu per satu menggunakan key dari
WAMessage
. - Tidak bisa menandai seluruh chat sebagai terbaca secara langsung seperti di WhatsApp Web.
const key = {
remoteJid: '628xxx@s.whatsapp.net',
fromMe: false,
id: 'ABCDEF123456'
}
// bisa juga array untuk banyak pesan sekaligus
await sock.readMessages([key])
Kamu bisa mendapatkan
messageID
dari:
let messageID = message.key.id
Memperbarui Status Kehadiran (Update Presence)
- Status
presence
bisa berupa:available
,unavailable
,composing
,recording
,paused
, dll.
Lihat daftar lengkapnya di sini
await sock.sendPresenceUpdate('available', jid) // online
await sock.sendPresenceUpdate('composing', jid) // mengetik
await sock.sendPresenceUpdate('unavailable', jid) // offline
Catatan:
Jika kamu menggunakan WhatsApp Desktop secara bersamaan, maka WA tidak akan mengirim notifikasi ke perangkat lain.
Kalau kamu ingin tetap terima notifikasi di HP, kamu bisa set status bot jadi offline:
await sock.sendPresenceUpdate('unavailable')
Memodifikasi Chat (Modifying Chats)
WhatsApp menggunakan komunikasi terenkripsi untuk memperbarui status chat atau aplikasi. Beberapa fitur modifikasi sudah didukung oleh Baileys, dan bisa kamu kirim seperti di bawah ini.
PERINGATAN:
Jika kamu salah menggunakan modifikasi ini (misal kirim data invalid), WhatsApp bisa logout semua perangkat dan kamu harus scan ulang QR.
Mengarsipkan Chat (Archive)
let lastMsgInChat = await getLastMessageInChat(jid) // kamu buat fungsi ini sendiri
await sock.chatModify({ archive: true, lastMessages: [lastMsgInChat] }, jid)
Membisukan / Mengaktifkan Notifikasi (Mute / Unmute)
Durasi | Milidetik |
---|---|
Hapus | null |
8 Jam | 86400000 |
7 Hari | 604800000 |
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid) // bisukan 8 jam
await sock.chatModify({ mute: null }, jid) // aktifkan kembali notifikasi
Tandai Sebagai Terbaca / Belum Dibaca
let lastMsgInChat = await getLastMessageInChat(jid)
await sock.chatModify({ markRead: false, lastMessages: [lastMsgInChat] }, jid)
Hapus Pesan Hanya untuk Saya
await sock.chatModify(
{
clear: {
messages: [
{
id: 'ATWYHDNNWU81732J',
fromMe: true,
timestamp: '1654823909'
}
]
}
},
jid
)
Hapus Chat Secara Keseluruhan
let lastMsgInChat = await getLastMessageInChat(jid)
await sock.chatModify({
delete: true,
lastMessages: [
{
key: lastMsgInChat.key,
messageTimestamp: lastMsgInChat.messageTimestamp
}
]
}, jid)
Pin / Unpin Chat
await sock.chatModify({
pin: true // false untuk unpin
}, jid)
Tandai / Hapus Bintang dari Pesan
await sock.chatModify({
star: {
messages: [
{
id: 'messageID',
fromMe: true
}
],
star: true // true: beri bintang, false: hapus bintang
}
}, jid)
Pesan Menghilang Otomatis (Disappearing Messages)
Durasi | Detik (Seconds) |
---|---|
Nonaktif | 0 |
24 Jam | 86400 |
7 Hari | 604800 |
90 Hari | 7776000 |
Aktifkan
await sock.sendMessage(jid, {
disappearingMessagesInChat: 604800 // 7 hari
})
Kirim Pesan dengan Mode Menghilang
await sock.sendMessage(
jid,
{ text: 'halo' },
{ ephemeralExpiration: 604800 }
)
Nonaktifkan
await sock.sendMessage(jid, {
disappearingMessagesInChat: false
})
Menghapus Pesan Tertentu (Clear Messages)
await sock.clearMessage(jid, key, timestamps)
Query Pengguna (User Queries)
Cek Apakah Nomor Terdaftar di WhatsApp
let [result] = await sock.onWhatsApp(jid)
if (result.exists) console.log(`${jid} terdaftar di WhatsApp sebagai ${result.jid}`)
Ambil Riwayat Chat (termasuk grup)
Kamu perlu mengambil pesan paling lama dari chat tersebut
let msg = await getOldestMessageInChat(jid)
await sock.fetchMessageHistory(
50, // maksimal 50 per query
msg.key,
msg.messageTimestamp
)
- Hasilnya akan dikirimkan melalui event
messaging.history-set
Ambil Status WhatsApp (Bio)
let status = await sock.fetchStatus(jid)
console.log('Status: ' + status)
Ambil Foto Profil (Profil, Grup, Channel)
let ppUrl = await sock.profilePictureUrl(jid)
console.log('Foto profil: ' + ppUrl)
Ambil Profil Bisnis (Business Profile)
Cocok untuk akun bisnis WhatsApp, seperti deskripsi & kategori bisnis
let profile = await sock.getBusinessProfile(jid)
console.log('Deskripsi bisnis: ' + profile.description + ', Kategori: ' + profile.category)
Cek Kehadiran Seseorang (Presence: Online / Typing)
sock.ev.on('presence.update', console.log)
await sock.presenceSubscribe(jid)
Ubah Profil
Ubah Status Profil (Bio)
await sock.updateProfileStatus('Halo Dunia!')
Ubah Nama Profil
await sock.updateProfileName('Nerox')
Ubah Foto Profil (termasuk grup)
Sama seperti pesan media, kamu bisa pakai:
{ url }
,Buffer
, atau{ stream }
await sock.updateProfilePicture(jid, { url: './foto-baru.jpeg' })
Hapus Foto Profil (termasuk grup)
await sock.removeProfilePicture(jid)
Grup WhatsApp (Groups)
Untuk mengubah pengaturan grup, kamu harus menjadi admin grup tersebut.
Membuat Grup
let group = await sock.groupCreate('Grup Hebat Nerox', ['1234@s.whatsapp.net', '4564@s.whatsapp.net'])
console.log('Grup berhasil dibuat dengan ID: ' + group.gid)
await sock.sendMessage(group.id, { text: 'Halo semuanya!' })
Tambah / Hapus / Jadikan Admin / Turunkan Admin
await sock.groupParticipantsUpdate(
jid,
['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
'add' // bisa diganti: 'remove', 'promote', 'demote'
)
Ubah Nama Grup
await sock.groupUpdateSubject(jid, 'Nama Baru Grup!')
Ubah Deskripsi Grup
await sock.groupUpdateDescription(jid, 'Deskripsi baru untuk grup ini')
Ubah Pengaturan Grup
// hanya admin yang bisa kirim pesan
await sock.groupSettingUpdate(jid, 'announcement')
// semua anggota bisa kirim pesan
await sock.groupSettingUpdate(jid, 'not_announcement')
// semua anggota bisa ubah info grup (foto, nama, dll.)
await sock.groupSettingUpdate(jid, 'unlocked')
// hanya admin yang bisa ubah info grup
await sock.groupSettingUpdate(jid, 'locked')
Keluar dari Grup
await sock.groupLeave(jid)
Dapatkan Kode Undangan Grup
let code = await sock.groupInviteCode(jid)
console.log('Kode undangan grup: ' + code)
// gabung pakai: https://chat.whatsapp.com/ + code
Reset / Ganti Kode Undangan Grup
let newCode = await sock.groupRevokeInvite(jid)
console.log('Kode undangan baru: ' + newCode)
Gabung Grup dengan Kode Undangan
let response = await sock.groupAcceptInvite('ABC123DEF456')
console.log('Berhasil gabung ke grup: ' + response)
Lihat Info Grup dari Kode Undangan
let response = await sock.groupGetInviteInfo('ABC123DEF456')
console.log('Info grup: ', response)
Lihat Metadata Grup (peserta, nama, deskripsi, dll.)
let metadata = await sock.groupMetadata(jid)
console.log(metadata.id + ', Nama: ' + metadata.subject + ', Deskripsi: ' + metadata.desc)
Gabung Grup dari groupInviteMessage
let response = await sock.groupAcceptInviteV4(jid, groupInviteMessage)
console.log('Gabung ke grup: ' + response)
Lihat Daftar Pengguna yang Minta Gabung
let response = await sock.groupRequestParticipantsList(jid)
console.log(response)
Setujui / Tolak Permintaan Gabung
let response = await sock.groupRequestParticipantsUpdate(
jid,
['abcd@s.whatsapp.net', 'efgh@s.whatsapp.net'],
'approve' // atau 'reject'
)
console.log(response)
Dapatkan Metadata Semua Grup yang Kamu Ikuti
let allGroups = await sock.groupFetchAllParticipating()
console.log(allGroups)
Aktifkan Pesan Sementara di Grup (Ephemeral Message)
Durasi | Detik (Seconds) |
---|---|
Nonaktif | 0 |
24 Jam | 86400 |
7 Hari | 604800 |
90 Hari | 7776000 |
await sock.groupToggleEphemeral(jid, 86400) // contoh: aktif 1 hari
Ubah Mode Penambahan Anggota Grup
await sock.groupMemberAddMode(
jid,
'all_member_add' // atau 'admin_add'
)
Privasi (Privacy)
Blokir / Buka Blokir Pengguna
await sock.updateBlockStatus(jid, 'block') // Blokir pengguna
await sock.updateBlockStatus(jid, 'unblock') // Buka blokir pengguna
Ambil Pengaturan Privasi
let privacySettings = await sock.fetchPrivacySettings(true)
console.log('Pengaturan privasi:', privacySettings)
Lihat Daftar Blokir
let blocklist = await sock.fetchBlocklist()
console.log(blocklist)
Ubah Privasi Terakhir Dilihat (Last Seen)
let value = 'all' // bisa juga: 'contacts', 'contact_blacklist', 'none'
await sock.updateLastSeenPrivacy(value)
Ubah Privasi Status Online
let value = 'all' // atau 'match_last_seen'
await sock.updateOnlinePrivacy(value)
Ubah Privasi Foto Profil
let value = 'all' // bisa juga: 'contacts', 'contact_blacklist', 'none'
await sock.updateProfilePicturePrivacy(value)
Ubah Privasi Status WhatsApp
let value = 'all' // bisa juga: 'contacts', 'contact_blacklist', 'none'
await sock.updateStatusPrivacy(value)
Ubah Privasi Centang Biru (Read Receipts)
let value = 'all' // atau 'none'
await sock.updateReadReceiptsPrivacy(value)
Ubah Privasi Siapa yang Bisa Menambahkan ke Grup
let value = 'all' // bisa juga: 'contacts', 'contact_blacklist'
await sock.updateGroupsAddPrivacy(value)
Ubah Mode Default Pesan Sementara
Durasi dalam detik:
Durasi | Detik (Seconds) |
---|---|
Nonaktif | 0 |
24 Jam | 86400 |
7 Hari | 604800 |
90 Hari | 7776000 |
let ephemeral = 86400
await sock.updateDefaultDisappearingMode(ephemeral)
NEWSLETTER
- Mendapatkan informasi newsletter
const metadata = await sock.newsletterMetadata("invite", "xxxxx")
// atau
const metadata = await sock.newsletterMetadata("jid", "abcd@newsletter")
console.log(metadata)
- Mengubah deskripsi newsletter
await sock.newsletterUpdateDescription("abcd@newsletter", "Deskripsi Baru")
- Mengubah nama newsletter
await sock.newsletterUpdateName("abcd@newsletter", "Nama Baru")
- Mengubah foto profil newsletter
await sock.newsletterUpdatePicture("abcd@newsletter", buffer)
- Menghapus foto profil newsletter
await sock.newsletterRemovePicture("abcd@newsletter")
- Mematikan notifikasi newsletter
await sock.newsletterMute("abcd@newsletter")
- Mengaktifkan kembali notifikasi newsletter
await sock.newsletterUnmute("abcd@newsletter")
- Membuat newsletter baru
const metadata = await sock.newsletterCreate("Nama Newsletter", "Deskripsi Newsletter")
console.log(metadata)
- Menghapus newsletter
await sock.newsletterDelete("abcd@newsletter")
- Mengikuti newsletter
await sock.newsletterFollow("abcd@newsletter")
- Berhenti mengikuti newsletter
await sock.newsletterUnfollow("abcd@newsletter")
- Mengirim reaksi ke pesan di newsletter
const id = "175"
await sock.newsletterReactMessage("abcd@newsletter", id, "🥳")
Ikon AI
// cukup tambahkan "ai: true" pada sendMessage
await sock.sendMessage(id, { text: "Hello World", ai: true })
Broadcast & Status WhatsApp
Kirim Broadcast dan Status (Stories)
- Kamu bisa kirim pesan ke broadcast & story WhatsApp menggunakan
sendMessage()
seperti biasa, tapi dengan tambahan properti khusus:
await sock.sendMessage(
jid,
{
image: {
url: url
},
caption: 'Halo dari broadcast!'
},
{
backgroundColor: '#ffffff', // opsional
font: 'default', // opsional
statusJidList: ['628xxx@s.whatsapp.net'], // daftar kontak yang akan terima status
broadcast: true // aktifkan mode broadcast
}
)
Konten pesan bisa berupa
extendedTextMessage
,imageMessage
,videoMessage
, atauvoiceMessage
.
Lihat semua tipe konten pesan di siniKamu juga bisa menggunakan
backgroundColor
,font
, dan pengaturan lainnya pada opsi pengiriman.
Lihat semua opsi di siniID broadcast biasanya berbentuk:
12345678@broadcast
Ambil Info Daftar Broadcast
let bList = await sock.getBroadcastListInfo('1234@broadcast')
console.log(`Nama list: ${bList.name}, Penerima: ${bList.recipients}`)
Menulis Fungsionalitas Kustom (Custom Functionality)
Baileys dirancang untuk ekstensi & kustomisasi. Kamu tidak perlu fork repo untuk modifikasi — cukup tulis kode kamu sendiri dan panggil lewat API yang disediakan.
Mengaktifkan Log Debug WhatsApp
- Untuk melihat semua pesan mentah dari WhatsApp, aktifkan logger debug saat inisialisasi soket:
import P from 'pino'
const sock = makeWASocket({
logger: P({ level: 'debug' })
})
Ini sangat berguna kalau kamu ingin memahami bagaimana WhatsApp bekerja di balik layar atau mau buat fitur-fitur advance yang gak didokumentasikan.
Bagaimana WhatsApp Berkomunikasi Dengan Kita
TIP:
Kalau kamu ingin mempelajari protokol komunikasi WhatsApp, disarankan untuk memahami tentang LibSignal Protocol dan Noise Protocol.
Contoh Kasus
Misalnya, kamu ingin melacak persentase baterai dari HP yang terhubung.
Kalau kamu mengaktifkan log debug
, maka akan muncul pesan seperti ini di terminal:
{
"level": 10,
"fromMe": false,
"frame": {
"tag": "ib",
"attrs": {
"from": "@s.whatsapp.net"
},
"content": [
{
"tag": "edge_routing",
"attrs": {},
"content": [
{
"tag": "routing_info",
"attrs": {},
"content": {
"type": "Buffer",
"data": [8,2,8,5]
}
}
]
}
]
},
"msg": "communication"
}
Penjelasan Struktur frame
Setiap pesan dari WhatsApp memiliki struktur frame
dengan komponen utama berikut:
tag
— menandakan tipe pesan (contoh:'message'
)attrs
— objek berisi key-value untuk metadata (biasanya mengandung ID pesan)content
— data utama dari isi pesan (contoh: isi teks dari pesan)
Untuk dokumentasi lebih lanjut, lihat struktur WABinary
Daftarkan Callback Untuk Event WebSocket
TIP:
Lihat fungsionMessageReceived
di filesocket.ts
untuk memahami cara event websocket diproses.
// untuk semua pesan dengan tag 'edge_routing'
sock.ws.on('CB:edge_routing', (node) => { })
// untuk pesan dengan tag 'edge_routing' dan atribut id = abcd
sock.ws.on('CB:edge_routing,id:abcd', (node) => { })
// untuk pesan dengan tag 'edge_routing', id = abcd & isi pertama adalah 'routing_info'
sock.ws.on('CB:edge_routing,id:abcd,routing_info', (node) => { })