Skip to main content

Quickstart

This guide will walk you through creating a basic WhatsApp bot that connects to WhatsApp and responds to messages.

Basic connection example

Here’s a complete working example that connects to WhatsApp and handles basic events:
import makeWASocket, { DisconnectReason, useMultiFileAuthState } from '@whiskeysockets/baileys'
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('connection closed due to ', lastDisconnect?.error, ', reconnecting ', shouldReconnect)
      
      // reconnect if not logged out
      if (shouldReconnect) {
        connectToWhatsApp()
      }
    } else if (connection === 'open') {
      console.log('opened connection')
    }
  })
  
  sock.ev.on('messages.upsert', async ({ messages }) => {
    for (const m of messages) {
      console.log(JSON.stringify(m, undefined, 2))
      
      console.log('replying to', m.key.remoteJid)
      await sock.sendMessage(m.key.remoteJid!, { text: 'Hello World!' })
    }
  })
  
  // save credentials when updated
  sock.ev.on('creds.update', saveCreds)
}

connectToWhatsApp()
When you run this code for the first time, a QR code will be printed in your terminal. Scan it with WhatsApp on your phone to authenticate.

How it works

Let’s break down the key components:
1

Authentication state

The useMultiFileAuthState function manages your authentication credentials in a folder called auth_info_baileys. This allows you to stay logged in across restarts.
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
2

Create socket connection

makeWASocket creates a connection to WhatsApp. The printQRInTerminal: true option displays the QR code in your terminal for easy scanning.
const sock = makeWASocket({
  auth: state,
  printQRInTerminal: true
})
3

Handle connection updates

The connection.update event fires when the connection state changes. You should handle reconnection logic here.
sock.ev.on('connection.update', (update) => {
  // Handle connection open, close, etc.
})
4

Process messages

The messages.upsert event fires when new messages arrive. Loop through all messages in the array to handle them.
sock.ev.on('messages.upsert', async ({ messages }) => {
  for (const m of messages) {
    // Process each message
  }
})
5

Save credentials

Always save credentials when they’re updated to prevent issues with message delivery.
sock.ev.on('creds.update', saveCreds)

Authentication methods

Baileys supports two authentication methods:

QR code (default)

Scan a QR code with your phone:
const sock = makeWASocket({
  auth: state,
  printQRInTerminal: true
})

Pairing code

Use a pairing code instead of QR code:
const sock = makeWASocket({
  auth: state,
  printQRInTerminal: false
})

if (!sock.authState.creds.registered) {
  const phoneNumber = 'YOUR_PHONE_NUMBER' // without + or () or -, just numbers
  const code = await sock.requestPairingCode(phoneNumber)
  console.log(`Pairing code: ${code}`)
}
Phone numbers must be in the format [country code][number] with no special characters. For example: 19999999999 for a US number.

Sending different message types

Once connected, you can send various types of messages:

Text messages

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

Images

import fs from 'fs'

await sock.sendMessage(jid, {
  image: fs.readFileSync('./image.jpg'),
  caption: 'Check out this image!'
})

Videos

await sock.sendMessage(jid, {
  video: { url: './video.mp4' },
  caption: 'Amazing video',
  gifPlayback: false
})

Locations

await sock.sendMessage(jid, {
  location: {
    degreesLatitude: 24.121231,
    degreesLongitude: 55.1121221
  }
})

Reactions

await sock.sendMessage(jid, {
  react: {
    text: '👍',
    key: message.key
  }
})
You can send media using a file path, URL, or Buffer. For large files, using { url: 'path' } or streams is recommended to save memory.

Running the example

The Baileys repository includes a comprehensive example file that demonstrates most common use cases:
1

Clone the repository

git clone https://github.com/WhiskeySockets/Baileys.git
cd Baileys
2

Install dependencies

yarn install
3

Run the example

yarn example
Or with optional flags:
yarn example --use-pairing-code  # Use pairing code instead of QR
yarn example --do-reply          # Auto-reply to messages

Important concepts

WhatsApp IDs (JIDs)

WhatsApp uses unique identifiers called JIDs for users and groups:
  • Individual chats: [country code][phone number]@s.whatsapp.net (e.g., [email protected])
  • Group chats: [group id]@g.us (e.g., [email protected])
  • Broadcast lists: [timestamp]@broadcast
  • Status updates: status@broadcast

Event handling

Baileys uses EventEmitter for all events. The main events you’ll work with:
  • connection.update - Connection state changes
  • creds.update - Authentication credentials updated (always save these!)
  • messages.upsert - New messages received
  • messages.update - Message status changed (delivered, read, deleted)
  • presence.update - User typing or online status
  • chats.update - Chat metadata changed
  • groups.update - Group settings changed
For a complete list of events, see the BaileysEventMap documentation.

Session persistence

The useMultiFileAuthState function saves authentication data to a local folder. This is fine for development but you should implement a database-backed solution for production:
Always save updated credentials (creds.update event) and key states. Failing to do so will prevent messages from reaching recipients and cause authentication issues.

Next steps

Event handling

Learn about all available events

Message types

Explore all message content types

Socket configuration

Configure advanced socket options

GitHub examples

View the complete example file

Build docs developers (and LLMs) love