go-whatsapp-web-multidevice (GOWA): a Go REST API for multi-account WhatsApp
GOWA - WhatsApp REST API with support for UI, Multi Account, Webhooks, and MCP, and Chatwoot. Built with Golang for efficient memory use.
At a glance
- What is it?
- GOWA wraps WhatsApp Web multi-device into a Go server that exposes REST endpoints, webhooks, MCP tools and a separately hosted dashboard. It suits self-hosters who want one process for several WhatsApp accounts, and it asks you to accept a browser-session model rather than the official Business API.
- Who is it for?
- Adopt GOWA if you need several WhatsApp accounts behind one HTTP surface and you are comfortable linking them as Web devices. Do not adopt it if you need an officially sanctioned messaging channel, guaranteed uptime, or a bundled dashboard, because the UI now lives in a separate repository and the server fetches it at startup.
- Can I use it commercially?
- Yes. MIT 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 Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap GOWA fills between WhatsApp Web and an HTTP API
WhatsApp Web is a browser session, not an interface you can script against. GOWA turns that session into a long-running Go process that speaks HTTP. The README describes it as a WhatsApp REST API with support for UI, multi account, webhooks, MCP and Chatwoot, built with Golang for efficient memory use.
The audience is narrow and specific. If you are wiring a support inbox, an alerting bot or an internal tool that must send and receive WhatsApp messages from your own infrastructure, and you are willing to run the account as a linked device, GOWA gives you endpoints instead of a browser automation script. The README points to docs/openapi.yaml as the endpoint reference, which is the right place to look before writing any client code.
What it is not: an official Meta product. The project links accounts the same way a phone or desktop client does, and the documentation frames everything around that linked-device model. Anyone who needs a sanctioned business channel should stop reading here.
How the server, devices and webhooks fit together
The architecture is a single process with several surfaces. REST and MCP share one mode: since v9, running `./whatsapp rest` serves both the API and an MCP endpoint at `/mcp`. There is no separate `mcp` subcommand anymore, which the README lists as a breaking change from earlier versions.
Multi-account support arrived in v8. You can connect and manage several WhatsApp accounts in one server instance, with endpoints under `/devices`. The consequence is scoping: every device-scoped REST call must carry either an `X-Device-Id` header or a `device_id` query parameter. If exactly one device is registered, that device becomes the default, which keeps single-account scripts working without changes.
WebSockets follow the same rule. The README says to connect to `/ws?device_id=<id>` to scope a socket to one device. When Basic Auth is enabled, browsers cannot attach headers to a WebSocket handshake, so the documented workaround is `/ws?device_id=<id>&authorization=<base64(user:pass)>`. The README itself warns to use TLS because the credential is visible in the URL. That is a real trade-off, not a footnote.
Webhooks carry a top-level `device_id` alongside the event and payload. The README gives this shape:
{
"event": "message",
"device_id": "[email protected]",
"payload": { ... }
}Any receiver written against pre-v8 payloads needs updating, because the device identifier now sits outside the payload object.
Installing GOWA from Docker and sending a first message
The README offers release binaries, Docker Hub and GitHub Container Registry images, and notes ARM and AMD64 builds. The repository also ships a docker-compose.yml, which is the shortest path to a running instance.
The compose file builds from `./docker/golang.Dockerfile`, maps port 3000, reads environment variables from `src/.env`, and mounts `./storages` and `./statics`. A comment in the file states that the entrypoint chowns the storage directories for `gowauser` (uid 20001, gid 20000) on start, which matters if you bind-mount host directories.
docker compose up -dAfter the container starts, the API listens on port 3000. The README documents CLI flags such as `--port 8000` and `--debug true` for binary deployments, and environment variables such as `WHATSAPP_AUTO_REJECT_CALL=true` for container deployments. Basic Auth accepts multiple credentials with the `--basic-auth` flag, for example `--basic-auth=kemal:secret,toni:password,userName:secretPassword`, or the short form `-b=...`.
For subpath deployments, `--base-path="/gowa"` lets the service sit under a prefix. The dashboard is a separate story: since v9 the UI lives in aldinokemal/gowa-ui and ships as a single `gowa-ui.html`. The server downloads the latest dashboard release at startup, verifies its SHA-256 digest, caches it under `storages/ui/`, and serves it at `/`. That download is a startup dependency you should plan for.
Sticker conversion and media handling are where the edge cases live
The feature list is broad, but the sticker pipeline is the one with hard numeric limits, and it is worth reading closely because failures there are silent to the sender.
Images sent as stickers are converted to WebP and resized to 512x512 pixels, with transparency preserved for PNG sources. JPG, JPEG, PNG, WebP and GIF are accepted. Animated WebP stickers are supported but must meet WhatsApp's own requirements: exactly 512x512 pixels, under 500 KB, and no longer than 10 seconds. The README is explicit that a sticker failing these checks must be resized first, and it points to ezgif.com as an external tool rather than doing the work itself. If your pipeline generates animated stickers, that constraint belongs in your validation step, not in a support ticket later.
Other defaults shape behaviour at scale. Automatic media download is on by default, and `--auto-download-media=false` turns it off. Status media is downloaded unless `--ignore-status-media=true` is set. Incoming calls can be rejected with `--auto-reject-call=true` or `WHATSAPP_AUTO_REJECT_CALL=true`, and the README points to docs/webhook-payload.md for call events. Presence on connect defaults to `unavailable`, which registers the push name without going online and preserves phone notifications; `available` marks the account online and suppresses them. None of these are exotic, but each one changes what your webhook receiver sees.
Where GOWA is the wrong tool
The linked-device model is the limitation that sits under everything else. A WhatsApp account has a finite number of companion device slots, and GOWA occupies one. If your organisation already runs WhatsApp Web or Desktop on several machines, adding GOWA may push you into slot contention rather than solving anything.
The second limitation is the dashboard. In v9 the UI moved out of this repository. The server fetches the latest dashboard release at startup and verifies its SHA-256 digest, which the README discusses under supply-chain pinning and air-gapped deployment. In an air-gapped environment, that startup fetch cannot succeed unless you have provisioned the UI some other way. The README documents the `APP_UI_*` settings for this, so the workaround exists, but it is configuration you must do before first boot, not after.
The third is version churn. The README devotes a section to breaking changes across v6, v7, v8 and v9. REST mode required an explicit `rest` subcommand from v6. Binaries moved to GoReleaser in v7. Device scoping and webhook payload shape changed in v8. MCP merged into `rest` in v9. If you pin a version and stop reading release notes, an upgrade will break your client.
Finally, if you need delivery guarantees, template messages or compliance paperwork, this is the wrong category of tool entirely.
Alternatives: the underlying Go library, or Baileys in Node
The most direct alternative is the library GOWA itself is built on top of the same protocol stack. Using it directly means you write the Go process, the HTTP layer, the device registry and the reconnection logic yourself. You gain full control over payload shapes and you avoid the breaking-change cadence documented above. You lose the OpenAPI spec, the `/devices` endpoints, the webhook contract and the MCP surface, all of which already exist here.
On the Node side, Baileys occupies a similar position: a WhatsApp Web multi-device library rather than a server. A Node team that wants TypeScript types and an npm workflow may prefer that ecosystem, at the cost of running a Node runtime where GOWA ships a single Go binary and a Docker image with a documented memory-efficiency goal.
The practical difference is packaging. GOWA is a server with a documented port, environment variables, a compose file and an OpenAPI document. The libraries are building blocks. Choose based on whether you want to operate a service or write one.
Maintenance, licensing and upgrade cost
The repository is not archived. The most recent release listed is v9.4.0 on 2026-09-19, following v9.3.1 on 2026-09-09 and v9.3.0 on 2026-08-29. Those dates are close together, so the project is moving quickly, and the breaking-changes section is the price of that pace.
The licence is MIT, and the repository carries a LICENCE.txt at the top level. MIT is permissive, so redistribution and modification are allowed under its terms. That is a statement about the licence text, not legal advice; if you are embedding GOWA in a commercial product, read LICENCE.txt and the dependency licences yourself.
The README also asks for Patreon support from anyone using the tool to generate income. That is a funding request, not a licence condition, but it is a signal about how the maintainer expects the project to be sustained.
Upgrade cost is concentrated in three places: the `rest` subcommand requirement, device scoping on every API call, and the top-level `device_id` in webhook payloads. Budget for a test pass against docs/openapi.yaml on every major version bump.
Editorial conclusion
Adopt GOWA if you need several WhatsApp accounts behind one HTTP surface and you are comfortable linking them as Web devices. Do not adopt it if you need an officially sanctioned messaging channel, guaranteed uptime, or a bundled dashboard, because the UI now lives in a separate repository and the server fetches it at startup. Before committing, verify three things on your own host: that the storage volume survives a container restart, that your device-scoped requests carry X-Device-Id or device_id, and that the webhook receiver handles the top-level device_id field that v8 added.
Frequently asked questions
How do I multi select on WhatsApp Web?
The README does not document a multi-select feature in the WhatsApp Web interface. What it does document is multi-account support since v8, where several WhatsApp accounts are connected and managed in one server instance through endpoints under /devices.
How do I link WhatsApp to more than 4 devices?
The README does not state a device limit or describe a way to exceed one. It does describe multi-device support introduced in v8, where multiple WhatsApp accounts can be connected and managed simultaneously in a single server instance.
Is WhatsApp using WebSocket?
The README does not describe WhatsApp's internal transport. It does document that GOWA exposes its own WebSocket endpoint at /ws, which you scope to a device with /ws?device_id=<id>.
What are the disadvantages of WhatsApp Web?
The README does not list disadvantages of WhatsApp Web itself. It does describe constraints that follow from the linked-device model, such as device-scoped API calls needing an X-Device-Id header or a device_id query parameter, and the WebSocket credential being visible in the URL when Basic Auth is enabled.
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/aldinokemal-go-whatsapp-web-multidevice)