open-wa
DocsMultiple sessions

Multiple sessions

Run more than one WhatsApp account with separate session profiles, API keys, and failure boundaries.

Multiple sessions

Give each WhatsApp account a unique sessionId and persistent browser profile. For separate Easy API processes, also assign a unique port and API key. The Easy API quick start covers installation and API-key setup; use the Docker guide when each session needs its own persistent volume.

One process per session

Separate processes keep browser failures, restarts, and API credentials scoped to one account. The commands below target the published v5.1.0 CLI; specify --host and --port explicitly for that release. Before running them, set different, nonempty SALES_API_KEY and SUPPORT_API_KEY values in your secret store or shell environment.

npx @open-wa/wa-automate@5.1.0 \
  --session-id sales --host 127.0.0.1 --port 8081 --api-key "$SALES_API_KEY"

npx @open-wa/wa-automate@5.1.0 \
  --session-id support --host 127.0.0.1 --port 8082 --api-key "$SUPPORT_API_KEY"

Keep the API processes on loopback or a private network and configure your reverse proxy with a separate upstream credential for each session. /health is public and can include QR or diagnostic data, so do not expose it through a public proxy. See Easy API security.

One Node.js process

Use one process when your application needs direct control of each runtime. Create and retain one runtime per session, and stop each runtime during application shutdown.

import { createClient } from '@open-wa/wa-automate';
import { PuppeteerDriver } from '@open-wa/driver-puppeteer';

const sessions = new Map();

for (const sessionId of ['sales', 'support']) {
  const runtime = await createClient({
    sessionId,
    userDataDir: `./private/sessions/${sessionId}`,
    driver: new PuppeteerDriver(),
    headless: true,
  });

  sessions.set(sessionId, runtime);
  await runtime.start();
}

Each runtime owns a browser context, so resource use grows with the number of active accounts. If one process exits, all its sessions stop; supervise and recover them as a unit or move sessions into separate processes when they need independent availability.

Route requests to the intended session

Keep the session-to-origin and session-to-key mapping in your application. Authenticate the upstream request with the key for that session and reject unknown session names before forwarding traffic.

SessionLocal API originAPI key source
saleshttp://127.0.0.1:8081SALES_API_KEY
supporthttp://127.0.0.1:8082SUPPORT_API_KEY

For example, a request to sales can be forwarded to the method route on its own API process:

const salesApiKey = process.env.SALES_API_KEY;
if (!salesApiKey) {
  throw new Error('Set SALES_API_KEY before sending requests');
}

const response = await fetch('http://127.0.0.1:8081/api/sendText', {
  method: 'POST',
  headers: {
    'content-type': 'application/json',
    'x-api-key': salesApiKey,
  },
  body: JSON.stringify({
    to: '447700900000@c.us',
    content: 'Your update is ready.',
  }),
});

if (!response.ok) {
  throw new Error(`The sales session returned ${response.status}`);
}

The exact input shape comes from the method contract; see the sendText reference. Do not let a user with access to one session inherit permission to send from another.

Recovery and capacity

Monitor each Easy API process separately and wait for /health to report connected: true and session.ready: true after startup or restart. A responding port establishes HTTP liveness only. Keep the session ID, profile directory, API key, logs, and restart policy paired so you can recover one account without changing another.

Browser memory, CPU, media work, sockets, and reconnect bursts determine how many sessions a host can support. There is no fixed safe count; add sessions only after measuring the workload on the intended host. For process supervision, use your platform's service manager or container runtime.

See authentication and session recovery for profile handling and configuration and CLI for runtime flags.

Was this helpful?

Your answer includes the page path and docs version.

On this page