Skip to main content

Documentation Index

Fetch the complete documentation index at: https://zapo.to/llms.txt

Use this file to discover all available pages before exploring further.

Besides the standard companion mode (linking via QR / pairing code, like WhatsApp Web), zapo can connect as a primary mobile client — speaking the Android app’s protocol over a raw TCP socket.
Mobile support is stable and functional. The one thing zapo does not provide is a registration API — requesting an SMS/voice code, submitting an OTP, or approving a takeover. Registering a number is complex and requires a physical phone, so it’s intentionally out of scope. You connect with an already-registered credential set, and that path is solid.

How it differs from companion mode

Companion (default)Mobile
TransportWebSocket (wss://…)TCP socket (tcp://g.whatsapp.net:443)
AuthQR / pairing codePre-registered credentials + device fingerprint
IdentityLinked devicePrimary account
PlatformBrowser (chrome, …)android
Device infoNot requiredRequired (hardware fingerprint)

Enabling mobile mode

Mobile mode is triggered by the mobileTransport option (a WaMobileTransportOptions). Its presence — or persisted deviceInfo in the loaded credentials — switches the client from the WebSocket transport to the TCP transport.
const client = new WaClient(
  {
    store,
    sessionId: 'mobile',
    mobileTransport: {
      deviceInfo: {
        manufacturer: 'OnePlus',
        device: 'OnePlus8Pro',
        osVersion: '12',
        osBuildNumber: 'SKQ1.210216.001',
        appVersion: '2.23.1.1',
        mcc: '55',  // mobile country code (optional)
        mnc: '11'   // mobile network code (optional)
      },
      passive: false // send keep-alives
    }
  },
  logger
)

await client.connect()

WaMobileTransportOptions

FieldTypeNotes
deviceInfoWaMobileTransportDeviceInfoRequired hardware fingerprint (see below).
tcpUrlstringDefaults to tcp://g.whatsapp.net:443.
passivebooleanfalse sends keep-alives; true is idle.
pushNamestringDisplay name.
yearClass / memClassnumberDevice performance/memory class.

WaMobileTransportDeviceInfo

manufacturer, device, osVersion, osBuildNumber, appVersion are required; mcc, mnc, localeLanguageIso6391, localeCountryIso31661Alpha2, phoneId, deviceBoard, deviceModelType are optional. A stable fingerprint across runs matters — persist it and reuse the same values.

Credentials

Mobile mode needs an already-registered credential set: a WaAuthCredentials with meJid populated, platform: 'android', and deviceInfo attached. You seed these into the auth store before connecting (e.g. imported from a device bundle).
Once credentials with deviceInfo are persisted, later reconnects automatically use the mobile TCP transport — you don’t need to pass mobileTransport again.

Registration events

While your mobile session is connected, you’re notified when someone tries to register your number on another device — a security-relevant signal, surfaced as these events:
client.on('mobile_registration_code', (event) => {
  // WaRegistrationCodeEvent — someone requested a code to register YOUR number elsewhere
  console.log('registration code issued:', event.code, 'expires:', event.expiryTimestampMs)
})

client.on('mobile_account_takeover_notice', (event) => {
  // WaAccountTakeoverNoticeEvent — another device is taking over your number
  console.log('takeover attempt from', event.newDevicePlatform, event.newDeviceName)
})
EventPayloadMeaning
mobile_registration_code{ code, expiryTimestampMs, fromDeviceId }Someone requested a registration code to register your number on another phone; the issued code is surfaced here.
mobile_account_takeover_notice{ serverToken, attemptTimestampMs, newDeviceName?, newDevicePlatform?, newDeviceAppVersion? }Another device is claiming (taking over) your number.
These events are informationalzapo surfaces them but intentionally does not expose methods to submit a code or respond to a takeover. Provisioning a number is done on a real phone; bring the resulting credentials to zapo and connect.

Standard features still apply

Once connected in mobile mode, the rest of the API is unchanged — client.message, client.group, events, stores, etc. all work the same way. The only difference is the transport and the auth/identity model.
Last modified on May 27, 2026