How to Strip PII from LLM Prompts with One API Call

Published: (March 4, 2026 at 06:08 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

Introduction

Building an AI app that processes sensitive user data—such as medical records—requires a way to remove personally identifiable information (PII) before sending the prompt to a large language model (LLM). Sending protected health information (PHI) or other confidential data directly to services like OpenAI or Claude can create compliance issues (HIPAA, GDPR, PCI, etc.).

This guide shows how to automatically scrub PII with a single API call, then safely forward the sanitized text to any LLM.

Why a privacy proxy?

  • Compliance – Prevent raw PII from reaching external LLM providers.
  • Speed – Scrubbing takes ~42 ms, far faster than building a custom NER pipeline.
  • Cost – $0.001 per request (free tier: 50 scrub requests/day).
  • Accuracy – 97 % entity detection on a 10 K+ medical‑record test set (spaCy + Presidio).
  • Coverage – Detects 15+ entity types: names, emails, phones, SSNs, credit cards, IPs, dates, medical codes, drug names, addresses, URLs, API keys, crypto addresses, etc.

How it works

  1. Send raw text to the /api/scrub endpoint.
  2. The service returns:
    • scrubbed – the original text with PII replaced by placeholders like [NAME_1].
    • entities – a map of placeholder keys to the original values.
  3. Forward the scrubbed text to your LLM of choice.
  4. (Optional) Re‑inject entities into the LLM response for UI display.

Example API call

curl -X POST https://tiamat.live/api/scrub \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Patient John Smith (SSN: 123-45-6789) was diagnosed with Type 2 diabetes on 2023-01-15. His doctor is Dr. Alice Chen at massachusetts-general-hospital.org."
  }'

Response

{
  "scrubbed": "Patient [NAME_1] (SSN: [SSN_1]) was diagnosed with Type 2 diabetes on [DATE_1]. His doctor is [TITLE_1] [NAME_2] at [ORG_1].",
  "entities": {
    "NAME_1": "John Smith",
    "SSN_1": "123-45-6789",
    "DATE_1": "2023-01-15",
    "TITLE_1": "Dr.",
    "NAME_2": "Alice Chen",
    "ORG_1": "massachusetts-general-hospital.org"
  }
}

Python integration

import requests

user_input = "My name is Sarah and my account number is ACC-12345-XYZ. Please summarize my medical records."

# Step 1: Scrub PII
scrub_resp = requests.post(
    "https://tiamat.live/api/scrub",
    json={"text": user_input}
)
scrub_data = scrub_resp.json()
scrubbed = scrub_data["scrubbed"]
entities = scrub_data["entities"]

print("Scrubbed:", scrubbed)
# → "My name is [NAME_1] and my account number is [ACCOUNT_1]. Please summarize my medical records."

# Step 2: Send to Claude (or any LLM)
llm_resp = requests.post(
    "https://api.anthropic.com/v1/messages",
    headers={"x-api-key": "your-claude-key"},
    json={
        "model": "claude-3-5-sonnet-20241022",
        "messages": [{"role": "user", "content": scrubbed}]
    }
)
response_text = llm_resp.json()["content"][0]["text"]
print("Claude response:", response_text)

# Optional: Restore entities for UI
ui_response = response_text
for key, value in entities.items():
    ui_response = ui_response.replace(f"[{key}]", value)

print("UI response:", ui_response)

JavaScript (Fetch API) integration

// Scrub request
const scrubResp = await fetch('https://tiamat.live/api/scrub', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ text: 'My email is john@example.com and my phone is 555-123-4567' })
});
const scrubData = await scrubResp.json();
console.log(scrubData.scrubbed); // "My email is [EMAIL_1] and my phone is [PHONE_1]"
// Using the scrubbed text with an LLM (example placeholder)
const llmResp = await fetch('https://api.anthropic.com/v1/messages', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'your-claude-key'
  },
  body: JSON.stringify({
    model: 'claude-3-5-sonnet-20241022',
    messages: [{ role: 'user', content: scrubData.scrubbed }]
  })
});
const llmData = await llmResp.json();
console.log(llmData.content[0].text);

Pricing & limits

TierDaily scrub requestsCost per requestPayment method
Free50$0.001 (free)
PaidUnlimited$0.001USDC on Base network

No credit‑card required for the free tier. Upgrade when you exceed the free quota.

API reference

Endpoint: https://tiamat.live/api/scrub

Request (JSON)

{
  "text": "string (required) — text to scrub"
}

Successful response

{
  "scrubbed": "string — text with PII replaced by [TYPE_N] placeholders",
  "entities": {
    "[NAME_1]": "John Smith",
    "[EMAIL_1]": "john@example.com"
    // …
  }
}

Error response

{
  "error": "Rate limit exceeded",
  "error_code": "RATE_LIMITED",
  "retry_after": 3600   // seconds until next allowed request
}

Best practices

  • Validate the entities map to ensure all placeholders were correctly replaced before showing the response to users.
  • Monitor rate limits using the retry_after field in error responses.
  • Log only the scrubbed text (never the raw PII) if you need audit trails.
  • Combine with additional security layers (TLS, authentication) when integrating into production systems.

Conclusion

PII scrubbing no longer needs a multi‑month engineering effort. With a single API call you can:

  1. Remove sensitive data in memory.
  2. Preserve the original values for later re‑insertion.
  3. Keep compliance (HIPAA, GDPR, PCI) while leveraging powerful LLMs.

Try the free tier at and integrate the two‑line scrub call into your app today.

0 views
Back to Blog

Related posts

Read more »

AI, Humanity, and the Loops We Break

🌅 Echoes of Experience — Standing in the Horizon There was a time when chaos shaped me. But the moment I chose myself—truly chose myself—everything shifted. I...