open-wa
DocsRate Limits and Ban Risk

Rate Limits and Ban Risk

Control queue pressure, handle provider rejection, and understand what this project can and cannot promise about WhatsApp restrictions.

Rate Limits and Ban Risk

open-wa does not expose a WhatsApp rate-limit guarantee. WhatsApp does not publish a stable per-chat or per-group rate table, and provider restrictions can change without notice, so a local queue is a pacing control rather than a ban avoidance mechanism.

What is known and what is not

The client and schema define how open-wa validates and dispatches a send. They do not define WhatsApp's server-side quota, rolling window, account-age rule, or restriction duration. Treat community measurements as dated observations that need their own evidence; this guide does not turn them into defaults.

Provider rejection can happen even when a local queue is obeying its schedule. Handle the rejected operation, stop or slow the relevant workflow, and record the provider error before deciding whether a retry is appropriate. Do not retry in a short loop, and do not assume that a random delay makes a pattern safe.

Queue concurrency and rate are different

concurrency limits how many queue tasks run at the same time. It does not set the time between tasks. In p-queue, intervalCap and interval implement an interval window; omitting intervalCap leaves the cap at its default of Infinity. The following example uses strict rolling-window mode to allow no more than one queued send in any 15-second span, runs one task at a time, and records rejected jobs:

import PQueue from 'p-queue';
import { Client, createClient } from '@open-wa/wa-automate';
import { PuppeteerDriver } from '@open-wa/driver-puppeteer';

const runtime = await createClient({
  sessionId: 'paced-sender',
  driver: new PuppeteerDriver(),
});
const client = new Client({
  client: runtime,
  transport: runtime.getTransport(),
});

const sendQueue = new PQueue({
  concurrency: 1,
  intervalCap: 1,
  interval: 15_000,
  strict: true,
});

async function enqueueSend(chatId: string, text: string) {
  try {
    const result = await sendQueue.add(() => client.sendText(chatId, text));
    if (result === false) {
      console.error('WhatsApp did not accept the send request', { chatId });
      return false;
    }
    return result;
  } catch (error) {
    console.error('WhatsApp rejected a queued send', { chatId, error });
    throw error;
  }
}

await client.start();
await enqueueSend('447700900000@c.us', 'Hello');

Install the example dependencies with npm install @open-wa/wa-automate@5.1.0 @open-wa/driver-puppeteer@5.1.0 p-queue. Complete the normal client authentication when it starts. This is a process-local schedule: it does not coordinate other sessions or senders and does not establish a provider quota. Choose the interval for your workflow, consent model, and operational budget, then stop or reclassify work when WhatsApp reports a restriction.

Safer workflow boundaries

  • Accept messages or jobs only from a bounded source so a traffic spike cannot create an unbounded backlog.
  • Keep consent and opt-out state beside the job, and remove opted-out recipients before enqueueing a send.
  • Keep one clear owner for retries. A queue retry and an application retry can multiply traffic if both act on the same rejection.
  • Record the chat ID, operation, result, and provider error without logging message contents or credentials by default.
  • Stop or pause the queue after repeated rejections and require an operator to decide whether the workflow should resume.

Handling a restriction

There is no documented universal wait time for a WhatsApp restriction. Stop the automation, retain the provider warning or error, and review consent, queue depth, duplicate sends, retry behavior, and account context. Resume only after you have a bounded plan and a reason to believe the provider state allows it; timing alone cannot establish that the account is clear.

Was this helpful?

Your answer includes the page path and docs version.

On this page