Groups
client.group is the group management namespace on the zaileys Client. It provides full
lifecycle control over WhatsApp groups: create and leave groups, manage participants, rotate invite
links, update subject and description, configure disappearing messages, and lock or unlock group
settings.
import { Client } from 'zaileys'
const client = new Client({ sessionId: 'default' })
client.on('connect', async () => {
const groupId = '120363000000000000@g.us'
const meta = await client.group.metadata(groupId)
console.log(meta.subject, 'has', meta.participants.length, 'members')
})Every method on client.group calls an internal requireSocket() guard. If the client is not
connected, the call immediately throws a ZaileysDomainError with code NOT_CONNECTED and message
client not connected. Always wait for the 'connect' event (or await client.connect()) before
calling any group method. See Error Handling.
At a glance
| Method | Signature | Returns | Description |
|---|---|---|---|
create | create(subject, participants[]) | Promise<GroupMetadata> | Create a new group. |
metadata | metadata(groupId) | Promise<GroupMetadata> | Fetch group info. |
addMember | addMember(groupId, jids[]) | Promise<ParticipantUpdateResult[]> | Add participants. |
removeMember | removeMember(groupId, jids[]) | Promise<ParticipantUpdateResult[]> | Remove participants. |
promote | promote(groupId, jids[]) | Promise<ParticipantUpdateResult[]> | Promote participants to admin. |
demote | demote(groupId, jids[]) | Promise<ParticipantUpdateResult[]> | Demote admins to member. |
updateSubject | updateSubject(groupId, subject) | Promise<void> | Change the group name. |
updateDescription | updateDescription(groupId, description?) | Promise<void> | Change or clear the group description. |
leave | leave(groupId) | Promise<void> | Leave the group. |
tagMember | tagMember(groupId, jid, label) | Promise<void> | Apply a member label in the group. |
inviteCode | inviteCode(groupId) | Promise<string> | Get the current invite link code. |
revokeInvite | revokeInvite(groupId) | Promise<string> | Revoke and regenerate the invite link. |
acceptInvite | acceptInvite(code) | Promise<string> | Join a group by invite code; returns the group JID. |
toggleEphemeral | toggleEphemeral(groupId, seconds) | Promise<void> | Set the disappearing-message timer (0 disables). |
setting | setting(groupId, value) | Promise<void> | Update group restrictions (announcement, locked, etc.). |
Rate limiting and ban safety
Rapid group operations are one of the top WhatsApp ban triggers. Creating many groups, joining many groups, or adding/removing large numbers of participants in quick succession is treated as automated bulk abuse.
zaileys ships an operationGuard that automatically spaces out sensitive operations by category.
It is enabled by default. The default minimum intervals are:
| Category | Operations | Default interval |
|---|---|---|
group.create | create() | 60 seconds |
group.participants | addMember(), removeMember(), promote(), demote() | 10 seconds |
group.join | acceptInvite() | 30 seconds |
When multiple calls of the same category queue up, each one waits for the previous to finish plus
the minimum interval before running. This means calling addMember() three times in a row will
space the sends ~10 seconds apart automatically.
To tune or disable the guard, see Configuration — operationGuard. For advice on what patterns are risky, see Troubleshooting.
create
create(subject: string, participants: string[]): Promise<GroupMetadata>Creates a new WhatsApp group with the given subject (name) and initial list of participant JIDs.
Returns the full GroupMetadata for the newly created group.
Throttled by operationGuard under the group.create category (default 60 s between calls).
client.on('connect', async () => {
const group = await client.group.create('Project Zaileys', [
'628111111111@s.whatsapp.net',
'628222222222@s.whatsapp.net',
])
console.log('Created group:', group.id)
console.log('Subject:', group.subject)
})| Parameter | Type | Description |
|---|---|---|
subject | string | The group name (displayed to all participants). |
participants | string[] | Initial member JIDs in the format 628xxxxxxxxxx@s.whatsapp.net. |
Returns: GroupMetadata — see GroupMetadata shape.
metadata
metadata(groupId: string): Promise<GroupMetadata>Fetches the current metadata for a group: subject, description, participant list, admin flags, creation timestamp, and related fields. This is the primary read operation for group state.
client.on('connect', async () => {
const meta = await client.group.metadata('120363000000000000@g.us')
console.log('Subject:', meta.subject)
console.log('Participants:', meta.participants.length)
const admins = meta.participants.filter((p) => p.admin)
console.log('Admins:', admins.map((p) => p.id))
})| Parameter | Type | Description |
|---|---|---|
groupId | string | The group JID (e.g. 120363000000000000@g.us). |
Returns: GroupMetadata — see GroupMetadata shape.
addMember
addMember(groupId: string, jids: string[]): Promise<ParticipantUpdateResult[]>Adds one or more participants to the group. Returns a result entry for each JID indicating whether the operation succeeded.
Throttled by operationGuard under the group.participants category (default 10 s between calls).
You must be a group admin to add members.
client.on('connect', async () => {
const results = await client.group.addMember('120363000000000000@g.us', [
'628333333333@s.whatsapp.net',
'628444444444@s.whatsapp.net',
])
for (const r of results) {
console.log(r.jid, '->', r.status)
}
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
jids | string[] | JIDs to add. |
Returns: ParticipantUpdateResult[] — { jid: string; status: string } for each entry.
removeMember
removeMember(groupId: string, jids: string[]): Promise<ParticipantUpdateResult[]>Removes one or more participants from the group. You must be a group admin.
Throttled under group.participants (default 10 s).
client.on('connect', async () => {
const results = await client.group.removeMember('120363000000000000@g.us', [
'628333333333@s.whatsapp.net',
])
for (const r of results) {
console.log(r.jid, '->', r.status)
}
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
jids | string[] | JIDs to remove. |
Returns: ParticipantUpdateResult[].
promote
promote(groupId: string, jids: string[]): Promise<ParticipantUpdateResult[]>Promotes one or more participants to group admin. You must be a group admin yourself.
Throttled under group.participants (default 10 s).
client.on('connect', async () => {
const results = await client.group.promote('120363000000000000@g.us', [
'628111111111@s.whatsapp.net',
])
for (const r of results) {
console.log(r.jid, 'promoted, status:', r.status)
}
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
jids | string[] | JIDs to promote. |
Returns: ParticipantUpdateResult[].
demote
demote(groupId: string, jids: string[]): Promise<ParticipantUpdateResult[]>Demotes one or more group admins back to regular member. You must be a group admin yourself.
Throttled under group.participants (default 10 s).
client.on('connect', async () => {
const results = await client.group.demote('120363000000000000@g.us', [
'628111111111@s.whatsapp.net',
])
for (const r of results) {
console.log(r.jid, 'demoted, status:', r.status)
}
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
jids | string[] | JIDs to demote. |
Returns: ParticipantUpdateResult[].
updateSubject
updateSubject(groupId: string, subject: string): Promise<void>Updates the group name (subject). You must be a group admin (or the group must not have the locked
setting). Does not go through the operationGuard — avoid calling in a tight loop.
client.on('connect', async () => {
await client.group.updateSubject('120363000000000000@g.us', 'Team Announcements')
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
subject | string | New group name. |
updateDescription
updateDescription(groupId: string, description?: string): Promise<void>Updates the group description. Pass undefined or omit description to clear it. You must be a
group admin.
client.on('connect', async () => {
// Set description
await client.group.updateDescription(
'120363000000000000@g.us',
'This group is for internal announcements only.',
)
// Clear description
await client.group.updateDescription('120363000000000000@g.us')
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
description | string | undefined | New description, or omit to clear. |
leave
leave(groupId: string): Promise<void>Leaves the specified group. After this call the bot is no longer a participant and will not receive further group events for that JID.
client.on('connect', async () => {
await client.group.leave('120363000000000000@g.us')
console.log('Left the group.')
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Group JID to leave. |
tagMember
tagMember(groupId: string, jid: string, label: string): Promise<void>Applies a label to a member within the group. The jid parameter identifies the target member; the
label is the label string to apply. Label support depends on the group’s WhatsApp configuration.
client.on('connect', async () => {
await client.group.tagMember(
'120363000000000000@g.us',
'628111111111@s.whatsapp.net',
'VIP',
)
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
jid | string | The member’s JID. |
label | string | Label string to apply. |
inviteCode
inviteCode(groupId: string): Promise<string>Returns the current invite code for the group (the fragment appended to
https://chat.whatsapp.com/<code>). Throws ZaileysDomainError('OPERATION_FAILED') if the code
is unavailable (e.g. the bot is not an admin or the group does not exist).
client.on('connect', async () => {
const code = await client.group.inviteCode('120363000000000000@g.us')
console.log('Invite link: https://chat.whatsapp.com/' + code)
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
Returns: string — the raw invite code (not a full URL).
revokeInvite
revokeInvite(groupId: string): Promise<string>Revokes the current invite link and generates a new one. The old invite code immediately becomes
invalid. Returns the new code. Throws ZaileysDomainError('OPERATION_FAILED') if the operation
fails. You must be a group admin.
client.on('connect', async () => {
const newCode = await client.group.revokeInvite('120363000000000000@g.us')
console.log('New invite link: https://chat.whatsapp.com/' + newCode)
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
Returns: string — the newly generated invite code.
acceptInvite
acceptInvite(code: string): Promise<string>Joins a group using an invite code. The code is the raw fragment (not the full URL). Returns the JID
of the group that was joined. Throws ZaileysDomainError('OPERATION_FAILED') if the invite is
invalid or expired.
Throttled by operationGuard under the group.join category (default 30 s between calls).
Accepting many invites in rapid succession is a well-known WhatsApp ban signal. The operationGuard
spaces calls 30 seconds apart by default, but you should also avoid scripting bulk joins altogether.
See Troubleshooting.
client.on('connect', async () => {
const groupJid = await client.group.acceptInvite('AbCdEfGhIjKlMnOpQrSt12')
console.log('Joined:', groupJid)
})| Parameter | Type | Description |
|---|---|---|
code | string | The invite code (the part after https://chat.whatsapp.com/). |
Returns: string — the JID of the group that was joined.
toggleEphemeral
toggleEphemeral(groupId: string, seconds: number): Promise<void>Sets the disappearing-message timer for the group. Pass 0 to disable ephemeral messages. Common
values are 86400 (24 hours), 604800 (7 days), and 7776000 (90 days). You must be a group admin.
client.on('connect', async () => {
// Enable 7-day disappearing messages
await client.group.toggleEphemeral('120363000000000000@g.us', 604800)
// Disable disappearing messages
await client.group.toggleEphemeral('120363000000000000@g.us', 0)
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
seconds | number | Timer in seconds. 0 disables ephemeral messages. |
setting
setting(
groupId: string,
setting: 'announcement' | 'not_announcement' | 'locked' | 'unlocked',
): Promise<void>Applies a group-level restriction. You must be a group admin.
| Value | Effect |
|---|---|
'announcement' | Only admins can send messages. |
'not_announcement' | All participants can send messages. |
'locked' | Only admins can edit the group subject, description, and icon. |
'unlocked' | All participants can edit group info. |
client.on('connect', async () => {
const groupId = '120363000000000000@g.us'
// Mute the group — only admins can send
await client.group.setting(groupId, 'announcement')
// Re-open for all participants
await client.group.setting(groupId, 'not_announcement')
// Lock editing to admins only
await client.group.setting(groupId, 'locked')
// Allow anyone to edit group info
await client.group.setting(groupId, 'unlocked')
})| Parameter | Type | Description |
|---|---|---|
groupId | string | Target group JID. |
setting | 'announcement' | 'not_announcement' | 'locked' | 'unlocked' | The restriction to apply. |
GroupMetadata
create() and metadata() return a GroupMetadata object (re-exported from the underlying
transport layer). Key fields you will typically use:
| Field | Type | Description |
|---|---|---|
id | string | The group JID (e.g. 120363000000000000@g.us). |
subject | string | The group name. |
desc | string | undefined | The group description. |
owner | string | undefined | JID of the group creator/owner. |
creation | number | undefined | Unix timestamp of group creation. |
participants | GroupParticipant[] | Full participant list with admin flags. |
size | number | undefined | Number of participants. |
Each GroupParticipant:
| Field | Type | Description |
|---|---|---|
id | string | Participant JID. |
admin | 'admin' | 'superadmin' | null | undefined | Admin role, or absent if regular member. |
ParticipantUpdateResult
addMember(), removeMember(), promote(), and demote() all return
ParticipantUpdateResult[]:
interface ParticipantUpdateResult {
jid: string // the participant's JID
status: string // WhatsApp status code for this individual update
}Iterate the result to detect per-member failures (e.g. a JID that does not have a WhatsApp account will have a non-success status code).
const results = await client.group.addMember(groupId, jids)
const failed = results.filter((r) => r.status !== '200')
if (failed.length > 0) {
console.warn('Some members could not be added:', failed)
}Error handling
All client.group methods throw ZaileysDomainError on failure. The relevant error codes are:
| Code | When thrown |
|---|---|
NOT_CONNECTED | Any method called before the client is connected. |
OPERATION_FAILED | inviteCode(), revokeInvite(), or acceptInvite() when the operation cannot complete (e.g. invalid/expired invite, insufficient permissions). |
import { Client, ZaileysDomainError } from 'zaileys'
const client = new Client()
client.on('connect', async () => {
try {
const code = await client.group.inviteCode('120363000000000000@g.us')
console.log(code)
} catch (err) {
if (err instanceof ZaileysDomainError) {
if (err.code === 'NOT_CONNECTED') {
console.error('Client disconnected unexpectedly.')
} else if (err.code === 'OPERATION_FAILED') {
console.error('Could not retrieve invite code — are you a group admin?')
}
}
}
})See Error Handling for the full error taxonomy and how to distinguish domain errors from builder and automation errors.
Complete example
The example below creates a group, promotes a member to admin, locks editing to admins, and prints the invite link — demonstrating the common admin setup flow.
import { Client } from 'zaileys'
const client = new Client({ sessionId: 'default' })
client.on('connect', async () => {
// 1. Create the group
const group = await client.group.create('Announcements', [
'628111111111@s.whatsapp.net',
'628222222222@s.whatsapp.net',
])
console.log('Group created:', group.id)
// 2. Promote a co-admin
await client.group.promote(group.id, ['628111111111@s.whatsapp.net'])
// 3. Only admins can send messages
await client.group.setting(group.id, 'announcement')
// 4. Only admins can edit group info
await client.group.setting(group.id, 'locked')
// 5. Enable 7-day disappearing messages
await client.group.toggleEphemeral(group.id, 604800)
// 6. Grab the invite link
const code = await client.group.inviteCode(group.id)
console.log('Share this link: https://chat.whatsapp.com/' + code)
// 7. Update description
await client.group.updateDescription(group.id, 'Official announcement channel. Admins only.')
})See also
- Client & Lifecycle — how to construct the client and connect.
- Configuration — tuning or disabling the
operationGuard. - Error Handling —
ZaileysDomainErrorcodes and catch patterns. - Troubleshooting — what to do if operations fail or the account gets flagged.
- Communities — grouping multiple groups under a community umbrella.