Skip to Content
Utilities

Utilities

Zaileys exports a handful of pure helpers used internally — useful for building your own logic. They are plain functions with no client dependency, so you can import and call them anywhere:

import { normalizeJid, computeStaticId, extractLinks, loadMedia, chunk } from 'zaileys'

These are the same helpers zaileys uses to build each message context. For example, computeUniqueId / computeStaticId produce the exact uniqueId / staticId values you see on a MessageContext, and senderDeviceOf produces its senderDevice. See Message Payload.

JID helpers

Functions for inspecting and normalizing WhatsApp JIDs (the user@server addresses used for chats, users, and groups).

MethodSignatureDescription
isJid(value)(value: string) => booleantrue if the string ends with a known WhatsApp server suffix (@s.whatsapp.net, @g.us, @lid, @newsletter, @broadcast, @c.us).
isLidJid(jid)(jid: string) => booleantrue if the JID is a LID address (@lid).
isPnJid(jid)(jid: string) => booleantrue if the JID is a phone-number address (@s.whatsapp.net or @c.us).
normalizeJid(jid)(jid: string | null | undefined) => string | nullNormalizes a JID — strips the device suffix and canonicalizes the user. Returns null for empty/invalid input.
jidToPhone(jid)(jid: string) => stringDigits-only phone number from a phone JID. Returns '' for groups, LIDs, and anything that is not a @s.whatsapp.net / @c.us JID.
phoneToJid(phone)(phone: string) => stringBuilds a user JID from a phone number or digits (non-digit characters are stripped).
import { isJid, isLidJid, isPnJid, normalizeJid, jidToPhone, phoneToJid } from 'zaileys' isJid('628123@s.whatsapp.net') // true isJid('hello') // false isLidJid('12345@lid') // true isPnJid('628123@s.whatsapp.net') // true // Strip a device suffix to get the canonical user JID normalizeJid('628123:7@s.whatsapp.net') // '628123@s.whatsapp.net' // Convert between phones and JIDs jidToPhone('628123@s.whatsapp.net') // '628123' jidToPhone('12345@g.us') // '' (groups have no phone) phoneToJid('+62 812-3') // '628123@s.whatsapp.net'

Baileys JID helpers

The lower-level JID helpers from Baileys are re-exported from 'zaileys', so you can import them directly without depending on baileys. They are pure functions.

MethodSignatureDescription
jidDecode(jid)(jid: string) => { user: string; server: string; device?: number } | undefinedDecode a JID into its parts. undefined for invalid input.
jidEncode(user, server, device?)(user: string | null, server: string, device?: number) => stringBuild a JID string from parts.
jidNormalizedUser(jid)(jid: string) => stringNormalized user JID (strips the device segment).
areJidsSameUser(a, b)(a?: string, b?: string) => booleantrue if both JIDs are the same user, ignoring device/LID.
isJidGroup(jid)(jid?: string) => booleantrue for a group JID (@g.us).
isJidBroadcast(jid)(jid?: string) => booleantrue for a broadcast JID (@broadcast).
isJidNewsletter(jid)(jid?: string) => booleantrue for a newsletter/channel JID (@newsletter).
isLidUser(jid)(jid?: string) => booleantrue for a LID user (@lid).
isPnUser(jid)(jid?: string) => booleantrue for a phone-number user (@s.whatsapp.net).
getDevice(jid)(jid: string) => stringDevice kind decoded from the JID.
import { jidDecode, jidEncode, jidNormalizedUser, areJidsSameUser, isJidGroup, isJidNewsletter, isLidUser, isPnUser, getDevice, } from 'zaileys' jidDecode('628123:7@s.whatsapp.net') // { user: '628123', server: 's.whatsapp.net', device: 7 } jidEncode('628123', 's.whatsapp.net') // '628123@s.whatsapp.net' jidNormalizedUser('628123:7@s.whatsapp.net') // '628123@s.whatsapp.net' areJidsSameUser('628123:7@s.whatsapp.net', '628123@s.whatsapp.net') // true isJidGroup('12345@g.us') // true isPnUser('628123@s.whatsapp.net') // true isLidUser('12345@lid') // true

LID ↔ phone (async, on the client)

These two are client.* methods, not pure functions — they resolve through WhatsApp’s LID mapping and may hit the network, so they need a connected socket and return a Promise.

MethodSignatureDescription
client.lidToPn(lid)(lid: string) => Promise<string | null>Resolve a @lid JID to its phone-number JID. null if unknown.
client.pnToLid(pn)(pn: string) => Promise<string | null>Resolve a phone-number JID to its @lid JID. null if unknown.
import { Client } from 'zaileys' const client = new Client() await client.connect() await client.lidToPn('12345@lid') // '628123@s.whatsapp.net' | null await client.pnToLid('628123@s.whatsapp.net') // '12345@lid' | null

ID hashers

Deterministic 16-character UPPERCASE hex hashers. They are pure: the same input always yields the same id, with no randomness or counters.

MethodSignatureDescription
computeUniqueId(key)(key: WAMessageKey) => stringPer-message id derived from the message key (remoteJid + id + fromMe). Matches a context’s uniqueId.
computeStaticId(roomId, senderId)(roomId: string | null, senderId: string) => stringStable id per (room, sender) pair — same room + same sender always hash to the same value. Matches a context’s staticId.
import { computeUniqueId, computeStaticId } from 'zaileys' const uid = computeUniqueId({ remoteJid: '628123@s.whatsapp.net', id: 'ABCD', fromMe: false }) // e.g. 'A1B2C3D4E5F60718' // Stable per (room, sender) — useful as a dedup / per-user key const sid = computeStaticId('12345@g.us', '628123@s.whatsapp.net') computeStaticId('12345@g.us', '628123@s.whatsapp.net') === sid // true
import { Client, computeStaticId } from 'zaileys' const client = new Client() const seen = new Set<string>() client.on('text', (ctx) => { // ctx.staticId already equals this value const key = computeStaticId(ctx.roomId, ctx.senderId) if (seen.has(key)) return // already handled this sender in this room seen.add(key) })

Text & device

MethodSignatureDescription
extractLinks(text)(text: string) => string[]Extracts all http(s) URLs from a string. Trailing punctuation (.,;:!?) is trimmed off each URL. Returns [] when none are found.
senderDeviceOf(jid)(jid: string) => 'android' | 'ios' | 'web' | 'desktop' | 'unknown'Decodes the originating device from a JID’s device segment.
epochSecondsToMs(value)(value: unknown) => numberConverts an epoch-seconds timestamp to milliseconds. Accepts number, string, bigint, or a Long-like { low, high } / { toNumber() } object. Returns 0 for invalid or non-positive input.
import { extractLinks, senderDeviceOf, epochSecondsToMs } from 'zaileys' extractLinks('see https://zaileys.dev and http://example.com.') // ['https://zaileys.dev', 'http://example.com'] senderDeviceOf('628123:2@s.whatsapp.net') // 'ios' senderDeviceOf('628123@s.whatsapp.net') // 'android' epochSecondsToMs(1718000000) // 1718000000000 epochSecondsToMs('0') // 0

Media

MethodSignatureDescription
loadMedia(src, opts?)(src: string | Buffer | URL, opts?: { timeoutMs?: number }) => Promise<{ buffer: Buffer; mime: string; size: number }>Resolves any media source into a buffer: fetches http(s) URLs, reads local file paths and file: URLs, or passes a Buffer through. Detects the MIME type and reports the byte size. Throws ZaileysBuilderError (MEDIA_LOAD_FAILED) on failure. Default fetch timeout is 30 000 ms.
detectMimeFromBuffer(buffer)(buffer: Buffer) => Promise<string>Sniffs the MIME type from a buffer’s magic bytes. Falls back to application/octet-stream for empty/unknown buffers.
import { loadMedia, detectMimeFromBuffer } from 'zaileys' // From a URL (fetched), a path (read), or a Buffer (passed through) const { buffer, mime, size } = await loadMedia('https://example.com/photo.jpg') console.log(mime, size) // 'image/jpeg' 51234 await loadMedia('./assets/voice.ogg') // local path await loadMedia(Buffer.from([0xff, 0xd8])) // existing buffer await detectMimeFromBuffer(buffer) // 'image/jpeg' // Override the fetch timeout (ms) await loadMedia('https://slow.example.com/big.mp4', { timeoutMs: 60_000 })

Array

MethodSignatureDescription
chunk(arr, size)<T>(arr: readonly T[], size: number) => T[][]Splits an array into batches of at most size items. Throws RangeError if size <= 0.
import { chunk } from 'zaileys' chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]] // Common use: rate-limit bulk sends by batching recipients const recipients = ['a@s.whatsapp.net', 'b@s.whatsapp.net' /* … */] for (const batch of chunk(recipients, 10)) { await Promise.all(batch.map((jid) => client.send(jid).text('Hello!'))) }

See also

Last updated on