Alternativesvs Baileys

A Baileys alternative for when the socket is the easy part

Baileys speaks WhatsApp's protocol. Here is everything else a production number needs, what it takes to build it around Baileys, and what wuapi runs for you.

wuapiAlternativeschecked 27 September 20267 min read
Baileys as the socket alone, with the layers a customer number needs drawn as empty boxes left to build, next to wuapi's stack with every layer run for you: API, signed webhooks, queue, pacing, reconnects, encrypted sessions and a sticky residential exit.[BAILEYS]rest api, sdk, mcpsigned webhooks, retriesqueue, idempotencypacing, recipient checkreconnects, healthencrypted sessionssticky residential exitnpm i baileysTHE SOCKET; THE REST IS YOURS[WUAPI]rest api, sdk, mcpsigned webhooks, retriesqueue, idempotencypacing, recipient checkreconnects, healthencrypted sessionssticky residential exitprotocolRUN FOR YOU[ALTERNATIVES]

Baileys is the open-source TypeScript library most people reach for when they want to talk to WhatsApp from Node.js without a browser. It is good at what it does, and a working bot takes an afternoon. What takes months is everything a number needs to stay connected and useful once real customers depend on it. This page lists those pieces, what building each one around Baileys involves, and what wuapi runs instead.

Pros and cons
wuapi
Advantages
  • Advantage: Proxies, reconnects and sends through drops are run for you.
  • Advantage: Sessions are encrypted and can move to another worker without a new QR code.
  • Advantage: A REST API with signed, retried webhooks around the number.
  • Advantage: No upgrades on your side when the protocol changes.
Disadvantages
  • Disadvantage: It costs money per number, where the library is free.
  • Disadvantage: You get what the API exposes, not every protocol feature the day it lands.
  • Disadvantage: Hosted: no fit for software your users run on their own machines.
Baileys
Advantages
  • Advantage: Free and MIT licensed.
  • Advantage: Every protocol feature, straight from the library.
  • Advantage: A plain Node.js process: no browser to run.
  • Advantage: Pairing by QR code or by a code typed on the phone.
Disadvantages
  • Disadvantage: The file auth state is not meant for production, per its docs.
  • Disadvantage: Proxies, pacing, reconnects and monitoring are yours to build.
  • Disadvantage: Breaking changes arrive with major versions, with a version 8 in the works.

#What Baileys is

Baileys, maintained under WhiskeySockets and MIT licensed, speaks the same WebSocket protocol WhatsApp Web uses, from a plain Node.js process. It is published on npm as baileys and @whiskeysockets/baileys. When we checked, the latest tag was 7.0.0-rc14, with 6.7.24 kept as the legacy line, and the maintainers describe a version 8 in active development with a new auth system.

The shape of a Baileys program is small:

  • A socket. makeWASocket opens the connection, with an optional agent for a proxy and a fetchAgent for media.
  • Auth state. useMultiFileAuthState keeps the keys in a folder. The docs are direct about it: it is not recommended for production, and you should write an auth state backed by a real database.
  • Events. messages.upsert for new messages, connection.update for the QR code and the connection state, creds.update to save keys.
  • Pairing. A QR code from connection.update, or requestPairingCode for a code typed on the phone.

Its README carries a clear warning: the project is not affiliated with WhatsApp, and the maintainers do not condone spam, bulk or automated messaging that breaks WhatsApp's terms.

#Who should run Baileys themselves

There are good reasons to stay on the library.

  • You are building something the API does not cover. A library gives you every protocol feature the day it lands. An API gives you what its maintainers chose to expose.
  • One number, one bot, low stakes. A personal assistant or an internal alert bot does not need a fleet.
  • Your product is open source or self-hosted. Your users run it on their own machines, so a hosted dependency does not fit.
  • You have the team. If you already run proxies, on-call and a database for sessions, most of the list below exists.

If none of those is you, read on. Everything in the next section is work that stands between a Baileys demo and a number a customer relies on.

#The socket is the easy part

A connection to WhatsApp lives inside a hostile network. Residential proxies drop connections every few minutes, sockets go half-open and silent, and round trips spike to seconds. A number also has a reputation that WhatsApp reads from how it connects and how it sends. The sections below take each consequence in turn, with what wuapi ships for it. Every figure is from our code.

#A network exit per number

WhatsApp sees where a session connects from. A number that shows up from a datacenter, or from a new country every day, looks unlike its owner. Why WhatsApp bans numbers goes through that signal and the others.

What you build: a residential proxy provider, an exit per number in the owner's country, logic to keep each number on the same exit, and a rule for what happens when the proxy is down.

What wuapi does: every account needs a proxyLocation, a country and city from 134 countries. Before a number first logs in through a new exit, the engine tests three candidates and keeps the fastest. The exit is sticky across reconnects and restarts. If the proxy cannot be reached, the account stays offline: there is no path to a datacenter IP or a direct connection, by design. 0.5 GB of traffic a month per paid number is included, then $0.99 per GB.

#Changing an exit without looking like a bot

Exits die, and replacing one is itself a signal if it happens too often.

What you build: a rotation policy with a budget.

What wuapi does: a number moves to a new exit only after 3 failed connects, at most 4 times a day and at least 6 hours apart, with a hard ceiling of 8 a day. If the proxy provider's gateway fails for several numbers at once, new connections move to a gateway in another region and move back once the first answers again, without touching live sockets and without spending any number's budget. Sessions dial the proxy over SOCKS5, which we measured to stay healthier than HTTP tunnels.

#Noticing a dead socket fast

The worst failure is the quiet one: a socket that looks open and delivers nothing.

What you build: your own liveness checks on top of the keepalive, and deadlines on every wait.

What wuapi does: an adaptive liveness ping with a 6 to 20 second deadline, a keepalive with a hard limit, and a send that gets no acknowledgement from WhatsApp within 20 seconds recycles the connection. The next connection is dialed ahead so the swap is quick.

#Reconnecting without looping

What you build: a reconnect loop that is patient with a flaky network and stops dead on a real logout. The Baileys docs show the basic version: reconnect unless the reason is loggedOut.

What wuapi does: the first retry is immediate, then an exponential backoff with full jitter capped at 20 seconds, and it never gives up on a temporary drop. It recycles the connection in place first and rebuilds the session only after two failures. It does not reconnect after logged_out, connection_replaced or temporary_ban, and on client_outdated it refreshes the version once. When many numbers drop at the same moment, the engine treats it as a network incident: it spreads the reconnects out and charges no exit budget.

#Sends that survive a drop

What you build: a queue per number that holds a message through a disconnect, retries it, and never delivers it twice.

What wuapi does: each number sends one message at a time. A send made during a drop waits for the number and is retried with the same WhatsApp message id, so it cannot arrive twice. Idempotency-Key on any POST is kept for 24 hours, so a retry from your side is safe too.

#Checking the recipient first

What you build: a lookup before writing to someone new, because messages to numbers that are not on WhatsApp are wasted and look careless.

What wuapi does: before a first message to a contact, the engine checks the number is on WhatsApp and fails the send with not_on_whatsapp if not. Answers are cached, 7 days for a yes and 6 hours for a no. This is always on.

#Pacing like a person

What you build: per-number rate limits, a stricter one for strangers, and a typing indicator.

What wuapi does: a per-minute cap from 0 to 30 with a random 1 to 3 second gap between sends, a separate cap for contacts who never wrote to the number, and a typing indicator sized to the message, between 0.8 and 6 seconds by default. These are off by default so replies are instant. We recommend 12 a minute, 5 to new contacts and typing on for anything that starts with you. Keep your number healthy explains when.

#Keeping sessions safe and movable

What you build: an auth state in a database, backups, encryption, and a rule that two processes never open the same session, because that looks like a takeover and logs the device out.

What wuapi does: session keys are encrypted with AES-256-GCM before they are stored, and a session can be restored on another worker without a new QR code. Writes are fenced so a stale worker cannot overwrite a newer session, and a deploy moves sessions one at a time.

#Webhooks, media and alerts

What you build: your own events to your own services, media handling, and a pager.

What wuapi does: webhooks signed with HMAC-SHA256 over the timestamp and raw body, retried at 30s, 2m, 10m, 1h and 6h, with 30 days of delivery logs. Media is sent by URL, fetched once from public addresses up to 100 MB, with uploads under deadlines and a cache for files you send repeatedly. account.disconnected fires only after a 20 second grace, and the dashboard emails you or posts to Slack when a number stays offline past a threshold you set.

#The work, side by side

pieceBaileys on your serverwuapi
protocolthe libraryhandled
session storageyour auth state, database, backupsencrypted, restorable on another worker
residential exityour provider, per numberincluded, sticky, in the number's country
proxy downyour ruleoffline, never a datacenter IP
exit rotationyour policyafter 3 failures, 4 a day, 6 hours apart
dead socket detectionyour checksliveness ping, 20 second send deadline
reconnectsyour loopjittered backoff, stops on logout or ban
sends through a dropyour queuewait, retry with the same message id
recipient checkyour lookupalways on, cached
pacing and typingyour limiterper number, opt-in
webhooksyour eventssigned, retried six times
upgradesyours, on protocol changesours
pricefree library; servers, proxies, time$6 first number, $4.50 each to 50

#Moving a Baileys bot to wuapi

Most of the code you delete. What remains is a webhook handler and API calls.

// Baileys: you hold the socket
import makeWASocket, { DisconnectReason, useMultiFileAuthState } from "baileys"

const { state, saveCreds } = await useMultiFileAuthState("auth")
const sock = makeWASocket({ auth: state })
sock.ev.on("creds.update", saveCreds)
sock.ev.on("connection.update", ({ connection, lastDisconnect }) => {
  // reconnect unless logged out, and everything this page lists
})
sock.ev.on("messages.upsert", async ({ messages }) => {
  for (const m of messages) {
    if (!m.key.fromMe) await sock.sendMessage(m.key.remoteJid!, { text: "Got it, thanks." })
  }
})

// wuapi: you handle an event
if (event.type === "message.received") {
  await wuapi.messages.send({ accountId: event.data.object.accountId, to: event.data.object.from, text: "Got it, thanks." })
}
Baileyswuapi
auth folder or databaseaccount, stored for you
connection.update with qrGET /v1/accounts/{accountId}, read qrCodeUrl
requestPairingCodePOST /v1/accounts/{accountId}/pairing-code
sendMessage(jid, { text })POST /v1/messages with to, text
messages.upsertmessage.received
connection.updateaccount.connected, account.disconnected
5511999999999@s.whatsapp.net+5511999999999

Link each number again with a QR code or a pairing code; a session cannot be carried from your auth folder to our store. Verify each webhook as the docs describe. The Free plan runs one number with 2,000 messages a month and no card, enough to run next to your bot for a week.

#Questions people ask

Is Baileys free?

Yes. Baileys is MIT licensed and free to use. What costs money is running it: servers, residential proxies for each number, a database for sessions, and the time someone spends on reconnects, upgrades and numbers that go quiet.

Is Baileys safe to use in production?

The library itself is widely used, but its docs say the file-based auth state is not meant for production, and its README warns against bulk or automated messaging. Production needs a database-backed auth state, proxies, pacing and monitoring you build yourself.

Does wuapi use Baileys?

We do not publish which protocol library our engine uses. What we publish is the behaviour around it: the proxy, reconnects, pacing, the recipient check and signed webhooks, each with the values from our code.

Can I keep using Baileys for some numbers and wuapi for others?

Yes. A number is linked to one place at a time, but nothing stops you running some numbers on your own Baileys service and others on wuapi, and moving them one by one.

Will wuapi stop my numbers from getting banned?

No one can promise that. WhatsApp restricts numbers for what they send and how people react. wuapi removes the network and connection signals a self-hosted setup often gets wrong, and gives you pacing to turn on.

wuapi is an independent service. It is not affiliated with, endorsed or sponsored by WhatsApp. WhatsApp is a trademark of its respective owner.

03/What to read next

Try it

Link a number and send your first message.

One REST call, a typed SDK, and webhooks signed with HMAC-SHA256 over the raw body. No per-message fees.

The whole API is in the docs, and the docs are in one file if you are handing the work to a coding agent.

All alternatives · openapi.json