What Is whatsapp-web.js and How to Use It?

≈ 9 min read

Anyone looking into WhatsApp automation eventually runs into whatsapp-web.js. It is the most popular WhatsApp library in the Node.js world — but exactly what it does, why it is not the official API, and why it is not enough on its own are rarely made clear. This article explains how whatsapp-web.js works under the hood, how LocalAuth keeps the session alive, what risks it carries, and how we give it the role of a "driver" inside our own system.

1. What exactly is whatsapp-web.js?

whatsapp-web.js is an open-source Node.js library that lets you control WhatsApp Web (web.whatsapp.com) programmatically. The crucial point is this: the library does not connect to WhatsApp over a direct network protocol. Instead it launches a real Chromium browser in the background (via Puppeteer, usually in headless mode), opens the WhatsApp Web page inside it, and talks to the page's JavaScript to send messages, listen for incoming ones and read chats.

In other words, whatsapp-web.js is an automation bridge: it sits between your Node code and WhatsApp Web, which is itself an extension of the WhatsApp account on your phone. Whatever happens when a human opens WhatsApp Web and types a message by hand, the library drives that same interface programmatically.

In short: whatsapp-web.js = headless Chromium + the WhatsApp Web protocol + a Node.js API. It is not an official network API; it is a wrapper that automates the official web client.

2. Why "unofficial"? How it differs from the Business API

whatsapp-web.js is not built, published or supported by Meta/WhatsApp. It is an independent community project. That sets it fundamentally apart from the official WhatsApp Business API:

Aspectwhatsapp-web.jsOfficial Business API
Connection methodQR phone pairing (WhatsApp Web)Cloud API via Meta / a BSP
Approval processNone, starts immediatelyBusiness verification + template approval
Message feeNonePer-conversation charge
Official supportNone (community)Yes
Ban riskYes (if used against the terms)Low if rules are followed

For a deeper comparison of the two approaches and which scenario each fits, see the Business API alternative. In short: whatsapp-web.js is easy, free and quick to start; but because it is unofficial, the responsibility and the risk are entirely yours.

3. How does whatsapp-web.js work? (Step by step)

A send cycle roughly goes like this:

  1. Create a client: You instantiate a Client object and give it an authentication strategy (usually LocalAuth).
  2. Launch Chromium: The library opens a Chromium via Puppeteer and loads WhatsApp Web.
  3. QR / session: On the first run a qr event produces a QR code; scanning it from your phone opens the session. On later runs the session is restored from disk.
  4. Ready event: When the connection is up, ready fires and you can send.
  5. Send: client.sendMessage(chatId, text) drops a message into a chat. The chatId is typically in the form [email protected].

A minimal example looks like this:

const { Client, LocalAuth } = require('whatsapp-web.js');

const client = new Client({
  authStrategy: new LocalAuth({ dataPath: './wa-session' }),
  puppeteer: { headless: true, args: ['--no-sandbox'] }
});

client.on('qr', qr => console.log('Scan this QR:', qr));
client.on('ready', () => console.log('Connected!'));

client.on('ready', async () => {
  await client.sendMessage('[email protected]', 'Hello, this is a test message.');
});

client.initialize();

Notice: this code works, but even for a single message there is no wait, queue or rate control. If you drop sendMessage into a loop over a list of a thousand people, the library fires the messages back to back within seconds — which is the strongest possible signal to WhatsApp's spam detection.

4. LocalAuth: keeping the session alive

One of the most useful parts of whatsapp-web.js is its authentication strategies. The most common is LocalAuth. LocalAuth writes the browser session credentials (WhatsApp Web's own cookie/session data) into a folder you specify. As a result:

  • You scan the QR once on the first pairing.
  • When you restart the app, the library restores the session from that folder and does not ask for the QR again.
  • The session survives even a server restart — as long as that folder is preserved.

That is why, when running with Docker, you must bind the session folder to a volume; otherwise the session is lost every time the container is recreated and you have to rescan the QR. If the folder is deleted, or you remove the session from your phone's "Linked Devices" screen, you go back to the QR again.

Tip: As an alternative, the RemoteAuth strategy can store the session in a database. But for most self-hosted setups a LocalAuth folder on a persistent disk is the simplest, most reliable path.

5. Risks and limits

whatsapp-web.js is powerful, but it is not free — the price is operational risk:

  • Ban risk: Because it is unofficial, it pushes against WhatsApp's terms of service. High speed, non-consented lists or spam-like behaviour can lead to a permanent ban of your number.
  • Fragility: If the WhatsApp Web interface changes, certain library features can break temporarily and you have to wait for an update.
  • Resource use: Each client is a full Chromium instance; it is heavy on RAM and CPU. At least 2 GB of RAM is recommended for production.
  • Scale: One client drives one number; multiple numbers mean multiple Chromiums.

Ethics and law: A tool like whatsapp-web.js should only be used to message people who have consented to hear from you. Unsolicited bulk messaging violates both WhatsApp's terms and data-protection law (GDPR in the EU, KVKK/6563 in Turkey); every marketing message must carry an opt-out line (e.g. "Reply STOP"). See consent-compliant messaging for details.

6. What does it lack alone? Queue and anti-ban

This is the most overlooked point. whatsapp-web.js gives you only the "send a message" ability. Everything it does not give is your responsibility:

The library providesThe library does NOT (you must add)
Send/receive messagesA job queue (one send at a time)
QR and session handlingScheduled sending (delay)
Chat/media APIRandom wait between messages (anti-ban)
Connection eventsBreaks, time window, recipient cooldown
Persistent records, reporting, retries

It is exactly this gap that makes "I wrote a bot with whatsapp-web.js in 20 minutes and then my number got banned" stories so common. The library leaves sending discipline up to you. For safe sending you must wrap the library in a queue and an anti-ban layer. You can find which rules are needed and why in the rules to avoid a ban.

7. The role of whatsapp-web.js in this project

In our system whatsapp-web.js is positioned as a "driver", with the missing pieces built around it. The architecture is roughly this:

LayerJob
Web panel (React/nginx)Compose sends, scan QR, track messages
Server (Express :3200)Validates the request, queues it; never sends itself
Redis + BullMQQueue and scheduled jobs (delay)
Worker (Node 20 + Chromium)Hosts whatsapp-web.js; the only sender, applies all anti-ban timing (concurrency 1)

So the library's raw sending ability lives only inside the bottom worker. The session is persisted in a LocalAuth folder bound to a Docker volume. The worker inserts a 45–90 s random wait between messages (67–135 s for media), takes an 8–12 min break every 15 messages, enforces a 05:00–23:00 window and a 4-hour cooldown per recipient. This turns the library's "send as fast as you like" nature into a safe flow that can never exceed human speed.

If you want to put that sending ability behind an HTTP interface and trigger it from your own order system or CRM, see HTTP API integration; and for the bigger picture of running the library on your own server, see the self-hosted WhatsApp messaging system.

Frequently asked questions

Is whatsapp-web.js the official WhatsApp API?

No. It is an unofficial open-source library, not built by Meta. It automates a headless Chromium driving WhatsApp Web. The official solution is the Business API; whatsapp-web.js does not replace it and carries a ban risk if used against the terms.

Does whatsapp-web.js ask for a QR every time?

No. With LocalAuth the session is stored in a folder (persistent disk / Docker volume). You scan the QR once on the first pairing; after that the library restores the session. If the folder is deleted or the device is removed from the phone, the QR is required again.

Is it enough on its own for bulk messaging?

No. The library only provides send/receive; it has no queue, scheduling, rate limiting or anti-ban break logic. Without those it fires messages back to back and your number gets banned easily.

How much RAM does it use?

It is heavy because it launches a full Chromium instance; the headless browser alone uses a few hundred MB. At least 2 GB of RAM is recommended for a stable production setup.

Use whatsapp-web.js the way it should be wrapped

Queue, scheduling and an anti-ban layer are ready. Run the library inside a safe system instead of risking it on its own.

Open the panel →