• Home
  • Blog
  • WPPConnect Explained: Features, Setup, and When to Use It
Libraries
9 min read Jun 13, 2026

WPPConnect Explained: Features, Setup, and When to Use It

WPPConnect isn't one package — it's a suite: a Puppeteer-driven Node lib plus a ready-to-run REST server. Here's the architecture, setup code, and when to use it.

Key takeaways
  • WPPConnect is a suite, not a single package: wa-js (browser layer), the wppconnect Node lib (Puppeteer-driven), and wppconnect-server (a REST/HTTP wrapper).
  • The core lib is @wppconnect-team/wppconnect (LGPL-3.0); the server and wa-js use the @wppconnect/ scope (Apache-2.0) — the scopes differ, which is easy to get wrong.
  • wppconnect-server gives you a language-agnostic REST API with multi-session routes, bearer tokens, webhooks, Swagger, and Docker out of the box.
  • It automates WhatsApp Web via headless Chromium on WhatsApp's multi-device protocol, so it's against WhatsApp's ToS and can get numbers banned; each session is a full browser instance.
  • For compliant, at-scale messaging use the official WhatsApp Cloud API; for just verifying numbers and pulling public profiles, a hosted API avoids running browsers entirely.

What WPPConnect actually is

WPPConnect is an open-source project maintained by the wppconnect-team GitHub organization, with roots in the Brazilian and wider LATAM JavaScript community (its docs ship in both English and Portuguese). The first thing to understand is that "WPPConnect" is not a single library you npm-install — it's a suite of related projects that sit at different levels of abstraction. Confusing them is the most common source of setup pain.

Like whatsapp-web.js and unlike Baileys, WPPConnect works by automating WhatsApp Web. It launches a real Chromium browser, loads web.whatsapp.com, and injects helper code that calls WhatsApp's own internal JavaScript functions. It is an unofficial tool — it is not the official WhatsApp Business Cloud API, and it is not affiliated with or endorsed by WhatsApp or Meta.

There are three layers that matter when you pick a starting point:

  • wa-js (@wppconnect/wa-js, Apache-2.0, v4.3.1) — the lowest level. It injects and exports WhatsApp Web's internal functions directly in the browser context. You'd use this inside a browser extension or a custom orchestrator.
  • wppconnect, the "lib" (@wppconnect-team/wppconnect, LGPL-3.0-or-later, v2.2.1) — the mid level and what most people mean by "WPPConnect." A Node.js library that drives Chromium via Puppeteer, injects wa-js, and exposes a clean Node API through wppconnect.create().
  • wppconnect-server (@wppconnect/server, Apache-2.0, v2.10.0) — the highest level. A ready-to-run REST/HTTP wrapper around the lib so you can integrate over HTTP from any language.

Two helper repos round out the suite: wa-version, which pins and serves specific WhatsApp Web HTML versions so your sessions survive WhatsApp's frequent updates, and wa-proto, which holds protobuf definitions.

How it works under the hood

The architecture is browser automation, top to bottom. The lib starts a headless Chromium instance through Puppeteer (it depends on Puppeteer ^24.x), navigates to WhatsApp Web, and links your account via the QR code flow. Once linked, it injects wa-js, which exposes WhatsApp Web's internal store functions so the lib can read chats, send messages, and listen for events as if a person were using the web client.

Worth knowing for context: since WhatsApp's multi-device rollout, WhatsApp Web no longer needs your phone to stay online — a linked device holds its own encrypted session against WhatsApp's multi-device protocol. WPPConnect rides on top of that web client, so a linked session keeps working even when the phone is offline, the same way the official Linked Devices feature does. It doesn't change any of the trade-offs below, but it explains why a scanned session stays alive between restarts.

This is fundamentally different from the two other common approaches. Baileys talks to WhatsApp's multi-device protocol over a WebSocket directly, with no browser at all — much lighter, but a different fragility profile. The official Cloud API is a sanctioned HTTP API from Meta with no reverse engineering involved. WPPConnect sits in the browser-automation camp alongside whatsapp-web.js.

Calling wppconnect.create() returns a client object with the methods you'd expect — sendText, sendImage, getAllChats, group operations, and so on — plus event callbacks like catchQR (to display the login QR), statusFind (connection status), onMessage (incoming messages), and onAck (delivery/read receipts). Sessions persist via a token and a Chromium userDataDir, so you don't have to rescan the QR on every restart.

Setting up the core library

If you're building a Node.js application and want the library directly in-process, install the lib. Watch the scope carefully — the core lib lives under @wppconnect-team, while the server and wa-js use the shorter @wppconnect scope. Getting this wrong is the number-one install error.

BASH
npm i --save @wppconnect-team/wppconnect

A minimal session that prints the QR to your terminal and sends a message once connected looks like this. The package ships its own TypeScript types, so you can import it either as ESM (import wppconnect from '@wppconnect-team/wppconnect') or via CommonJS require() — use whichever your project is configured for. The recipient id format is the phone number in international format with the @c.us suffix for individual chats:

TS
// ESM / TypeScript
import wppconnect from '@wppconnect-team/wppconnect';
// CommonJS equivalent:
// const wppconnect = require('@wppconnect-team/wppconnect');

wppconnect
  .create({
    session: 'sessionName',
    headless: true, // true uses Chrome's new headless mode; 'shell' uses the
                    // legacy chrome-headless-shell binary (lighter, fewer features)
    catchQR: (base64Qr, asciiQR) => console.log(asciiQR),
    statusFind: (status, session) => console.log('Status:', status, session),
  })
  .then((client) => {
    client.sendText('[email protected]', 'Hello from WPPConnect');
  })
  .catch(console.error);

Scan the asciiQR with WhatsApp on your phone (Linked Devices), and the session links. On subsequent runs, the persisted session token lets it reconnect without a new QR. Leave headless on true for the modern, full-featured headless mode; only switch to 'shell' if you specifically need the lighter legacy binary and can live with its reduced feature set. From there you wire up onMessage and the other callbacks to build a bot, an auto-responder, or a notification sender.

wppconnect-server: REST mode and multi-session

The headline feature that sets WPPConnect apart from whatsapp-web.js is wppconnect-server: an official REST wrapper built on Express, Socket.IO, and Swagger. It turns the lib into a language-agnostic HTTP service, which is what you want for multi-tenant setups or when your stack isn't Node. It ships with a Dockerfile and a docker-compose.yml, listens on port 21465 by default, and exposes interactive Swagger docs at /api-docs.

Every route is namespaced by session — /api/:session/... — so a single server instance can run many WhatsApp numbers concurrently. That multi-session-by-design model is the main reason teams reach for the server over rolling their own around the lib.

Authentication is two steps. First, you mint a bearer token using the secret key from config.ts. Then you pass that token on every other call. The secret key defaults to THISISMYSECURETOKEN and absolutely must be changed before production:

BASH
# 1) Get a bearer token using the SECRET_KEY from config.ts
curl -X POST "http://localhost:21465/api/mySession/THISISMYSECURETOKEN/generate-token"

# 2) Start the session (returns a QR to scan)
curl -X POST "http://localhost:21465/api/mySession/start-session" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $2b$10$JcHd97xHN6ErBuiLd7Yu4..."

The returned token has a wppconnect:$2b$10$... shape (it's bcrypt-derived). Once a session is started and the QR is scanned, you send messages and call other endpoints under the same /api/:session/ prefix. Webhooks live in the webhook block of config.ts — set webhook.url and toggle events like onPresenceChanged, onParticipantsChanged, onReactionMessage, onPollResponse, onRevokedMessage, and onLabelUpdated, along with autoDownload for incoming media. To push that media to object storage, flip uploadS3 on in the same block, then fill in the separate aws_s3 block (region, access_key_id, secret_key, defaultBucketName, and an optional custom endpoint for S3-compatible providers).

WPPConnect vs whatsapp-web.js, Baileys, and the Cloud API

WPPConnect and whatsapp-web.js use the exact same fundamental technique — Puppeteer-driven WhatsApp Web automation — which means they share the same fragility when WhatsApp ships an update. The differences are about scope and packaging, not about one being broken and the other not. Widen the lens to Baileys and the official Cloud API and the trade-off becomes resources versus compliance.

AspectWPPConnectwhatsapp-web.jsBaileysCloud API
TechniquePuppeteer + WhatsApp WebPuppeteer + WhatsApp WebDirect multi-device WebSocket (no browser)Official HTTP API from Meta
Official / sanctionedNo (unofficial)No (unofficial)No (unofficial)Yes (compliant with ToS)
Built-in REST serverYes (wppconnect-server)No (library only)No (library only)N/A (it is the API)
Multi-sessionBuilt in (per-session routes)Roll your ownRoll your ownNative (multiple numbers via Meta)
Resource costHigh (Chromium per session)High (Chromium per session)Low (socket only)None (managed by Meta)
Best fitProduction, multi-tenant, non-Node stacksBeginners, a single number, Node appsResource-constrained Node automationCustomer messaging at scale

In short: whatsapp-web.js is simpler, lighter to learn, and has a large community, which makes it ideal for a single number or a developer getting started. WPPConnect packs more features out of the box and — crucially — ships an official REST server, positioning it for HTTP-based, language-agnostic, and multi-tenant deployments. Baileys drops the browser entirely for a far smaller footprint when resources dominate. And the official WhatsApp Cloud API is the only path that complies with WhatsApp's Terms of Service, which matters a lot once money or scale is involved.

Real limitations and ToS risk

Be clear-eyed about the trade-offs before you build on WPPConnect. None of these are unique to the project — they apply to every WhatsApp Web automation library — but you should weigh them honestly.

  • Terms of Service and ban risk: automating WhatsApp Web with these libraries is against WhatsApp's Terms of Service. Numbers can be rate-limited or banned, especially for unsolicited or bulk messaging. WPPConnect is not affiliated with or endorsed by WhatsApp or Meta.
  • Fragility: because it depends on WhatsApp Web's internal JavaScript, WhatsApp updates can break it. Keeping the package and wa-version current is an ongoing maintenance burden, not a one-time setup.
  • Resource cost: each session is a full Chromium instance, so RAM and CPU usage climb quickly. Running many concurrent sessions requires real infrastructure planning.
  • No SLA and no official support: it's community-driven open source. There's no vendor to call when something breaks at 2 a.m.

For commercial, at-scale messaging, the compliant option is the official WhatsApp Business / Cloud API. Use WPPConnect where its trade-offs are acceptable — internal tooling, prototypes, small-scale automation you control — and reach for the official API when compliance, deliverability guarantees, and support become requirements. And if your task is read-only enrichment rather than messaging, you may not need a session at all (more on that next).

When WPPConnect is the right call

Choose WPPConnect — specifically the server — when you need a self-hosted WhatsApp REST API, when you have to run multiple numbers from one service, or when your application isn't written in Node and HTTP is the only sane integration boundary. Its multi-session routing, bearer-token auth, webhooks, and Docker packaging make it a reasonable foundation for an internal multi-tenant messaging service.

Choose the lib directly when you're building a Node application and want the API in-process without an HTTP hop. Choose whatsapp-web.js instead when you have a single number and want the gentlest learning curve. Choose Baileys when resource footprint dominates. And choose the official Cloud API when you're sending at scale, to customers, with compliance on the line.

Finally, if messaging isn't actually your goal — you're enriching leads, validating phone numbers, detecting business accounts, or pulling public avatars — you can skip sessions entirely. A read-only profile lookup that tells you whether a number is on WhatsApp, plus its public name, avatar, and business flag, answers those questions over a single HTTPS call. Match the tool to the job, and you'll avoid both unnecessary infrastructure and unnecessary risk.

Frequently asked questions

Don't run a browser just to read a profile

If you only need to verify numbers and pull public WhatsApp profiles — picture, name, about, and business flag — skip the Chromium sessions and ban risk. Our hosted WhatsApp Profile API does it in one HTTPS call, free for 50 requests a month.

Explore the API
Sponsored

Need cheap numbers to create, verify or warm up WhatsApp accounts for testing? GrizzlySMS rents virtual numbers for WhatsApp verification from under $1.

Get a WhatsApp number

Sources & further reading

Related

More from the blog

Written by
Eduardo Airaudo

Developer and founder of the WhatsApp Profile API. Building WhatsApp tooling and APIs since 2022.

What Our Users Say

Real reviews from our satisfied customers

4.5/5 (170 reviews)