Skip to main content

Requirements

zapo requires Node.js >= 20.9.0. The package ships dual ESM/CJS builds and full TypeScript types.

Install the core package

The core package has no mandatory runtime dependencies. Everything else — storage, logging, and the WebSocket transport — is an opt-in peer dependency, so you only install what you use.

The package ecosystem

zapo-js is the only required install. Everything else is an optional @zapo-js/* package you add as needed:
zapo-js — core client, coordinators, store contract
@zapo-js/store-sqlite — SQLite backend
@zapo-js/store-postgres — PostgreSQL backend
@zapo-js/store-mysql — MySQL backend
@zapo-js/store-redis — Redis backend
@zapo-js/store-mongo — MongoDB backend
@zapo-js/media-utils — thumbnails, probes, waveforms
@zapo-js/voip — WhatsApp voice calls
@zapo-js/wam — WhatsApp Web telemetry parity (analytics)
@zapo-js/mcp-server — dev tool: drive from an AI agent
@zapo-js/fake-server — dev tool: in-process test server

Add a storage backend

zapo persists authentication and Signal state through a pluggable store. Pick the backend that matches your deployment and install its package:
You can also run with no backend at all — the built-in memory store works out of the box and is great for tests. It just does not survive a process restart, so you would re-pair on every boot.

Optional peer dependencies

Install these only if you use the corresponding feature:
  • pino + pino-pretty — required only if you use createPinoLogger. Without them, the built-in ConsoleLogger is used.
  • ws — only needed to route the WebSocket through a proxy. The runtime’s native WebSocket can’t take an HTTP Agent/dispatcher, so zapo falls back to ws for the proxy.ws leg. Without a proxy, the built-in WebSocket is used and you don’t need this package.
  • argo-codec — only needed for mobile connections (for now). The standard companion (QR / pairing-code) flow does not use it.

Sending media

@zapo-js/media-utils is effectively required to send usable media. Media still uploads without it, but there’s no processor to generate thumbnails/previews, image-video dimensions, or voice-note waveforms — so it can render as a plain attachment or with no preview. Install it whenever your app sends images, video, audio, documents, or stickers.
It shells out to ffmpeg/ffprobe and uses sharp, so make sure those binaries are available. See the media guide for how to wire the processor into the client.
@zapo-js/media-utils also lists file-type (^19) as an optional peer dependency. Install it (npm install file-type) to enable automatic mimetype detection — without it, the media guide’s mimetype resolution falls back to requiring an explicit mimetype on each send.

Voice calls

Install @zapo-js/voip to place and receive WhatsApp voice calls. It ships as a WaClient plugin and pulls two peer dependencies of its own:
  • @roamhq/wrtc — SCTP for the relay transport.
  • libmlow-wasm — WhatsApp’s Opus profile, as WebAssembly (no native build).
See the VoIP guide for how to wire voipPlugin() into the client.

Telemetry parity

Install @zapo-js/wam to make the session emit the client-side w:stats analytics batches a real WhatsApp Web tab sends — a wire-parity / anti-fingerprinting improvement, not required for messaging.
The only peer dependency is zapo-js. The WAM event registry (@vinikjkkj/wa-wam) is pinned as a regular dependencies entry on the plugin, so it comes down transitively. See the WAM guide for how to wire wamPlugin() into the client. It is opt-in: skip it unless you specifically want the parity.

Verify your setup

Next, head to the quickstart to connect and send your first message.
Last modified on July 12, 2026