whatsapp-web.js drives WhatsApp Web in a Puppeteer browser, ban risk included
A WhatsApp client library for NodeJS that connects through the WhatsApp Web browser app
At a glance
- What is it?
- A Node.js library that automates WhatsApp Web by driving a browser page instead of a protocol. It covers nearly the whole feature table of the web client, but the host needs Chrome, the account carries platform ban risk, and two message types are already deprecated.
- Who is it for?
- Adopt whatsapp-web.js when you want WhatsApp Web's own feature set from Node.js and can accept a browser on the host plus a phone number that carries platform ban risk. Do not adopt it to send buttons or lists, both marked deprecated in the project's own feature table, or for a number whose loss you cannot absorb.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- wwebjs/whatsapp-web.js22,909 ★ · +305
| Repository | 2026-09-21 | 2026-11-14 |
|---|---|---|
| wwebjs/whatsapp-web.js | 22.6k | 22.9k |
305 Stars in the last 54 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Puppeteer drives the web client, not a WhatsApp protocol
whatsapp-web.js does not implement a WhatsApp protocol. It loads WhatsApp Web in a browser it controls and calls the functions already living inside that page, with puppeteer pinned at 24.38.0 among the dependencies. Because Puppeteer downloads and launches Chrome, the host needs a working browser before a single message moves, and the stated reason for running everything in a managed browser instance is to "reduce the risk of being blocked". That is a mitigation, not a guarantee.
The rest of the dependency list is small and pinned exactly, with no range markers: fluent-ffmpeg 2.1.3, mime 3.0.0, node-fetch 2.7.0 and node-webpmux 3.2.1. fluent-ffmpeg is a wrapper around the ffmpeg binary, so media work depends on an ffmpeg toolchain the README never asks you to install. Exact pins also mean you control upgrades yourself; nothing moves under you between installs.
What this design cannot do is absorb an upstream redesign. Every call travels through WhatsApp's own page scripts, so a change in that page changes your API surface, and the repair arrives as a library release rather than as a config toggle you can set.
Node v18.0.0, three package managers, and the QR handshake
The floor is stated plainly: Node.js v18.0.0 or higher is required. Three package managers install the same package name:
npm install whatsapp-web.js
yarn add whatsapp-web.js
pnpm add whatsapp-web.jsThe entry point is index.js and typings ship next to it as index.d.ts, so editor completion comes from the package itself rather than from a separate types package.
The shortest real program is the one the README gives, and it reads as a state machine rather than as boilerplate: the qr event hands you a string to render, ready means the page has paired, and message fires for inbound chat.
const { Client } = require('whatsapp-web.js');
const qrcode = require('qrcode-terminal');
const client = new Client();
client.on('qr', (qr) => {
qrcode.generate(qr, { small: true });
});
client.on('ready', () => {
console.log('Client is ready!');
});The reply path and the call that starts everything are the other half:
client.on('message', (msg) => {
if (msg.body == '!ping') {
msg.reply('pong');
}
});
client.initialize();Note what package.json does not list: qrcode-terminal is required by this example yet is not one of the five runtime dependencies, so the install block above is not enough to run the snippet as written. Add that package to your own project first, or the require at the top of the snippet fails. The first thing you should see is a QR code in the terminal; nothing else happens until a phone pairs with it.
Video needs Google Chrome, and buttons and lists are already gone
The supported features table is long, and almost every row is green: send and receive messages, images, audio, documents, stickers, contact cards, locations, replies, mentions of users and groups, group invites, adding, kicking and promoting participants, muting chats, blocking contacts, contact info, profile pictures, status messages, reactions, polls, poll voting and channels. Multi Device is on the list too.
Three rows carry conditions you cannot design around. Sending video is marked as requiring Google Chrome, so a host with no Chrome install can send images, audio and documents from the same code and still cannot send video. Send buttons and Send lists are both marked deprecated rather than missing, which means code that once built interactive messages now has nothing to call. Communities is the single row flagged as coming soon.
What you cannot get from this repository is a roadmap for the two deprecated types: no replacement is named and no removal version is given. If your product depends on interactive list messages or button messages, that dependency cannot be met here, and the only documented path for a gap is opening an issue. The repository root also has no Dockerfile, so the headless deployment is yours to build, and your image has to carry a browser if video matters to it.
Events in, events out, with no delivery receipt to wait on
Every interaction in the example is a subscription rather than a request. There is no send call you await and no connection handle you keep; client.initialize() is the one method the README invokes, and it is what makes the registered handlers live. Anything that is not a handler has to be derived from what those three events carry.
The feature table names capabilities, not confirmations. Send messages and Receive messages both carry a check mark, but no row records read receipts, delivery status or message history. If your product promise depends on that confirmation, check the documentation for it before building on this library.
For looking at a live client without a full program, package.json carries a REPL entry point alongside the test script:
"shell": "node --experimental-repl-await ./shell.js",
"test": "mocha tests --recursive --timeout 5000"The --experimental-repl-await flag is what lets the shell await inside the prompt, so top level await works while you poke at a paired client. Reference documentation is generated from JSDoc rather than written by hand, through the .jsdoc.json config, and the published docs and the guide are linked from the README at wwebjs.dev and guide.wwebjs.dev.
The disclaimer says WhatsApp does not allow bots
The project is explicit about the platform side. It states it is not affiliated, associated, authorized or endorsed by WhatsApp, that WhatsApp does not allow bots or unofficial clients on its platform, that it is not guaranteed you will not be blocked by using this method, and that for those reasons this should not be considered totally safe. Apache-2.0 covers the code, not the platform's permission to use it.
The consequence for the reader is concrete. The number you scan the QR code with is the number exposed, and a block ends that number's WhatsApp account along with the session driving it. Running in a managed browser lowers the odds of that outcome without removing it, and nothing in the repository tells you how often a block happens or what recovery looks like. The login is also manual every time a fresh session starts, so a deployment that cannot keep a browser and its profile alive will depend on a human being present.
Read this before choosing the library, not after the first block. The README documents no retry layer, no failover account and no appeal path, and the library's own words are the strongest warning available about that.
Session storage lives in a guide the README only links
Keeping a session alive across restarts is the part of this library most deployments get wrong, and the README deals with it in a single sentence: for more details on saving and restoring sessions, check out the Authentication Strategies guide. The example above passes no options to new Client(), and the README does not document what the no option path does with an existing session.
That silence matters when the process is a container that restarts on deploy. If you have no strategy wired up, your recovery procedure is a person with a phone, and your incident runbook becomes a QR scan. The repository root lists example.js and a tests directory but no session fixture, so there is no committed example of a persisted session to copy.
What you can verify from here is narrower but still useful: the docs and guide live at wwebjs.dev and guide.wwebjs.dev, the Discord server is linked from the README, and the feature table includes Multi Device, so the client is built around a modern linked device session rather than the older single device pairing.
The test suite wants a paired client and a real chat id
The tests are not hermetic. The .env.example file at the repository root shows what they expect:
[email protected]
WWEBJS_TEST_CLIENT_ID=authenticatedThat placeholder is a real WhatsApp chat id shape, and the second line says the client is expected to have completed pairing before the suite runs. dotenv sits in devDependencies to load them. So a green run needs a paired account and a chat you control, and it means touching a real conversation, not a sandbox number.
The test command carries a five second per test budget, from mocha tests --recursive --timeout 5000, with test-single running plain mocha for one file. On a slow or containerised host that budget can expire before a browser finishes loading a page, and the failure you see looks the same as a genuine assertion failure. The consequence is that you cannot treat a red suite as a code problem until you have read the error text.
What the suite cannot give you is coverage of the upstream page. Tests run against live WhatsApp Web, so they detect a client change only after WhatsApp has already shipped it and only if you run them often enough to notice.
A push on 2026-09-29, a release tag from April, and pinned dependencies
The repository is not archived and the last push was on 2026-11-01. Released versions move more slowly: v1.34.7 on 2026-04-24, v1.34.6 on 2026-01-30 and v1.34.5-alpha.3 on 2026-01-05, and package.json still declares 1.34.7. Read together, that is a project taking commits between releases, with a version bump roughly every few months and prereleases tracked under an alpha tag.
Upgrade cost sits in the dependency pins. Runtime dependencies carry exact versions, so puppeteer stays at 24.38.0 and its bundled Chrome stays put until you change it, and security updates to those five packages arrive only when the library is released with a new number. There is no automated update path in the scripts:
"check": "npm run lint && npm run format:check",
"generate-docs": "npx jsdoc --configure .jsdoc.json --verbose"Code quality gates exist through eslint.config.mjs and the .prettierrc.json settings, husky installs through the prepare script, and commitlint.config.js with @commitlint/cli means commits follow conventional commit messages. Contributors are asked to open an issue before a significant change and to check whether one already exists. The licence is Apache-2.0, copyright 2019 Pedro S Lopez, with the standard Apache text in the LICENSE file.
Editorial conclusion
Adopt whatsapp-web.js when you want WhatsApp Web's own feature set from Node.js and can accept a browser on the host plus a phone number that carries platform ban risk. Do not adopt it to send buttons or lists, both marked deprecated in the project's own feature table, or for a number whose loss you cannot absorb. Before the first deploy, read the Authentication Strategies guide to confirm a saved session survives your restart pattern, and check the feature table again after each library release.
Frequently asked questions
What is whatsapp-web.js?
A Node.js library for interacting with WhatsApp Web that reaches the web client's internal functions through Puppeteer in a managed browser instance. It targets nearly all features of the web client and is published on npm as whatsapp-web.js under Apache-2.0.
How to install WhatsApp web.js?
Node.js v18.0.0 or higher is required, then run npm install whatsapp-web.js, yarn add whatsapp-web.js or pnpm add whatsapp-web.js. If the install gives you trouble, the project points to its Guide for more detailed instructions.
How do you use whatsapp-web.js?
Create a Client, register handlers for the qr, ready and message events, and call client.initialize() to start it. The repository also ships example.js with additional examples and a shell.js entry point for working with a live client.
Is whatsapp-web.js safe?
The project does not claim that it is. Its disclaimer states that WhatsApp does not allow bots or unofficial clients on its platform, that being blocked is not guaranteed not to happen, and that the method should not be considered totally safe.
Is whatsapp-web.js legal?
The code is Apache-2.0, copyright 2019 Pedro S Lopez, and the project states it is not affiliated with or endorsed by WhatsApp. The same disclaimer says WhatsApp does not allow bots or unofficial clients, so the code licence and the platform's own terms are two separate questions the project does not resolve for you.
How do you update whatsapp-web.js?
The README does not document an update procedure. The package.json scripts cover test, shell, generate-docs, lint, format:check and check, and none of them upgrades the library, so an upgrade is the dependency bump you write yourself.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wwebjs-whatsapp-web-js)Star history chart for your README
[](https://hysenlabs.com/projects/wwebjs-whatsapp-web-js)Was this useful?