Skip to main content

Overview

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

JID Format

A JID consists of three parts: user@server[:device]
  • user - The unique identifier (phone number for users, timestamp for groups)
  • server - The server domain
  • device - Optional device ID for multi-device protocol

Server Types

From src/WABinary/jid-utils.ts:8:
type JidServer =
  | 'c.us'           // User (legacy)
  | 'g.us'           // Group
  | 'broadcast'      // Broadcast list
  | 's.whatsapp.net' // User (new)
  | 'call'           // Call
  | 'lid'            // LID (Logged In Device)
  | 'newsletter'     // Newsletter/Channel
  | 'bot'            // Bot
  | 'hosted'         // Hosted PN
  | 'hosted.lid'     // Hosted LID

User JIDs

Standard User Format

[country_code][phone_number]@s.whatsapp.net
Examples:
User JIDs do not include +, (), or -. Only digits followed by @s.whatsapp.net.

Legacy User Format

[country_code][phone_number]@c.us
This format is deprecated but still encountered in some contexts.

Group JIDs

Format

[timestamp]-[creator_suffix]@g.us
Example: [email protected]
  • The first number is typically a Unix timestamp of group creation
  • The second number identifies the group creator

Broadcast List JIDs

Format

[timestamp]@broadcast
Example: 1234567890@broadcast

Stories/Status

From src/WABinary/jid-utils.ts:5:
const STORIES_JID = 'status@broadcast'
Stories use the special JID status@broadcast.

Newsletter JIDs

Format

[id]@newsletter
Newsletters (WhatsApp Channels) use the @newsletter server.

JID Utilities

Baileys provides utility functions for working with JIDs.

jidDecode

Parse a JID into its components: From src/WABinary/jid-utils.ts:55:
function jidDecode(jid: string | undefined): FullJid | undefined

type FullJid = {
  server: JidServer
  user: string
  domainType?: number
  device?: number
}
Example:
import { jidDecode } from '@whiskeysockets/baileys'

const decoded = jidDecode('[email protected]')
// {
//   server: 's.whatsapp.net',
//   user: '19999999999',
//   domainType: 0,
//   device: undefined
// }

const groupDecoded = jidDecode('[email protected]')
// {
//   server: 'g.us',
//   user: '123456789-1234567890',
//   domainType: 0
// }

jidEncode

Construct a JID from components: From src/WABinary/jid-utils.ts:51:
function jidEncode(
  user: string | number | null,
  server: JidServer,
  device?: number,
  agent?: number
): string
Example:
import { jidEncode } from '@whiskeysockets/baileys'

const userJid = jidEncode('19999999999', 's.whatsapp.net')
// '[email protected]'

const groupJid = jidEncode('123456789-1234567890', 'g.us')
// '[email protected]'

// With device ID
const deviceJid = jidEncode('19999999999', 's.whatsapp.net', 0)
// '19999999999:[email protected]'

jidNormalizedUser

Normalize a user JID (convert c.us to s.whatsapp.net): From src/WABinary/jid-utils.ts:113:
function jidNormalizedUser(jid: string | undefined): string
Example:
import { jidNormalizedUser } from '@whiskeysockets/baileys'

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

const alreadyNormal = jidNormalizedUser('[email protected]')
// '[email protected]'

JID Type Checking

Baileys provides functions to check JID types: From src/WABinary/jid-utils.ts:87-108:
// Check if same user
function areJidsSameUser(
  jid1: string | undefined,
  jid2: string | undefined
): boolean

// Check JID types
function isJidGroup(jid: string | undefined): boolean
function isJidBroadcast(jid: string | undefined): boolean
function isJidStatusBroadcast(jid: string): boolean
function isJidNewsletter(jid: string | undefined): boolean
function isPnUser(jid: string | undefined): boolean
function isLidUser(jid: string | undefined): boolean
function isJidBot(jid: string | undefined): boolean
function isJidMetaAI(jid: string | undefined): boolean
Examples:
import { 
  isJidGroup, 
  isJidBroadcast,
  areJidsSameUser,
  isJidStatusBroadcast
} from '@whiskeysockets/baileys'

// Check if group
if (isJidGroup('[email protected]')) {
  console.log('This is a group')
}

// Check if broadcast
if (isJidBroadcast('1234567890@broadcast')) {
  console.log('This is a broadcast list')
}

// Check if status/story
if (isJidStatusBroadcast('status@broadcast')) {
  console.log('This is a status update')
}

// Compare users (ignoring device ID)
if (areJidsSameUser(
  '19999999999:[email protected]',
  '[email protected]'
)) {
  console.log('Same user, different device')
}

Special JIDs

From src/WABinary/jid-utils.ts:1-6:
const S_WHATSAPP_NET = '@s.whatsapp.net'
const OFFICIAL_BIZ_JID = '[email protected]'
const SERVER_JID = '[email protected]'
const PSA_WID = '[email protected]'
const STORIES_JID = 'status@broadcast'
const META_AI_JID = '[email protected]'

Meta AI Bot

import { isJidBot, META_AI_JID } from '@whiskeysockets/baileys'

if (isJidBot(META_AI_JID)) {
  console.log('This is Meta AI')
}

Multi-Device Protocol

Device IDs

In multi-device protocol, JIDs can include a device ID:
19999999999:[email protected]
  • :0 is the primary device (phone)
  • :1, :2, etc. are companion devices

Transferring Device ID

From src/WABinary/jid-utils.ts:123:
function transferDevice(fromJid: string, toJid: string): string
Example:
import { transferDevice } from '@whiskeysockets/baileys'

const newJid = transferDevice(
  '19999999999:[email protected]',  // From device 1
  '[email protected]'      // To another user
)
// '17777777777:[email protected]'

LID (Logged In Device)

LID is a privacy-focused identifier used in some contexts:
[lid_id]@lid

LID Utilities

import { isLidUser } from '@whiskeysockets/baileys'

if (isLidUser('abc123@lid')) {
  console.log('This is a LID user')
}

Practical Examples

Sending to a User

const phoneNumber = '19999999999'
const jid = `${phoneNumber}@s.whatsapp.net`

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

Extracting Phone Number

import { jidDecode } from '@whiskeysockets/baileys'

function getPhoneNumber(jid: string): string | undefined {
  const decoded = jidDecode(jid)
  return decoded?.server === 's.whatsapp.net' 
    ? decoded.user 
    : undefined
}

const phone = getPhoneNumber('[email protected]')
// '19999999999'

Validating Group JID

import { isJidGroup } from '@whiskeysockets/baileys'

function isValidGroupJid(jid: string): boolean {
  return isJidGroup(jid) && jid.includes('-')
}

Filtering Message Types

import { isJidNewsletter, isJidGroup } from '@whiskeysockets/baileys'

sock.ev.on('messages.upsert', ({ messages }) => {
  for (const msg of messages) {
    const jid = msg.key.remoteJid!
    
    if (isJidGroup(jid)) {
      console.log('Group message')
    } else if (isJidNewsletter(jid)) {
      console.log('Newsletter message')
    } else {
      console.log('Private message')
    }
  }
})

JID Domain Types

From src/WABinary/jid-utils.ts:20:
enum WAJIDDomains {
  WHATSAPP = 0,
  LID = 1,
  HOSTED = 128,
  HOSTED_LID = 129
}
Domain types are used internally to route messages to the correct server infrastructure.

Best Practices

JID Handling Tips:
  1. Always validate - Use type checking functions before operations
  2. Normalize user JIDs - Use jidNormalizedUser for consistency
  3. Handle device IDs - Use areJidsSameUser to compare users across devices
  4. Never hardcode formats - Use jidEncode to construct JIDs
  5. Check types - Use isJidGroup, isJidBroadcast, etc. before group operations
  6. Store normalized JIDs - Always normalize before storing in database

Common Mistakes

Avoid These Mistakes:❌ Including + in JIDs: [email protected]✅ Use digits only: [email protected]❌ Mixing server types: Using c.us for new messages✅ Use s.whatsapp.net for users: jidNormalizedUser(jid)❌ String concatenation: phoneNumber + '@s.whatsapp.net'✅ Use jidEncode: jidEncode(phoneNumber, 's.whatsapp.net')

See Also

Build docs developers (and LLMs) love