Blog··12 min read

PII redaction for LLM applications: the complete guide (2026)

Godfrey Lebo
Godfrey Lebo
Founder, Sether · Last updated 2026-07-09
Direct answer

PII redaction for LLM apps means detecting personal data (names, emails, phone numbers, cards, secrets) in prompts before they leave your infrastructure, replacing each value with a stable token, and restoring the real values in the model reply. It runs as a library in your request path, a proxy gateway, or a browser extension.

TL;DR
  • Personal data in prompts legally makes your LLM provider a data processor. Most teams have not written that down anywhere.
  • Three places to redact: in-process library, proxy gateway, or browser extension. The library is the default for product teams.
  • Detection is layered: validated patterns (email, card, IBAN) catch structured PII; label anchoring catches "name: Sarah"; NER catches names in free text.
  • Reversible tokenization (redact, then restore in the reply) keeps the UX identical while the provider never sees real values.
  • Streaming breaks naive redaction: a value split across two chunks slips through unless the redactor holds back a safety window.

What is PII redaction for LLM applications?

Every prompt your application sends to OpenAI, Anthropic, Google, or any other provider is a network request that leaves your boundary. If a user typed "Hi, I'm Sarah Chen, my email is sarah@acme.com, calling about order 4532", all of that crosses the wire in plaintext inside the messages array. PII redaction is the practice of catching those values before the request leaves, swapping them for placeholders, and (when you need a seamless UX) swapping the real values back into the reply.

The important design decision is that redaction should be reversible inside your boundary and irreversible outside it. The provider only ever sees <NAME_1> and <EMAIL_1>. Your app, holding the token vault, can still render a reply that reads like nothing happened. We wrote a dedicated deep-dive on this in Reversible PII redaction: how redact-then-restore works.

Why this became urgent in 2026

Three forces converged. First, regulation: under GDPR Article 28, sending customer personal data to an LLM API makes that provider a data processor, which requires a written agreement and a listed sub-processor. The EU AI Act adds its own obligations, with the most serious violations carrying fines of up to 7% of global annual turnover, and key obligations applying from August 2, 2026. Second, procurement: enterprise security questionnaires now routinely ask "what personal data reaches your AI vendors, and what technical control prevents more?". Third, scale: teams shipped chat features in 2024-2025 faster than they shipped the data-handling controls around them.

If you are wondering whether your specific setup is a problem, start with Is it GDPR-compliant to send customer data to OpenAI? That post walks the actual legal reasoning instead of fear-mongering.

Where to redact: library, gateway, or browser

ApproachWhere it runsBest forTrade-off
In-process libraryInside your app, wrapping the LLM callProduct teams who own the code pathOne integration per service
Proxy gatewayA separate service your SDK points atMany services, one policy; polyglot stacksNew infrastructure to run and trust
Browser extensionThe user's browser, watching the chat inputEmployees pasting into ChatGPT/Claude/Gemini directlyProtects humans, not your API traffic

These are complements, not competitors. A library protects your product's API calls; an extension protects the copy-paste habits of the humans in your company. We cover the human side in How to stop pasting sensitive data into ChatGPT.

Detection: patterns, labels, and NER

No single technique catches everything. Production redaction layers stack three:

  1. Validated patterns for structured PII. An email has a grammar. A credit card is sixteen digits that must pass a Luhn check. An IBAN has a mod-97 checksum. Patterns plus validation give near-zero false positives on this class.
  2. Label anchoring for semi-structured data. "name: Sarah Chen" or "DOB: 12/04/1991" announce themselves with a label. Anchored detectors match the label (in multiple languages and scripts) and capture the value that follows.
  3. NER (named-entity recognition) for free text. Nobody types "name: Chidi"; they type "tell Chidi I'll send the money on Friday". Only a model that reads the sentence catches that. This is heavier, so it belongs in a separate, lazy-loaded package.

When to reach for which is its own topic: Regex vs NER for PII detection covers the decision line, including why running NER locally (ONNX in-process) beats calling a cloud detection API that would itself see the data.

Not just PII: API keys and secrets

The same pipeline that catches emails should catch sk-... OpenAI keys, AWS access keys, GitHub tokens, Slack tokens, Stripe keys, JWTs, and high-entropy strings. Developers paste config into AI chats constantly, and a leaked provider key is a worse day than a leaked email address. Sether ships this as a separate detector pack (8 detectors including a Shannon-entropy catch-all) that you enable alongside the basic pack.

The streaming trap: values split across chunks

LLM apps stream. Streaming means your redactor sees sarah@ac in one chunk and me.com in the next, and a naive per-chunk regex passes both. The fix is a bounded hold-back window: the redactor keeps the last N bytes (Sether defaults to 256) unemitted until it can prove no match could span the boundary. This is the single most common correctness bug in home-grown redaction, and it is invisible in demos because demos rarely split mid-value.

We almost shipped this bug ourselves. The full story, including the property-based test that now locks it down, is in The chunk-boundary bug: why streaming redaction is hard.

The tool landscape, honestly

ToolLanguageApproachNotes
Microsoft PresidioPythonNER (spaCy) + patterns, analyzer/anonymizer servicesBattle-tested, flexible, heavier footprint; no built-in restore round-trip for LLM replies
LLM Guard (Protect AI)PythonGuardrail scanner suite; Anonymize is one scanner among manyBroad guardrails (prompt injection, toxicity) rather than a focused redaction layer
SetherTypeScript + PythonStreaming redact/restore with a token vault; pattern + label + optional local NER packs~35 KB core, 1 runtime dependency, MIT; browser build and Chrome extension share the same detectors
DIY regexAnyHand-rolled patterns in your request pathFine for a prototype; typically falls to the streaming trap and lacks restore, validation, and tests

We keep a longer, more critical version of this comparison (including when Presidio is the right choice over Sether) in Microsoft Presidio alternatives for Node and TypeScript. Short version: if you are a Python data team with GPU budget and batch pipelines, Presidio is excellent. If you are a product team shipping a TypeScript or Python web service and you need streaming plus restore, that is the gap Sether was built for.

A minimal implementation

In TypeScript (full walkthrough):

npm i @raeven-co/sether
import { Sether } from '@raeven-co/sether';
import { Readable } from 'node:stream';

const sether = new Sether();

// Outgoing: pipe the prompt through redact() before it leaves
const safeForLLM = Readable.from([userMessage]).pipe(sether.redact());

// Incoming: pipe the model reply through restore() before the user sees it
const safeForUser = llmResponse.pipe(sether.restore());

In Python (full walkthrough):

pip install sether
from sether import Sether

sether = Sether()

safe = sether.redact_sync(user_message)    # tokens out
reply = call_openai(safe)
restored = sether.restore_sync(reply)      # real values home

Trusting the redactor itself

A redaction layer sits on the most sensitive path in your system, so it must be inspectable. Whatever tool you choose, check: is the source public, how many dependencies does it pull in, does it make network calls of its own, and is it scanned by supply-chain watchdogs? We documented our own hardening pass, including getting to a single runtime dependency and zero open alerts, in How we took Sether's supply chain to zero alerts.

The 10-point checklist

  1. List every place your code sends text to an LLM provider (including background jobs and evals).
  2. Add your LLM providers to your written sub-processor list and sign their DPA.
  3. Put a redaction layer in each request path (library or gateway).
  4. Enable structured-PII detectors with validation (email, phone, card + Luhn, SSN, IBAN + mod-97, IPs).
  5. Enable the secrets pack (provider keys, tokens, JWTs, high-entropy).
  6. Turn on label-anchored identity detection, multilingual if you serve non-English users.
  7. Add NER if your prompts carry free-text names (support tickets, chat, documents).
  8. Verify streaming safety: test a value split across chunk boundaries.
  9. Use reversible tokens with a vault so replies restore transparently.
  10. Give employees a browser-side guard for direct ChatGPT/Claude/Gemini use.

Frequently asked questions

Does redaction hurt LLM answer quality?
Rarely, if tokens are stable and format-preserving. The model treats <NAME_1> as an opaque name and reasons normally. Quality drops only when the redacted value itself carries meaning the task needs, e.g. asking the model to validate an email format.
Is prompt redaction required by GDPR?
GDPR does not name any specific technique. It requires a lawful basis, processor agreements, and "appropriate technical and organisational measures" (Article 32). Redaction is the most direct technical measure for the prompt path, and data minimisation (Article 5) points the same way.
Why not just use OpenAI's zero-retention or EU endpoints?
Retention settings reduce how long the provider stores data; they do not change the fact that the data left your boundary and that the provider processed it. Redaction means the personal data never leaves at all, which is a categorically stronger answer on a security questionnaire.
What does Sether cost?
The library, the Python package, the NER add-on, and the Chrome extension are free and MIT open source. The code is at github.com/raeven-co/sether.
Try it

Sether is free and MIT-licensed: npm i @raeven-co/sether · pip install sether. Or paste some text into the live sandbox and watch the redaction happen.

Keep reading