Skip to main content
WhatsApp uses a specific ID format called JID (Jabber ID) to identify users, groups, broadcast lists, and other entities. Understanding JID formats is essential for working with Baileys.

JID format overview

A JID consists of two parts separated by @:
[identifier]@[server]
  • identifier: The unique identifier (phone number, group ID, etc.)
  • server: The WhatsApp server domain

User JIDs

Regular WhatsApp users are identified by their phone number:
const userJid = '[email protected]'

Format breakdown

Format
string
[country_code][phone_number]@s.whatsapp.net
Example
string
[email protected] for a US number +1 (999) 999-9999

Creating user JIDs

function createUserJid(phoneNumber: string): string {
    // Remove all non-numeric characters
    const cleaned = phoneNumber.replace(/[^0-9]/g, '')
    
    // Add WhatsApp server domain
    return `${cleaned}@s.whatsapp.net`
}

// Examples
const jid1 = createUserJid('+1 (234) 567-8900')  // '[email protected]'
const jid2 = createUserJid('1234567890')         // '[email protected]'
Phone numbers in JIDs must include the country code without the + symbol. Do not include spaces, parentheses, or hyphens.

Validating phone numbers

Check if a phone number exists on WhatsApp:
const [result] = await sock.onWhatsApp('[email protected]')

if (result?.exists) {
    console.log(`Number exists as: ${result.jid}`)
} else {
    console.log('Number does not exist on WhatsApp')
}

Group JIDs

Groups have a different JID format:
const groupJid = '[email protected]'

Format breakdown

Format
string
[group_id]-[creator_timestamp]@g.us

Working with groups

// Create a group
const group = await sock.groupCreate('My Group', [
    '[email protected]',
    '[email protected]'
])

console.log('Group JID:', group.id)
// Output: [email protected]

// Send message to group
await sock.sendMessage(group.id, { text: 'Hello group!' })

// Get group metadata
const metadata = await sock.groupMetadata(group.id)
console.log('Group name:', metadata.subject)
console.log('Participants:', metadata.participants.length)

Broadcast JIDs

Broadcast lists use timestamp-based identifiers:
const broadcastJid = '1234567890@broadcast'

Format breakdown

Format
string
[timestamp_of_creation]@broadcast
Example
string
1234567890@broadcast

Working with broadcasts

// Get broadcast list info
const broadcastInfo = await sock.getBroadcastListInfo('1234567890@broadcast')

console.log('List name:', broadcastInfo.name)
console.log('Recipients:', broadcastInfo.recipients)

// Send to broadcast list
await sock.sendMessage(
    '1234567890@broadcast',
    { text: 'Broadcast message' }
)
WhatsApp Web does not support creating new broadcast lists, but you can send messages to existing lists and delete them.

Story/Status JID

WhatsApp stories (status updates) use a special JID:
const statusJid = 'status@broadcast'

Posting to status

await sock.sendMessage(
    'status@broadcast',
    {
        image: { url: './image.jpg' },
        caption: 'My status update'
    },
    {
        backgroundColor: '#00FF00',
        statusJidList: [
            '[email protected]',
            '[email protected]'
        ],
        broadcast: true
    }
)
await sock.sendMessage(
    'status@broadcast',
    { image: { url: './photo.jpg' } },
    { statusJidList: contacts, broadcast: true }
)

Newsletter JIDs

WhatsApp newsletters (channels) have their own JID format:
const newsletterJid = '123456789@newsletter'

Checking for newsletters

import { isJidNewsletter } from '@whiskeysockets/baileys'

if (isJidNewsletter(jid)) {
    console.log('This is a newsletter')
    // Handle newsletter differently
}

JID utility functions

Baileys provides utility functions for working with JIDs:

Checking JID types

import { 
    isJidUser,
    isJidGroup,
    isJidBroadcast,
    isJidStatusBroadcast,
    isJidNewsletter,
    jidNormalizedUser
} from '@whiskeysockets/baileys'

// Check JID type
if (isJidUser(jid)) {
    console.log('This is a user JID')
}

if (isJidGroup(jid)) {
    console.log('This is a group JID')
}

if (isJidBroadcast(jid)) {
    console.log('This is a broadcast JID')
}

if (isJidStatusBroadcast(jid)) {
    console.log('This is a status broadcast')
}

if (isJidNewsletter(jid)) {
    console.log('This is a newsletter')
}

// Normalize user JID
const normalized = jidNormalizedUser('[email protected]')

Extracting JID components

function parseJid(jid: string) {
    const [identifier, server] = jid.split('@')
    return { identifier, server }
}

const { identifier, server } = parseJid('[email protected]')
console.log('Phone number:', identifier)  // '1234567890'
console.log('Server:', server)             // 's.whatsapp.net'

Message keys and JIDs

Message keys contain JID information:
type WAMessageKey = {
    remoteJid?: string      // Chat where message was sent
    fromMe?: boolean        // Whether message is from you
    id?: string             // Message ID
    participant?: string    // Sender JID (in group chats)
}

Understanding message JIDs

{
    remoteJid: '[email protected]',
    fromMe: true,
    id: 'ABCD1234'
}
In private chats, remoteJid is the other user’s JID.

Determining message sender

function getMessageSender(msg: WAMessage): string {
    if (msg.key.fromMe) {
        return 'me'
    }
    
    // In groups, participant contains the sender
    if (msg.key.participant) {
        return msg.key.participant
    }
    
    // In private chats, remoteJid is the sender
    return msg.key.remoteJid!
}

JID addressing modes

Baileys supports two addressing modes:
enum WAMessageAddressingMode {
    PN = 'pn',   // Phone number mode
    LID = 'lid'  // LID (Linked ID) mode
}
LID addressing is used internally by WhatsApp for multi-device functionality. In most cases, you’ll work with phone number (PN) mode.

Common JID patterns

Here are common patterns for working with JIDs:
// Send message to user
await sock.sendMessage(
    '[email protected]',
    { text: 'Hello!' }
)

// Send message to group
await sock.sendMessage(
    '[email protected]',
    { text: 'Hello group!' }
)

// Reply to message (preserves JID context)
await sock.sendMessage(
    msg.key.remoteJid!,
    { text: 'Reply' },
    { quoted: msg }
)

// Check if message is from group
if (isJidGroup(msg.key.remoteJid)) {
    console.log('Message from group')
}

// Filter out broadcast messages
if (!isJidBroadcast(jid)) {
    // Process non-broadcast message
}

JID validation example

Create a robust JID validator:
function isValidJid(jid: string): boolean {
    const patterns = [
        /^\d+@s\.whatsapp\.net$/,              // User
        /^\d+-\d+@g\.us$/,                       // Group
        /^\d+@broadcast$/,                       // Broadcast
        /^status@broadcast$/,                    // Status
        /^\d+@newsletter$/                       // Newsletter
    ]
    
    return patterns.some(pattern => pattern.test(jid))
}

// Usage
if (isValidJid('[email protected]')) {
    console.log('Valid JID')
}

Best practices

1

Always validate JIDs

Check if a JID exists before sending messages:
const [result] = await sock.onWhatsApp(jid)
if (!result?.exists) {
    throw new Error('JID does not exist')
}
2

Use utility functions

Use Baileys’ built-in functions to check JID types:
if (isJidGroup(jid)) {
    // Handle group
}
3

Store JIDs consistently

Always store JIDs in their full format including the server domain:
// Good: '[email protected]'
// Bad:  '1234567890'
4

Handle group participants correctly

In group messages, use msg.key.participant to identify the sender:
const sender = msg.key.participant || msg.key.remoteJid

Next steps

Sending messages

Learn how to send messages to different JID types

Group management

Work with group JIDs and participants

Build docs developers (and LLMs) love