Local emulator of the Meta WhatsApp Cloud API: signed webhooks, chat-style web UI, one Docker image
351
whaloc is a local emulator of the Meta WhatsApp Cloud API (Graph API v25.0) in a single
Docker image, configured entirely through environment variables. It plays Meta's whole side of a
WhatsApp integration โ accepting sends of every message type, minting Meta-shaped wamids,
walking the status ladder, moderating templates, storing media and POSTing signed webhooks back
to your app โ so an application that talks to the Cloud API runs entirely offline: no Meta app,
no business number, no public tunnel. Point your app's GRAPH_API_BASE_URL at whaloc, open the
web UI, and be the WhatsApp user on the other side of the conversation.
It is deterministic by default: nothing fails, drops or changes state on its own. Rate limits, expired tokens, template rejections, media expiry and number changes all exist โ and happen only when you trigger them, from the UI or from a test.
๐ Full documentation lives on GitHub: READMEโ ยท integration guideโ ยท behavioral contract (SPEC)โ ยท issuesโ
docker run --rm -p 8080:8080 \
-e WHALOC_WEBHOOK_URL=http://host.docker.internal:3001/meta-webhooks \
-e WHALOC_APP_SECRET=dev-app-secret \
-e WHALOC_WEBHOOK_VERIFY_TOKEN=dev-verify-token \
dgadelha/whaloc:latest
Open http://localhost:8080โ for the chat-style web UI and point the app under test at
GRAPH_API_BASE_URL=http://localhost:8080/v25.0 (from another container on the same compose
network: http://whaloc:8080/v25.0).
Seeded IDs are derived deterministically โ the same on every machine โ so this works verbatim against a fresh container (any non-empty bearer token is accepted):
curl -X POST http://localhost:8080/v25.0/573542517421694/messages \
-H 'Authorization: Bearer dev-token' -H 'Content-Type: application/json' \
-d '{"messaging_product":"whatsapp","to":"5571990000001","type":"text","text":{"body":"olรก"}}'
The seed also ships a pre-approved, zero-parameter template (hello_whaloc), so a
type: "template" send works cold too. All seeded IDs are shown, with copy buttons, in the UI's
Settings view.
Range), the resumable Upload API, templates with Meta's filters and cursor paging,
phone-number management, business profile, subscribed_apps โ answering with Meta's exact
envelopes, fbtrace_id and error codes.X-Hub-Signature-256-signed over the exact bytes sent, with a browsable, redeliverable
delivery log.Environment variables only โ blank counts as unset, and an invalid environment prints every problem and exits. The most common ones:
| Variable | Default | Purpose |
|---|---|---|
WHALOC_PORT | 8080 | Listen port (one port serves the API mock, control plane, UI) |
WHALOC_PUBLIC_URL | http://localhost:8080 | Base for generated media URLs โ must be reachable by your app |
WHALOC_WEBHOOK_URL | unset โ webhooks disabled | Where signed webhooks are POSTed |
WHALOC_APP_SECRET | unset โ unsigned | HMAC key for X-Hub-Signature-256 |
WHALOC_WEBHOOK_VERIFY_TOKEN | unset | Token echoed in the hub.challenge handshake |
WHALOC_SEED | 1 WABA, 1 number, 1 template | JSON seed; omitted IDs are derived deterministically |
WHALOC_DB_PATH | :memory: | SQLite file for persistence, e.g. /data/whaloc.db |
WHALOC_MEDIA_BACKEND | local | local directory or s3 (MinIO, R2, AWSโฆ) |
The full referenceโ covers seeding, status ladder timing, template auto-approval, strict tokens, media TTL and the S3 settings.
Persistence: the default database is in-memory โ every restart starts from the seed. Mount
the declared /data volume and set WHALOC_DB_PATH=/data/whaloc.db to keep state. The container
runs as the unprivileged node user (uid 1000).
latest โ the current release (moves with tagged releases and main)X.Y.Z, X.Y, X โ the semver ladder, from release tagssha-<short> โ every build, pinned to a commitImages are multi-arch (linux/amd64, linux/arm64) and published with SLSA provenance and an
SBOM; provenance is verifiable with
gh attestation verify oci://docker.io/dgadelha/whaloc:latest --owner dgadelha. Also published
to GitHub Container Registry as ghcr.io/dgadelha/whaloc.
MITโ . whaloc is an independent reimplementation for local development, unaffiliated with and unendorsed by Meta.
Content type
Image
Digest
sha256:32fd339e8โฆ
Size
59.5 MB
Last updated
18 days ago
docker pull dgadelha/whaloc