WAHA, short for WhatsApp HTTP API, is a self-hosted REST server by devlike.pro that runs as one Docker container. It is well documented, it is free, and it already does several of the things people usually list as reasons to pay for a hosted API. This page is honest about that, and about the part that stays with you when you run it.
- Advantage: A residential proxy per number is included, and never falls back to a datacenter IP.
- Advantage: Per-number pacing with a typing indicator, ready to turn on.
- Advantage: No container, storage or upgrades to run.
- Advantage: Every webhook delivery logged for 30 days, with a resend button.
- Disadvantage: It costs money per number, where WAHA is free.
- Disadvantage: You cannot choose the engine, the storage or the server.
- Disadvantage: Proxy traffic past 0.5 GB a month per number costs $0.99 per GB.
- Advantage: Free and Apache 2.0, with every former Plus feature in the one image.
- Advantage: Signed webhooks (SHA-512 HMAC) with a configurable retry policy.
- Advantage: A built-in dashboard, Swagger and an MCP server per session.
- Advantage: You choose the engine: a browser or a WebSocket.
- Disadvantage: Proxies are yours to buy, place and keep healthy.
- Disadvantage: A pacing queue with a first-contact cap is yours to build.
- Disadvantage: Upgrades, session backups and night pages are yours.
- Disadvantage: Idempotent sends are not documented.
#What WAHA is
WAHA wraps a linked WhatsApp session in an HTTP API. You pull devlikeapro/waha, start the container, create a session, scan a QR code, and call POST /api/sendText.
Under the API it offers several engines, and you pick one per server with an environment variable:
- WEBJS, the default, drives a real browser running WhatsApp Web.
- WPP is also browser based.
- NOWEB and GOWS talk to WhatsApp directly over a WebSocket, one written in Node.js and one in Go, without a browser.
The browser engines are heavier to run. The WebSocket ones use far less memory per session, and the docs explain the trade-offs per feature.
The pricing changed in 2026. Until version 2026.6.1, WAHA had a free Core image and a paid Plus image that you pulled with a key from its supporters' portal. From 2026.6.1 on, the Plus features (any number of sessions, media, every storage backend, the built-in security) are in the one free image, licensed Apache 2.0, with no license checks. There is still a $5 a month tier for people who want to support the project, and the page says plainly that it brings nothing extra.
#What WAHA already gets right
It would be easy to write this page as if a self-hosted tool lacks everything. WAHA does not.
- Signed webhooks. Set an
hmac.keyon a webhook and every request carriesX-Webhook-Hmac, a SHA-512 HMAC of the raw body, withX-Webhook-Timestampand a request id. - Webhook retries. Each webhook takes a retry policy (constant, linear or exponential), a delay and a number of attempts.
- A dashboard. A built-in web UI at
/dashboardwith an event monitor and a chat view, which can manage several servers. - Swagger. An OpenAPI description is served by the container, and there is a Postman collection.
- An MCP server. WAHA can run an MCP endpoint per session inside the container, with scoped actions and the same API key.
- Per-session keys. An admin key for everything, and session keys scoped to one number.
If what you need is a free HTTP API on your own server, WAHA is a strong choice and we would not try to talk you out of it.
#What stays with you
Everything above runs on your machine, so the same machine is where things go wrong.
The proxy. WAHA lets you set a proxy globally or per session, and its docs recommend a couple of providers with discount codes. It does not supply one. Choosing residential IPs, matching each number's country, keeping the exit stable, and noticing a dead one are yours. A number that reconnects from a datacenter address, or from a different country each day, carries a signal WhatsApp reads. Why WhatsApp bans numbers walks through it.
Pacing. WAHA's docs have advice on sending safely, but a queue that holds a number to a rate, a slower rate for strangers, and a typing indicator before each message is something you build on top.
Operations. Upgrades track WhatsApp's protocol changes. Sessions live in the storage you configure, which needs backups. Someone decides which disconnect is a blip and which is a logged-out phone, and gets woken for the second kind.
#What wuapi does instead
wuapi is a hosted API for the same model: each number is a linked device, connected by QR code or pairing code.
- A residential proxy per number, included. Pass
proxyLocationwhen you create the account and the number gets a sticky exit in that country and city. If the proxy is down, the account stays offline rather than connecting from a datacenter IP. - Pacing per number. A per-minute cap, a lower cap for first contacts, and typing before each send, set with
PATCH /v1/accounts/{accountId}. All three are off by default so replies are instant; the guide says when to turn them on, and we recommend12a minute and5to new contacts. - Webhooks. HMAC-SHA256 over
<t>.<raw body>inWuapi-Signature, retried at 30s, 2m, 10m, 1h and 6h, six attempts, with every delivery kept in the dashboard for 30 days and a resend button. How the signature works. - Idempotency.
Idempotency-Keyon anyPOST, remembered for 24 hours. - A typed SDK.
@wuapidev/sdkfor TypeScript, next to the OpenAPI 3.1 file, and a hosted MCP server as well as the local one. - Projects. Separate customers or environments, each with its own accounts, keys, webhooks and usage.
The trade is control for time. You do not choose the server, the storage or the engine, and your messages pass through our infrastructure.
#What twenty numbers cost each way
Say you run twenty numbers for twenty small customers, each in its own country.
With WAHA the software line is zero. One server with enough memory for twenty sessions is a modest monthly bill if you run a WebSocket engine, and a larger one if you run a browser per session. The proxy line is twenty residential exits in twenty countries, which usually means an account with a proxy provider that sells by the gigabyte, plus the work of pinning each number to its exit and replacing an exit when it stops answering. The time line is the one to be honest about: upgrades when WhatsApp changes something, a look at the dashboard every morning, and the night a customer's number drops while you are asleep.
With wuapi, twenty numbers cost $91.50 a month: $6 for the first and $4.50 for each of the next nineteen. That includes a residential exit per number in the country you pick, and 10 GB of proxy traffic a month pooled across the twenty. Past that, traffic is $0.99 per GB. Each customer can sit in its own project with its own API key, so a support ticket from one never touches another's numbers.
If your team already runs servers at night and has a proxy account it trusts, WAHA is cheaper. If neither is true, the hosted price is mostly the price of not building those two things.
#Side by side
| WAHA | wuapi | |
|---|---|---|
| what it is | free server you run in Docker | hosted API |
| price | free; optional $5 a month to support it | $6 first number, $4.50 each to 50, $3.50 after |
| free plan | the whole product is free to self-host | 1 number, 2,000 messages, 0.5 GB proxy a month |
| hosting | your server, your storage | none on your side |
| engines | browser or WebSocket, your choice | ours, not configurable |
| residential proxy per number | bring your own | included, sticky, fails closed |
| pacing and typing | build it yourself | per number, opt-in |
| signed webhooks | SHA-512 HMAC of the body | HMAC-SHA256 over timestamp and body |
| webhook retries | configurable policy | 30s, 2m, 10m, 1h, 6h |
| idempotent sends | not documented | Idempotency-Key, 24 hours |
| typed SDK and OpenAPI | Swagger, code examples | OpenAPI 3.1, TypeScript SDK |
| MCP server | per session, in your container | local and hosted |
| dashboard | built in | built in, with delivery logs |
| multi-tenant | session keys | projects with keys, webhooks and usage |
#Moving from WAHA
The two APIs share a shape: a session is a number, a send names the number and the chat, events arrive by webhook.
| WAHA | wuapi |
|---|---|
| session | account |
X-Api-Key | Authorization: Bearer wu_live_... |
POST /api/sessions | POST /v1/accounts with proxyLocation |
GET /api/{session}/auth/qr | GET /v1/accounts/{accountId}, read qrCodeUrl |
POST /api/{session}/auth/request-code | POST /v1/accounts/{accountId}/pairing-code |
POST /api/sendText | POST /v1/messages |
12132132130@c.us | +12132132130 |
...@g.us | ...@g.us, unchanged |
message event | message.received |
session.status event | account.connected, account.disconnected |
// WAHA
await fetch(`${WAHA_URL}/api/sendText`, {
method: "POST",
headers: { "X-Api-Key": WAHA_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ session: "default", chatId: "12132132130@c.us", text: "Hi there!" }),
})
// wuapi
await wuapi.messages.send({ accountId, to: "+12132132130", text: "Hi there!" })Plan for three things:
- Numbers link again. A session cannot be moved between servers, so each phone scans a new code. Do it one number at a time.
- Your webhook check changes. Swap the SHA-512 check for the
Wuapi-Signatureone in the docs, and keep your handler idempotent by eventid. - Contacts change format. WAHA's
@c.usids become E.164 numbers with a+. Contacts that hide their number arrive aslid:ids in both.
Start with one number on the Free plan and run it next to your WAHA session for a week. Watch how often each one drops, how long a send waits during a drop, and how much of your time each one takes.
#Questions people ask
Is WAHA free?
Yes. Since version 2026.6.1 every feature that used to be in the paid Plus image is in the free one, licensed Apache 2.0, with no license checks. A $5 a month supporter tier exists and, by the project's own description, brings no extra features.
Does WAHA sign its webhooks?
Yes, when you set an HMAC key on the webhook. The request then carries X-Webhook-Hmac, a SHA-512 HMAC of the body, plus a timestamp header. wuapi signs every delivery with HMAC-SHA256 over the timestamp and the raw body.
Do I need proxies for WAHA?
WAHA lets you set a proxy per session but does not provide one, so the residential IPs, their countries and their upkeep are yours. On wuapi a residential proxy with a sticky exit comes with every number, and 0.5 GB a month per paid number is included.
When should I stay on WAHA?
When your data has to stay on your servers, when you want to choose the engine, or when you run enough numbers that a flat server bill beats any per-number price and someone on the team already handles the proxies and the night pages.
Can I move WAHA sessions to wuapi without scanning again?
No. A linked session cannot be exported, so each number links again with a QR code or a pairing code. The move is short per number, but the phone's owner has to be there for it.