Sanitext

Detect and redact email addresses with the Sanitext API

Sanitext finds email addresses with the EMAIL label. POST text to /v1/detect to get spans with byte offsets, a confidence score, and the matched text. POST to /v1/redact to replace each address with [EMAIL]. It runs on our own model, so raw text never goes to a third-party LLM.

An email address is one of the most common pieces of PII in support tickets, logs, chat transcripts, and form data. Sanitext detects email addresses with a single label, EMAIL, and either returns their exact position or masks them in place. This page explains what counts as an email, how detection works, the edge cases we handle, and how it behaves across languages.

EMAIL label: detect vs redact

AspectPOST /v1/detectPOST /v1/redact
Outputentities array with spansredacted text string
Email formatlabel "EMAIL" + start/end byte offsets, score, texteach address replaced by [EMAIL]
Best forcustom masking, hashing, tokenization, reviewfast drop-in masking before storage or LLM
Multiple emailsone span per addressevery address masked in place
Threshold controlyes (default 0.5)yes (default 0.5)
Raw text retentionnone (counts and timings only)none (counts and timings only)

What counts as an email address?

An email address is any string that identifies a mailbox: a local part, an @ sign, and a domain. Sanitext tags all of these with the EMAIL label. It is treated as direct PII because it usually maps to one real person or account.

Sanitext detects email addresses in context, not just by matching a fixed pattern. It picks up addresses inside sentences, after labels like "Email:", inside quotes, and mixed with other text and other PII such as names and phone numbers.

  • —Standard addresses: jane@example.com
  • —Subdomains and country domains: jane.doe@mail.example.co.uk
  • —Plus and dot variants: jane.doe+news@example.com
  • —New-style TLDs: founder@startup.io, hello@brand.dev
  • —Addresses next to other PII (names, phones) in the same line

How does email detection work?

Send your text to POST /v1/detect. Sanitext returns an entities array. Each detected email address is one entity object with five fields: label ("EMAIL"), start and end byte offsets, a score, and the matched text.

The start and end values are byte offsets, not character counts, so multibyte text lines up correctly. Use those offsets to highlight, hash, tokenize, or mask the address yourself. Each response also includes a count of all entities and an ms timing.

You can set a threshold in the request body (default 0.5). Raise it to keep only high-confidence matches, or lower it to catch more borderline strings. The score on each span tells you how confident the model is.

Which email edge cases and formats are handled?

Real text is messy, so email addresses do not always look clean. Sanitext is built to handle common variations rather than a single regex shape.

Detection coverage is strong but not perfect. Heavily obfuscated addresses (for example "jane [at] example [dot] com") may not always be caught. Verify against your own data before production use, since this is a data-minimization aid, not an anonymization guarantee.

  • —Plus-addressing and dotted local parts (jane.doe+tag@example.com)
  • —Multiple addresses in one request, each as its own span
  • —Addresses inside parentheses, quotes, or after "Email:" labels
  • —Long subdomain chains and two-part country TLDs (.co.uk)
  • —Addresses adjacent to URLs without confusing the two labels

Does it detect email addresses in other languages?

Email syntax is the same worldwide, but the surrounding text is not. Sanitext detects email addresses in 30+ languages, so it still finds the address when it sits inside Spanish, French, German, Dutch, Portuguese, or Italian sentences and after localized labels like "Correo:" or "Courriel :".

Because offsets are measured in bytes, accented and non-Latin characters around the address do not break the spans. Coverage can vary by language, so test with samples from your real traffic.

bash

# Detect email addresses
curl https://api.sanitext.app/v1/detect \
  -H "Authorization: Bearer pf_live_…" \
  -H "Content-Type: application/json" \
  -d '{"text":"Reply to jane.doe+news@sub.example.co.uk or sales@acme.com"}'

# Response
# {
#   "entities": [
#     { "label": "EMAIL", "start": 9,  "end": 40,
#       "score": 0.99, "text": "jane.doe+news@sub.example.co.uk" },
#     { "label": "EMAIL", "start": 44, "end": 58,
#       "score": 0.98, "text": "sales@acme.com" }
#   ],
#   "count": 2, "ms": 27
# }

# Redact email addresses (same body, masked output)
curl https://api.sanitext.app/v1/redact \
  -H "Authorization: Bearer pf_live_…" \
  -H "Content-Type: application/json" \
  -d '{"text":"Reply to jane.doe+news@sub.example.co.uk or sales@acme.com"}'

# { "redacted": "Reply to [EMAIL] or [EMAIL]", "count": 2, "ms": 24 }

FAQ

What label does Sanitext use for email addresses?+

Sanitext uses the EMAIL label for every detected email address. In /v1/detect it appears as the label field on each entity span, alongside byte offsets, a score, and the matched text. In /v1/redact each address is replaced by the literal token [EMAIL].

How do I redact every email but keep the rest of the text?+

POST your text to /v1/redact. Sanitext returns a redacted string where each email address is swapped for [EMAIL] and all non-PII text stays unchanged. The byte offsets from /v1/detect let you do custom masking, hashing, or tokenization instead.

Can Sanitext detect multiple email addresses in one request?+

Yes. Every email address in the text is returned as its own entity span with its own start and end byte offsets and score. The response includes a count field with the total number of detected entities for the request.

Does email detection send my data to a third-party LLM?+

No. Sanitext runs an open-weights model on our own Cloudflare infrastructure, so your text never goes to an external LLM. We log only counts and timings, not raw text. Detection is a data-minimization aid, not an anonymization or compliance guarantee.

Redact email addresses in 60 seconds

Sign up free for 300K characters, no card. Get an API key and run your first /v1/redact call from a curl command. See live pricing on the pricing page.

Get your free API key