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.
A JID consists of two parts separated by @:
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:
[country_code][phone_number]@s.whatsapp.net
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:
[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'
[timestamp_of_creation]@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
}
)
Image status
Video status
Text status
await sock . sendMessage (
'status@broadcast' ,
{ image: { url: './photo.jpg' } },
{ statusJidList: contacts , broadcast: true }
)
await sock . sendMessage (
'status@broadcast' ,
{ video: { url: './video.mp4' } },
{ statusJidList: contacts , broadcast: true }
)
await sock . sendMessage (
'status@broadcast' ,
{ text: 'My text status' },
{
statusJidList: contacts ,
broadcast: true ,
backgroundColor: '#FF5733' ,
font: 2
}
)
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] ' )
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
In private chats, remoteJid is the other user’s JID. In group chats, remoteJid is the group JID and participant is the sender’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
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' )
}
Use utility functions
Use Baileys’ built-in functions to check JID types: if ( isJidGroup ( jid )) {
// Handle group
}
Store JIDs consistently
Always store JIDs in their full format including the server domain:
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