Detection coverage
Where detection runs
There is one detector, and it runs on your device: in browser WASM, in the desktop app, in the local proxy, or in an SDK you embed. It runs before any byte is sent.
There is no server-side detection, and no server-side detection tier you can opt into.
The gateway exposes no /v1/detect, /v1/tokenize, /v1/detokenize or /v1/reconstruct
route — those were retired, and the detection engine was deleted from the gateway at the code
level rather than disabled behind a flag. See
Content-blindness attestation.
That matters for reading the rest of this page: coverage below is a property of the engine
build your device loaded, not of a plan or a server-side setting. That build is identified by
an engine hash and a ruleset version, both checkable against a public allowlist you can rebuild
from source — see Reproducibility and
GET https://api.cloakapi.io/api/v1/engine/hashes.
The two detection lanes
The engine has two lanes with genuinely different guarantees. Conflating them is the most common way privacy copy overclaims, so they are kept apart here — and they are reported separately on the benchmark page for the same reason.
| Deterministic lane | Name / organisation / place lane | |
|---|---|---|
| What it finds | Identifiers with a defined structure | Free-form person, company and place names |
| How | Pattern rules + checksum validation | Gazetteers, plus an optional on-device model |
| Model needed | No — always on, no download | Gazetteer floor always on; model tier optional |
| Guarantee | Deterministic for the covered forms | Best-effort, recall-bounded |
Lane 1 — deterministic structured identifiers
Around 140 identifier rules ship in the current ruleset. No model is involved and nothing is downloaded; this lane is always on. It covers:
- Contact and network — email addresses; phone numbers (international form, and cue-anchored national form); IPv4 and IPv6 addresses; MAC addresses; URLs.
- Payment and banking — payment card numbers; IBAN; BIC/SWIFT; ABA routing; UK sort-code + account; national account and payment-reference formats; Bitcoin, Ethereum and stablecoin addresses.
- Government and personal identity — roughly 60 national and personal identity-number formats across the Americas, Europe, the Nordics, Asia and Oceania (SSN, NINO, personnummer, CPR, HETU, kennitala, NISS, NIF, codice fiscale, BSN, PESEL, SIN, Aadhaar, PAN, My Number, CPF, CURP, RUT and others), plus passports and passport MRZ lines, driving licences, green-card / USCIS receipts and voter IDs.
- Company identity — around 15 VAT and company-registry formats (UK/EU/NO/CH VAT, ABN, CNPJ, GSTIN, HRB, CVR, organisationsnummer, Y-tunnus, KvK, Companies House, …).
- Health — NHS number, helsenummer, HPR, Medicare, Versichertennummer, insurance numbers, prescription and lab-order references, ICD-10 and SNOMED codes.
- Location and device — around 12 postal-code formats plus city- and cue-anchored postal forms; GPS coordinate pairs; IDFA / GAID advertising identifiers.
- Credentials and dates — API keys and bearer secrets, JSON Web Tokens, dates of birth.
- Other — biometric template references, medical record numbers, alias handles.
Checksums are used wherever the format has one. Twenty-one validators are implemented,
including Luhn (payment cards, Canadian SIN), IBAN mod-97, Verhoeff (Aadhaar), and the NHS,
Dutch BSN, Brazilian CPF, Chilean RUT, Mexican CURP, Australian ABN, Belgian NRN, Czech/Slovak
rodné číslo, Chinese RIC, Danish CVR, Finnish Y-tunnus, Japanese My Number and Norwegian
organisation-number checks. A class that carries a checksum is replaced with a locked
[CLK-…] token rather than a plausible-looking stand-in, so no downstream reader can mistake
the replacement for a genuine identifier.
A normalisation pre-pass runs before matching. Invisible and format characters (zero-width
space/joiner, soft hyphen, BOM, word joiner, bidi controls, variation selectors, Unicode tags)
are stripped, fullwidth and compatibility ASCII is folded to ASCII, and non-ASCII decimal digits
from 46 scripts (Arabic-Indic, Devanagari, Bengali, Thai and so on) are folded to 0–9. The
pre-pass keeps a byte-offset map back to the original string, so a match found on the folded
text is cloaked at its exact original bytes — the invisible characters included.
Lane 2 — names, organisations and places
Free-form names have no checksum and no fixed format, so this lane is best-effort and recall-bounded. It has a deterministic floor plus optional heavier tiers:
- Always on: a deterministic gazetteer floor. Frequency-tiered given names and surnames
across many cultures and scripts (Latin, Arabic, Hebrew, Devanagari, Bengali, Gujarati,
Gurmukhi, Oriya, Tamil, Telugu, Kannada, Malayalam, Thai), plus locale name/place and
world-places datasets. Name entries are transcribed from published national statistics-authority
name-frequency lists (SSB, INSEE, US Census/SSA, Destatis and others); place entries are
transcribed from a GeoNames
cities1000snapshot (ODbL-1.0). Nothing is fetched at build time — the per-source provenance, licence, row count and hash is published, machine-readable, at/.well-known/corpus-integrity.json. Pure and synchronous — no model, no network, no load delay. - Optional, on-device: an expanded gazetteer. A larger name asset a surface downloads on demand and caches once.
- Optional, on-device: a quantized transformer NER. A multilingual BERT
token-classification model (
Xenova/bert-base-multilingual-cased-ner-hrl, q8 ONNX, ~170 MB) covering ten high-resource languages. Browser surfaces run it through transformers.js in WebAssembly; the desktop app runs the same model natively through ONNX Runtime. It finds names by context rather than by dictionary membership, and merges additively with the gazetteer. The files are self-hosted by CloakAPI and fetched on first use, so nothing is pulled from a model hub at runtime and no text leaves the device. It is fail-safe: any load or inference error falls back to the gazetteer tier, and a send is never silently blocked by it. - Local proxy: an optional loopback-only on-device mini-model (Ollama running Phi-3.5-Mini by default) covers the name lane there. By default the proxy fails closed if that model is unreachable, rather than letting a name through. See Local proxy.
The benchmark page measures both configurations separately — engine-only (before any model is downloaded) and engine + on-device model (the shipped app default) — because they are genuinely different systems and the gap between them on this lane is large.
Known evasions and residuals
These techniques are known to bypass or degrade detection. Honest scoping is more useful to you than a longer capability list.
Mitigated
Invisible-character and compatibility-form insertion. Zero-width and format characters inserted into an identifier, fullwidth digits, and non-ASCII script digits are handled by the normalisation pre-pass above, and the match is cloaked at the original byte positions.
Base64-wrapped payment cards. A base64 token that decodes to a Luhn-valid 13–19-digit run is detected and cloaked. It is checksum-gated, so it cannot manufacture a false positive.
Fully space-separated national IDs. A digit-by-digit spaced form (1 2 3 - 4 5 - 6 7 8 9)
is recovered by a targeted, shape-gated span source.
Email addresses fragmented by OCR. A line-wrap inside an email-shaped run is repaired before cloaking. This closed a real leak found on the wire; the full account — including why the re-test also asserts the address was still readable afterwards — is on Verification & evidence.
Not mitigated
Homoglyph substitution. Replacing characters with visual look-alikes from another script
(Cyrillic о for Latin o in an email address) evades the pattern rules. The normalisation
pre-pass folds compatibility forms and digits but does not perform Unicode confusable
folding (UAX #39). Roadmap item.
General base64 and other encodings. Only the checksum-gated card case above is decoded. Arbitrary base64-encoded PII — an encoded email address, for instance — passes through as an opaque token. A general decode-and-re-detect pass is a roadmap item.
Fragmentation of classes other than email. The OCR repair is scoped to email-shaped runs. A value split across a line-wrap, a page boundary or an intervening markup element in another class may not match, because detection operates on the text as the device sees it.
Bare, uncued digit runs. A digit run that could be a phone number but carries no cue word, no country prefix and no formatting is deliberately not treated as a phone number — treating every such run as one produces constant false positives on order numbers, reference codes and quantities. The same reasoning applies to national-ID forms that are both uncued and carry no validating checksum. The cued, internationally-formatted and conventionally-formatted forms all cloak. This is a chosen precision trade, not an oversight.
Names and places outside the covered data. The gazetteer floor is multilingual but finite, and the optional model covers ten high-resource languages (ar, de, en, es, fr, it, lv, nl, pt, zh). Rare names, unlabelled single-token brand names, and names in scripts thinner in the gazetteers will be missed — the per-class organisation and person figures on the benchmark page show the size of that residual. The cased model also misses ALL-CAPS and all-lowercase names, which the gazetteer’s case handling only partly covers.
Semantic identification without an identifier. “The patient in bed 7”, “the employee who resigned last Tuesday” — text that identifies someone through context alone, with no identifier present. No detector addresses this, and no receipt claims to. It is out of scope for the engine.
Roadmap
| Item | Status |
|---|---|
| Unicode confusable folding (UAX #39) | Planned |
| General base64 decode-and-re-detect pass | Planned |
| Fragmentation repair beyond email-shaped runs | Planned |
| Multilingual name detection | Shipped — on-device model, measured on the detection benchmark |
| Per-class precision/recall | Published — see the detection benchmark (corpus v1.0, ruleset 1.4.29) |
| Evaluation against Ai4Privacy and PII-NER benchmarks | Planned |
We do not claim precision or recall numbers we have not measured, and we do not generalise the numbers we have: the benchmark is one corpus, one scorer, one run, with its biases documented on that page.
What this means for your deployment
- Structured identifiers — emails, cards, IBANs, national IDs, health and company numbers, IPs, postal codes — are the strong case: deterministic, checksum-validated where a checksum exists, no model required, and measured both on the benchmark corpus and on the wire.
- Free-form names, organisations and places are best-effort. Treat them as a recall-bounded layer, not a control you can rely on alone — and note that the organisation class is the weakest of the three.
- Adversarial input designed to evade detection: the unmitigated techniques above apply. Consider additional sanitisation on your side.
- Review before send. Every interactive surface shows you what will leave before it leaves. For anything sensitive, that review is the last and strongest check.
For high-assurance environments, treat the engine as a defence-in-depth layer rather than a sole control. Tokenising known-sensitive fields explicitly at your application layer, before they ever enter a text prompt, is a stronger guarantee than relying on automatic detection of any kind.
No legal conclusions
Nothing on this page is a statement about your regulatory obligations or whether any particular deployment satisfies any particular law. Those are determinations for you and your advisers. What we publish are architectural facts and measurements with their method and scope attached.