PII detection and redaction for chatbots
Sanitext detects and redacts PII in chatbot text before it reaches your model or your logs. Send the user message to POST /v1/redact, get back text with names, emails, phones, addresses, and cards masked as [LABEL], then pass the clean text downstream. It works in 30+ languages on our own infrastructure.
Chatbots are a firehose for personal data. Users paste emails, phone numbers, account IDs, and full names into the chat box without thinking. That data then flows to your LLM provider, lands in your logs, and sometimes ends up in training sets. Sanitext puts a redaction step between the user and the model so the sensitive parts never travel further than they have to.
Where PII leaks in a chatbot and how Sanitext helps
| Stage | Risk | Sanitext step |
|---|---|---|
| User input | Real names, emails, phones, cards typed into chat | Redact before the model call and before logging |
| Model call | PII sent to a third-party LLM provider | Pass masked text; provider never sees raw PII |
| Logs and analytics | Raw messages retained in plaintext | Log the [LABEL] version, not the original |
| Model output | Bot echoes PII or surfaces it from context | Redact the reply before storing or displaying |
| Conversation store | Stored chats feed training and eval sets | Persist masked turns to cut training-data risk |
Why is PII a problem in chatbots?
Every chatbot turn carries text you did not write. People type their real name, work email, phone number, and sometimes a card number or an API key, all in plain language. You cannot predict it and you cannot pre-validate it the way you would a form field.
That raw text usually leaves your system three times. It goes to the model API on the request. It gets written to application and analytics logs. And it sits in your conversation store for history and support. Each hop is a place where PII can leak, get retained longer than you intended, or get swept into a training pipeline.
The output side matters too. A model can repeat a user's email back, or pull a name from retrieved context and surface it in an answer. Scrubbing only the input is half the job.
- —Inputs: users paste names, emails, phones, addresses, account numbers, and secrets
- —Outputs: models echo PII back or pull it from retrieved documents
- —Storage: conversation history and logs retain PII far longer than needed
- —Training: stored chats often feed fine-tuning or eval datasets
What is the pattern for redacting PII in a chatbot?
The pattern is a redaction step in the middle of your message flow. Before you call the model, send the user turn to Sanitext and use the masked version for the model and for your logs. You can do the same on the model's reply before you store it or show it.
Use POST /v1/detect when you want the raw spans so you can decide what to mask, swap with placeholders, or restore later. Each span returns a label, byte offsets, a score, and the matched text. Use POST /v1/redact when you just want clean text back with each match replaced by its label, like [EMAIL] or [PHONE].
Drop it in as a thin wrapper around your existing model call. No re-architecture. The chatbot logic stays the same; it just sees scrubbed text.
- —Redact the user message before the model call and before logging
- —Optionally redact the model output before storing or displaying it
- —/v1/detect for spans and custom handling; /v1/redact for ready-to-use masked text
- —Labels include FIRSTNAME, LASTNAME, EMAIL, PHONE, ADDRESS, DATE, URL, ACCOUNT, SECRET
Why Sanitext fits chatbot pipelines
We own the open-weights model (Apache-2.0, from the OpenAI privacy-filter family) and run it on our own Cloudflare infrastructure. There is no per-token AI cost, so pricing is flat and predictable, not metered against your chat volume. Your chatbot traffic can spike without a surprise bill.
Your text never goes to a third-party LLM for the redaction step. We do not retain raw text; we log counts and timings only. That is the point: you add a redaction layer without adding another data processor that sees everything your users type.
It detects PII in 30+ languages, which matters for chatbots that serve mixed-language audiences. EU data residency and a DPA are available on Enterprise.
- —Zero per-token AI cost: flat pricing, not metered per chat
- —No raw-text retention: we store counts and timings, not messages
- —30+ languages for multilingual chat
- —EU data residency and DPA available on Enterprise
Integration notes
Sanitize the user turn first, then the model output. The cleanest place is right before and right after your model call, so both the provider and your storage see masked text.
If you need the model to act on the real value (for example, look up an account), keep the real text only in the short-lived call and mask the copy you log and store. With /v1/detect you can map each placeholder back to its original span in memory and restore it in the final reply if you control that step.
Add a timeout and a fail-safe. Decide upfront whether a failed redaction call blocks the turn or falls back to a stricter local rule. Latency is low, but treat the redaction step as part of your critical path and handle errors explicitly.
- —Authenticate with your API key in the Authorization header
- —Redact input before the model; redact output before storage and display
- —Keep real values only in-memory for the live call when you truly need them
- —Set a timeout and a documented fallback for redaction failures
Is this enough for compliance?
Redacting chatbot text is a strong data-minimization aid. It reduces how much PII you send to third parties, how much you retain, and how much can leak into training data. That lowers risk in a real, measurable way.
It is not anonymization and it is not a compliance guarantee. No detector catches 100% of PII, free-text is messy, and obligations under laws like GDPR or HIPAA depend on your full process, not one API call. Use Sanitext as one control inside a documented program, and validate it on your own chat data before you rely on it.
python
import os, requests
from openai import OpenAI
SANITEXT_KEY = os.environ["SANITEXT_API_KEY"]
llm = OpenAI()
def redact(text: str) -> str:
"""Mask PII (names, emails, phones, cards, secrets) before it leaves us."""
r = requests.post(
"https://api.sanitext.app/v1/redact",
headers={"Authorization": f"Bearer {SANITEXT_KEY}"},
json={"text": text},
timeout=5,
)
r.raise_for_status()
return r.json()["text"]
def chat(user_message: str) -> str:
# 1. Scrub the user turn before the model and before logging.
clean_input = redact(user_message)
log.info("chat turn", input=clean_input) # logs see [EMAIL], not the real one
# 2. Call the model with the masked text.
resp = llm.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": clean_input}],
)
answer = resp.choices[0].message.content
# 3. Scrub the model output before you store or display it.
return redact(answer)
print(chat("Hi, I'm Dana Klein, email dana@acme.com, card 4111 1111 1111 1111"))
# -> model and logs only ever saw: Hi, I'm [FIRSTNAME] [LASTNAME], email [EMAIL], card [ACCOUNT] FAQ
Does Sanitext send my chatbot messages to another LLM?+
No. Sanitext runs an open-weights model on our own Cloudflare infrastructure. Your chatbot text is not forwarded to a third-party LLM for redaction, and we do not retain raw text. We log only counts and timings, so the redaction step does not add a new processor that reads every message.
Should I redact chatbot inputs, outputs, or both?+
Redact both. Scrub the user message before the model call and before logging so providers and storage see masked text. Scrub the model reply before you store or display it, since models can echo a user's PII or surface names pulled from retrieved context.
How do I keep the real value when the bot needs it?+
Use POST /v1/detect to get spans with labels and byte offsets, keep the original value only in memory for the live action (like an account lookup), and store and log the masked copy. You can map placeholders back to originals and restore them in the final reply if you control that step.
Does it work for non-English chats?+
Yes. Sanitext detects PII in 30+ languages, including names, emails, phone numbers, addresses, dates, URLs, account numbers, and secrets. That suits chatbots serving mixed-language audiences where a single user turn might switch languages mid-sentence.
Does redacting chatbot text make me GDPR or HIPAA compliant?+
No. Redaction is a data-minimization aid, not anonymization or a compliance guarantee. No detector catches every instance of PII in free text. Treat Sanitext as one control in a documented program and validate it on your own chat data before relying on it.
Add a redaction layer to your chatbot in 60 seconds
Sign up, get an API key, and wrap your model call with one POST to /v1/redact. Free tier gives you 300K characters with no card. Try it in the playground first.
Get your free API key