Detect and redact phone numbers in text
Sanitext detects phone numbers with the PHONE label. POST text to /v1/detect to get spans (label, byte offsets, confidence score, matched text), or to /v1/redact to mask each number as [PHONE]. It handles local, international, and formatted numbers across 30+ languages.
Phone numbers are some of the messiest PII to catch with plain regex. They show up with country codes, dots, dashes, parentheses, spaces, or no spacing at all. Sanitext uses an open-weights model run on our own Cloudflare infrastructure, so detection works across formats and languages without sending your text to a third-party LLM.
Phone formats the PHONE label detects
| Format | Example | Detected |
|---|---|---|
| International + code | +1 (415) 555-0199 | Yes |
| 00 country prefix | 0044 20 7946 0958 | Yes |
| Local / national | (212) 555-0147 | Yes |
| Spaced grouping | 612 34 56 78 | Yes |
| Dotted / compact | 415.555.0199 | Yes |
| With extension | +1 415 555 0199 ext. 23 | Yes |
| Spelled-out digits | five-five-five | No |
What counts as a phone number?
The PHONE label covers any string Sanitext reads as a callable telephone number. That includes mobile, landline, toll-free, and VoIP numbers written in human text.
It catches numbers with or without a country code, with mixed separators, and with common prefixes like +, 00, ext, or x for extensions. The model uses surrounding words like call, tel, phone, or móvil to lift confidence on ambiguous strings.
- —International with country code: +1 (415) 555-0199, +44 20 7946 0958, +34 612 345 678
- —Local and national: (212) 555-0147, 020 7946 0958, 612 345 678
- —Compact and dotted: 4155550199, 415.555.0199
- —Toll-free and short: 1-800-555-0199, 0800 123 456
- —With extensions: +1 415 555 0199 ext. 23
How does phone number detection work?
Send raw text to POST /v1/detect. Sanitext returns a list of spans. Each span has a label (PHONE), start and end byte offsets, a confidence score between 0 and 1, and the exact matched text.
Byte offsets are UTF-8 byte positions, not character indices. This matters when text contains accents or non-Latin scripts, because one character can be several bytes. Use the offsets to highlight, slice, or replace the number in your own pipeline.
To mask instead of inspect, send the same text to POST /v1/redact. Sanitext replaces every detected number with [PHONE] and returns the cleaned string. The score lets you set a threshold and drop low-confidence matches if you want fewer false positives.
Which formats and edge cases does it handle?
Phone numbers break naive matchers because separators, grouping, and country conventions all vary. Sanitext is trained on real-world text, so it reads numbers the way people actually write them.
A few honest limits to know. Long digit strings that are not phone numbers (order IDs, tracking codes, ZIP+4) can look phone-shaped. The model uses context to tell them apart, but no detector is perfect, so review the score and combine with the ACCOUNT label where you handle account or card numbers.
- —Mixed separators: dots, dashes, spaces, slashes, and parentheses
- —Country code as + or 00 (for example +49 vs 0049)
- —Extensions written as ext, ext., x, or anexo
- —Numbers split across spacing like 612 34 56 78
- —Words instead of symbols are not parsed (for example five-five-five)
Does it work in other languages?
Yes. PHONE detection runs in 30+ languages. Context words that boost confidence are recognized in each language, so tel, téléphone, teléfono, Telefon, and telefono all help the model lock onto a number.
Because detection is multilingual and format-aware, the same API call works whether your text is English support chat, Spanish form data, or German invoices. Pair PHONE with EMAIL, ADDRESS, FIRSTNAME, and LASTNAME to redact full contact blocks in one pass.
bash — POST /v1/redact (phone numbers)
curl https://api.sanitext.app/v1/redact \
-H "Authorization: Bearer $SANITEXT_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Call Marta at +34 612 345 678 or (415) 555-0199 ext. 23."}'
# 200 OK
# {
# "text": "Call [FIRSTNAME] at [PHONE] or [PHONE].",
# "spans": [
# { "label": "FIRSTNAME", "start": 5, "end": 10, "score": 0.97, "text": "Marta" },
# { "label": "PHONE", "start": 14, "end": 28, "score": 0.99, "text": "+34 612 345 678" },
# { "label": "PHONE", "start": 32, "end": 53, "score": 0.96, "text": "(415) 555-0199 ext. 23" }
# ]
# } FAQ
What label does Sanitext use for phone numbers?+
The label is PHONE. Every detected telephone number returns a span tagged PHONE with byte offsets, a confidence score, and the matched text. In /v1/redact, each one is masked as [PHONE].
Can it detect phone numbers without a country code?+
Yes. Sanitext detects local and national numbers with no country code, like (212) 555-0147 or 612 345 678. It uses formatting and nearby context words such as call or tel to confirm the match.
How do I avoid masking order IDs or tracking numbers?+
Long digit strings can look phone-shaped. Sanitext returns a confidence score per span, so set a threshold and drop low scores. For account and card numbers use the ACCOUNT label, which is detected separately from PHONE.
Does redacting phone numbers make my data anonymous?+
No. Redacting phone numbers is data minimization, not anonymization or a compliance guarantee. It removes one direct identifier. Combine PHONE with EMAIL, NAME, and ADDRESS redaction, and apply your own review for sensitive use.
Redact phone numbers in 60 seconds
Sign up, grab an API key, and curl your first /v1/redact call. Free tier gives you 300K characters with no card and it never resets.
Get your free API key