privacy-guard-proxy
privacy-guard-proxy is a local reverse proxy for Claude Code that masks sensitive data before it leaves your machine.
Email addresses, names, IBANs, API keys, IDs, addresses, and other secrets are replaced with placeholders like [EMAIL_1] or [IBAN_1] on the way to the Anthropic API. Detection runs fully in-process. No external redaction service is involved.

Why use it?
- Keep PII and secrets out of model requests by default
- Run locally with no extra SaaS dependency
- Use it as a drop-in proxy for Claude Code
- Inspect detections, logs, and config in a built-in Web UI
- Expose the same detector engine through a REST API
How it works
Claude Code -> privacy-guard-proxy -> Anthropic API
| masks PII + secrets |
Before a request is forwarded upstream, the proxy scans user messages, tool payloads, and file contents for sensitive data. Matching values are replaced with stable placeholders. Upstream responses are passed through unchanged.
Quick start
Local binary
cp config.example.json config.json
go build -o privacy-guard-proxy .
./privacy-guard-proxy
export ANTHROPIC_BASE_URL=http://127.0.0.1:9880
claude
By default:
- Proxy:
http://127.0.0.1:9880 - Web UI + REST API:
http://127.0.0.1:9881
Docker Compose
cp config.example.json config.json
docker compose up -d
The compose setup exposes the same two ports and mounts config.json plus ./logs.
What gets masked?
| Content | Masked |
|---|---|
| User messages | Yes |
| File contents returned by tools | Yes |
| Tool inputs such as write/edit payloads | Yes |
| System prompt | No |
| Assistant responses | No |
Web UI
If api_port is enabled, the browser UI is available at http://localhost:9881.

First login:
- Username:
admin - Password:
admin
You are forced to change the password on first login.
The UI lets you:
- Manage one or more proxy instances
- Choose detectors and whitelists per proxy
- Enable
dry_runmode to log findings without modifying requests - Manage REST API keys without storing plaintext secrets
- Configure default detectors, default whitelist, and CORS
- Inspect live proxy logs
- Test detector behavior interactively
REST API
The built-in API exposes the same detector engine used by the proxy.
# Anonymize text
curl http://localhost:9881/anonymize \
-H "Content-Type: application/json" \
-d '{"text":"Meine IBAN: DE89370400440532013000"}' | jq
# Full scan with findings and placeholder mapping
curl http://localhost:9881/scan \
-H "Content-Type: application/json" \
-d '{"text":"foo@example.com, +49 171 1234567"}' | jq
# Use selected detectors for this request only
curl http://localhost:9881/scan \
-H "Content-Type: application/json" \
-d '{"text":"...", "detectors":["EMAIL","IBAN","SECRET"]}' | jq
# Health and metrics
curl http://localhost:9881/health
curl http://localhost:9881/metrics
Authentication is optional. If no API keys are configured, requests are accepted without auth.
curl http://localhost:9881/scan \
-H "X-Api-Key: pgk_..." \
-H "Content-Type: application/json" \
-d '{"text":"..."}'
Current limit:
/scanand/anonymize:120requests per minute- Limit is applied per API key, or per client IP when auth is disabled
Configuration
Start from config.example.json and adjust as needed:
{
"api_port": 9881,
"api_keys": [],
"default_detectors": [],
"default_whitelist": [],
"cors_origins": [],
"ui_password_hash": "",
"proxies": [
{
"type": "claude-code",
"port": 9880,
"upstream": "https://api.anthropic.com",
"privacy_guard": {
"url": "",
"api_key": null,
"detectors": [],
"whitelist": [],
"dry_run": false
}
}
]
}
| Field | Meaning |
|---|---|
api_port |
Port for Web UI and REST API. 0 disables both. |
api_keys |
Stored API key metadata and hashes for protecting /scan and /anonymize. |
default_detectors |
Fallback detector list for API requests that do not specify detectors. Empty means all detectors. |
default_whitelist |
Global terms that should never be masked by the REST API. |
cors_origins |
Allowed browser origins for the REST API. Empty means CORS is off. |
ui_password_hash |
SHA-256 hash of the UI password. Empty means initial admin/admin. |
proxies[].type |
Request format. Use claude-code for Claude Code traffic. |
proxies[].port |
Local listening port of this proxy instance. |
proxies[].upstream |
Upstream Anthropic base URL. |
proxies[].privacy_guard.url |
Reserved config field for compatibility. |
proxies[].privacy_guard.api_key |
Optional per-proxy upstream API key override. |
proxies[].privacy_guard.detectors |
Enabled detector types. Empty means all detectors. |
proxies[].privacy_guard.whitelist |
Terms that should never be replaced for this proxy. |
proxies[].privacy_guard.dry_run |
Detect and log findings without changing outgoing request bodies. |
For /scan and /anonymize, the runtime whitelist is the combination of default_whitelist and any request-level whitelist.
Legacy configs using a top-level []Config array are still accepted.
Supported detectors
| Type | Example | Validation / logic |
|---|---|---|
EMAIL |
foo@example.com |
Regex-based |
PHONE |
+49 171 1234567 |
DACH-focused, at least 9 digits |
IBAN |
DE89 3704 0044 0532 0130 00 |
MOD-97 checksum |
CREDIT_CARD |
4111-1111-1111-1111 |
Luhn check |
TAX_ID |
86 095 742 719 |
German tax ID validation |
SOCIAL_SECURITY |
65 180675 B 003 |
German social security format |
KVNR |
A123456789 |
German health insurance number validation |
VAT_ID |
DE 123 456 789 |
German VAT ID validation |
PERSONAL_ID |
C22990047 |
German passport / ID style patterns |
LICENSE_PLATE |
M-AB 1234 |
German plate formats |
DRIVER_LICENSE |
B123456AB |
Context-aware driver's license detection |
ADDRESS |
Musterstrasse 12, 80331 Muenchen |
DACH street + postal code + city |
URL_SECRET |
?token=abc123 |
Sensitive query parameter detection |
SECRET |
API keys, JWTs, cloud tokens | Large built-in ruleset |
Typical use cases
- Protect prompts and file snippets sent from Claude Code
- Offer a local anonymization API for internal tooling
- Run detector tests against sample text before rolling out changes
- Operate in
dry_runmode first to see what would be masked
Development
go build -o privacy-guard-proxy .
go test ./...
Project layout:
internal/
βββ api/ # Web UI + REST API
βββ detector/ # PII and secret detection engine
βββ proxy/ # Reverse proxy and masking pipeline
main.go # Application entry point
config.json # Runtime configuration
Frontend assets are vendored under internal/api/static/vendor/, so the Web UI does not depend on external CDNs at runtime.