WhatsApp uses a specific ID format called JID (Jabber ID) to identify users, groups, broadcast lists, and other entities. Understanding JIDs is essential for sending messages and managing chats.
A JID consists of three parts: user@server or user:device@server
// Basic format
[user]@[server]
// With device ID (multi-device)
[user]:[device]@[server]
// Examples
1234567890@s.whatsapp.net // Regular user
1234567890:0@s.whatsapp.net // User with device ID
123456789-987654321@g.us // Group
status@broadcast // Status/Stories
JID Types
Individual Users
Individual user JIDs use the s.whatsapp.net server:
// Format: [country code][phone number]@s.whatsapp.net
const userJid = '[email protected]'
// Send message to user
await sock.sendMessage(userJid, { text: 'Hello!' })
User JIDs must include the country code without the + symbol. For example, a US number +1 (234) 567-8900 becomes [email protected].
Groups
Group JIDs use the g.us server and follow this format:
// Format: [timestamp]-[random]@g.us
const groupJid = '[email protected]'
// Send message to group
await sock.sendMessage(groupJid, { text: 'Hello group!' })
Broadcast Lists
Broadcast lists use a timestamp-based format:
// Format: [timestamp]@broadcast
const broadcastJid = '1234567890@broadcast'
// Send to broadcast list
await sock.sendMessage(broadcastJid, { text: 'Broadcast message' })
Status/Stories
Status updates use a special broadcast JID:
// Fixed JID for status
const statusJid = 'status@broadcast'
// Send status update
await sock.sendMessage(statusJid, {
image: { url: './image.jpg' },
caption: 'My status update'
})
Newsletters
Newsletters (channels) use the newsletter server:
// Format: [newsletter_id]@newsletter
const newsletterJid = '1234567890@newsletter'
LID (Local Identity)
LID is used for privacy-focused identifiers:
// Format: [lid]@lid
const lidJid = 'ABC123@lid'
JID Utilities
Baileys provides utility functions for working with JIDs:
jidDecode
Parse a JID into its components:
import { jidDecode } from '@whiskeysockets/baileys'
const jid = '1234567890:[email protected]'
const decoded = jidDecode(jid)
console.log(decoded)
// {
// user: '1234567890',
// server: 's.whatsapp.net',
// device: 0,
// domainType: 0
// }
jidEncode
Construct a JID from components:
import { jidEncode } from '@whiskeysockets/baileys'
const jid = jidEncode('1234567890', 's.whatsapp.net', 0)
console.log(jid) // '1234567890:[email protected]'
// Without device
const simpleJid = jidEncode('1234567890', 's.whatsapp.net')
console.log(simpleJid) // '[email protected]'
Type Checking Functions
Check what type of JID you’re working with:
import {
isJidGroup,
isJidBroadcast,
isJidStatusBroadcast,
isJidNewsletter,
isLidUser,
isPnUser,
areJidsSameUser
} from '@whiskeysockets/baileys'
// Check if JID is a group
if (isJidGroup('[email protected]')) {
console.log('This is a group')
}
// Check if JID is a broadcast
if (isJidBroadcast('1234567890@broadcast')) {
console.log('This is a broadcast list')
}
// Check if JID is status broadcast
if (isJidStatusBroadcast('status@broadcast')) {
console.log('This is the status broadcast')
}
// Check if JID is a newsletter
if (isJidNewsletter('1234567890@newsletter')) {
console.log('This is a newsletter')
}
// Check if JID is a LID user
if (isLidUser('ABC123@lid')) {
console.log('This is a LID user')
}
// Check if JID is a regular user
if (isPnUser('[email protected]')) {
console.log('This is a regular user')
}
// Compare if two JIDs belong to same user
if (areJidsSameUser('1234567890:[email protected]', '1234567890:[email protected]')) {
console.log('Same user, different devices')
}
Multi-Device JIDs
WhatsApp’s multi-device feature uses device IDs in JIDs:
Device ID 0 always refers to the main phone. Linked devices start from 1.
JID Server Types
Different servers indicate different entity types:
| Server | Type | Example |
|---|
s.whatsapp.net | Individual user | [email protected] |
g.us | Group | [email protected] |
broadcast | Broadcast list / Status | 1234567890@broadcast |
newsletter | Newsletter/Channel | 1234567890@newsletter |
lid | Local identity (LID) | ABC123@lid |
c.us | User (alternative) | [email protected] |
call | Call-related | Used internally |
Extract phone number from a user JID:
import { jidDecode } from '@whiskeysockets/baileys'
function getPhoneNumber(jid: string): string | undefined {
const decoded = jidDecode(jid)
if (decoded?.server === 's.whatsapp.net' || decoded?.server === 'c.us') {
return decoded.user
}
return undefined
}
const phone = getPhoneNumber('[email protected]')
console.log(phone) // '1234567890'
Normalizing JIDs
Normalize JIDs for consistent comparison:
import { jidNormalizedUser } from '@whiskeysockets/baileys'
// Converts c.us to s.whatsapp.net
const normalized = jidNormalizedUser('[email protected]')
console.log(normalized) // '[email protected]'
Message Keys
Every message has a key that includes JID information:
import { WAMessageKey } from '@whiskeysockets/baileys'
interface WAMessageKey {
remoteJid: string // Who the chat is with
fromMe: boolean // Did I send this message?
id: string // Unique message ID
participant?: string // Who sent it (in groups)
}
// Example: Message in a group
const messageKey: WAMessageKey = {
remoteJid: '[email protected]', // Group JID
fromMe: false,
id: 'ABC123',
participant: '[email protected]' // Who sent it
}
// Example: Direct message
const dmKey: WAMessageKey = {
remoteJid: '[email protected]',
fromMe: true,
id: 'XYZ789'
// No participant in direct messages
}
Group Participant JIDs
In group messages, distinguish between chat JID and participant JID:
sock.ev.on('messages.upsert', ({ messages }) => {
for (const msg of messages) {
const chatJid = msg.key.remoteJid // Group JID
const senderJid = msg.key.participant // Who sent it
if (isJidGroup(chatJid)) {
console.log(`Message in group ${chatJid}`)
console.log(`Sent by ${senderJid}`)
}
}
})
Checking if JID Exists
Verify if a phone number has WhatsApp:
// Check if number exists on WhatsApp
const phoneNumber = '1234567890'
const jid = `${phoneNumber}@s.whatsapp.net`
const [result] = await sock.onWhatsApp(jid)
if (result?.exists) {
console.log(`JID ${result.jid} exists on WhatsApp`)
} else {
console.log('Number not on WhatsApp')
}
Special JIDs
Baileys defines constants for special JIDs:
import {
S_WHATSAPP_NET,
OFFICIAL_BIZ_JID,
SERVER_JID,
PSA_WID,
STORIES_JID,
META_AI_JID
} from '@whiskeysockets/baileys'
console.log(S_WHATSAPP_NET) // '@s.whatsapp.net'
console.log(OFFICIAL_BIZ_JID) // '[email protected]' (WhatsApp Business)
console.log(STORIES_JID) // 'status@broadcast'
console.log(META_AI_JID) // '[email protected]' (Meta AI)
JID Best Practices
Always validate JIDs
Check if a JID is valid before using it:import { jidDecode } from '@whiskeysockets/baileys'
function isValidJid(jid: string): boolean {
return jidDecode(jid) !== undefined
}
Use type checking functions
Don’t parse JIDs manually - use provided utilities:// Good
if (isJidGroup(jid)) {
// Handle group
}
// Bad
if (jid.endsWith('@g.us')) {
// Don't do this
}
Store JIDs consistently
Always store JIDs in their canonical form:import { jidNormalizedUser } from '@whiskeysockets/baileys'
const normalizedJid = jidNormalizedUser(jid)
await db.saveContact(normalizedJid)
Domain Types
JIDs can have different domain types for privacy:
import { WAJIDDomains } from '@whiskeysockets/baileys'
enum WAJIDDomains {
WHATSAPP = 0, // Regular WhatsApp
LID = 1, // Local identity
HOSTED = 128, // Hosted account
HOSTED_LID = 129 // Hosted LID
}
Complete JID Example
import {
jidDecode,
jidEncode,
isJidGroup,
isJidBroadcast,
areJidsSameUser
} from '@whiskeysockets/baileys'
function analyzeJid(jid: string) {
const decoded = jidDecode(jid)
if (!decoded) {
console.log('Invalid JID')
return
}
console.log('User:', decoded.user)
console.log('Server:', decoded.server)
console.log('Device:', decoded.device)
if (isJidGroup(jid)) {
console.log('Type: Group')
} else if (isJidBroadcast(jid)) {
console.log('Type: Broadcast')
} else {
console.log('Type: Individual')
}
}
analyzeJid('1234567890:[email protected]')
analyzeJid('[email protected]')
analyzeJid('status@broadcast')