← deemwar engineering examples Runnable · Node · zero deps · free · no credentials

Your WhatsApp account is restricted. Your dashboard looks fine.

WhatsApp restricts accounts that send through unofficial clients, and it does it quietly on purpose. Your established customers keep receiving messages. Every new lead gets nothing. Nobody is told — not them, not you.

Why it is invisible

An existing conversation already carries a privacy token (tctoken), so it is unaffected by the restriction. Only new chats are refused, with error 463. Baileys names it exactly that, in src/Utils/decode-wa-message.ts:

/**
 * 1:1 message missing privacy token (tctoken). Usually means the account is
 * restricted: WhatsApp blocks starting new chats but preserves existing ones,
 * since established chats already carry a tctoken.
 */
MessageAccountRestriction: '463',

This is why an overall send success rate cannot see it. Most of your traffic is to people you already talk to, and all of that still works. The part that is broken is the part that grows your business.

The check that actually finds it

A restriction has a start time. Before it, new chats succeed; after it, they do not. Averaging across your whole history buries that flip under every lead you ever landed — the same mistake as reading an overall CI pass rate straight through a billing outage. So the question is not "what is my success rate", it is "since the first 463, what has happened to new chats?"

$ node check.js --demo WhatsApp account-restriction check Records: 21 · established chats: 5 · new chats: 16 established chats succeeding : 5/5 (100%) new chats succeeding : 10/16 (63%) new chats refused with 463 : 6 since the FIRST 463 : 6/6 new chats refused, 0 got through DIAGNOSIS: ACCOUNT RESTRICTED. New conversations are being refused with 463 while your established chats keep working. That asymmetry is the restriction fingerprint -- an established chat already holds a tctoken, so it is unaffected, which is exactly why your overall success rate still looks acceptable. Every new lead since the first 463 has received NOTHING, with no error surfaced to them and none to you unless you were looking for this. First refusal: 2026-09-12T10:26:00Z ([email protected])

Read those two lines together: overall new-chat success still reads 63%, which would pass any dashboard you own. Since the first refusal it is 0 of 6. That gap is the entire bug.

It separates three things that all look the same

Run it

node check.js --demo          # the shape of the answer
node check.js sends.ndjson    # your own data

sends.ndjson is one JSON object per line, appended by your own send loop — {"ts":…,"jid":…,"ok":true|false,"code":463}. Zero dependencies, no credentials, nothing leaves your machine. Exit code 2 on a restriction, so you can put it in a cron and be told rather than having to look.

What it does not do

It does not unrestrict your account, and nothing in code can. Sending harder is how a restriction becomes a ban. This tells you when it started so you can stop early and deal with the account, instead of hearing about it from a customer a week later.

It also does not prove delivery. A clean result means new chats are not being refused — not that anyone received or read anything.

What we verified, and what we did not

The 463 semantics are quoted from Baileys' own source, and the reports come from issues #2688, #2698 and #2707. We did not get an account restricted on purpose to test this — deliberately provoking a ban on a live number is not something we would do to our own account or suggest you do to yours. The classifier is verified against constructed fixtures in both directions: it fires on the restriction pattern, and stays silent when failures are spread evenly.

Get the code