DataFog is a Python library for detecting and redacting personally identifiable information (PII) offline in AI applications. It provides fast regex-based detection, optional NER support, and ready-made enforcement points for Claude Code and LiteLLM with zero network calls and minimal dependencies.
Offline PII firewall for AI agents and LLM apps: fast local detection and redaction, Claude Code hook, LiteLLM guardrail. Zero network calls, one dependency.
README
DataFog Python
DataFog is a Python library for detecting and redacting personally identifiable information (PII).
It provides:
- Fast structured PII detection via regex
- An offline PII firewall for AI agents: a Claude Code hook and a LiteLLM gateway guardrail (introduced in 4.6)
- Optional NER support via spaCy and GLiNER
- A simple agent-oriented API for LLM applications
- Backward-compatible
DataFogandTextServiceclasses
Agent & Gateway Firewall
DataFog includes two ready-made enforcement points that catch PII at the moment it would leave your machine — offline, in microseconds, with matched values never echoed into logs or transcripts:
-
Claude Code hook (
datafog-hook): gates agent tool calls (shell commands, web requests, file writes, MCP tools) and warns the model when prompts or tool results carry PII. ~70–90ms per invocation including process startup. Easiest install is the Claude Code plugin:/plugin marketplace add DataFog/datafog-claude-plugin /plugin install datafog@datafogManual hook setup and limitations: examples/claude_code_hook/.
-
LiteLLM guardrail (
DataFogGuardrail): redacts or blocks PII in requests and responses at the gateway, for any LiteLLM-proxied provider. In-process (~40µs per message scanned; a request clears the guardrail in well under a millisecond), no sidecar service. Setup: examples/litellm_guardrail/.
Both default to the high-precision entity set (EMAIL, PHONE,
CREDIT_CARD, SSN); noisier types are opt-in. Known-safe values can be
exempted with an allowlist: scan(text, allowlist=[...]) for exact values,
allowlist_patterns=[...] for full-match regexes (e.g. ^\d{10}$ to stop
unix timestamps matching as phone numbers) — available in both adapters and
the API. Presidio-style entity names (EMAIL_ADDRESS, PHONE_NUMBER,
US_SSN) are accepted as aliases for easy migration.
Every performance number above is reproducible with one command — methodology, pinned payloads, and comparisons against Presidio and spaCy NER live in benchmarks/.
Installation
# Core install (regex engine)
pip install datafog
# Add spaCy support
pip install datafog[nlp]
# Add GLiNER + spaCy support
pip install datafog[nlp-advanced]
# Add local OCR support
pip install datafog[ocr]
# Add Spark/distributed support
pip install datafog[distributed]
# Everything
pip install datafog[all]
Python 3.13 support is certified for the core SDK, CLI, nlp,
nlp-advanced, and ocr install profiles. Donut OCR still requires a model
that is available locally before runtime use. distributed and all remain
optional, heavier profiles and are not part of the lightweight core path.
Quick Start
import datafog
text = "Contact [email protected] or call (555) 123-4567"
clean = datafog.sanitize(text, engine="regex")
print(clean)
# Contact [EMAIL_1] or call [PHONE_1]
For LLM Applications
import datafog
# 1) Scan prompt text before sending to an LLM
prompt = "My SSN is 123-45-6789"
scan_result = datafog.scan_prompt(prompt, engine="regex")
if scan_result.entities:
print(f"Detected {len(scan_result.entities)} PII entities")
# 2) Redact model output before returning it
output = "Email me at [email protected]"
safe_result = datafog.filter_output(output, engine="regex")
print(safe_result.redacted_text)
# Email me at [EMAIL_1]
# 3) One-liner redaction
print(datafog.sanitize("Card: 4111-1111-1111-1111", engine="regex"))
# Card: [CREDIT_CARD_1]
German Structured PII
German structured PII is country-specific and opt-in. Use explicit locale selection or entity-type filtering when you want German VAT IDs, German IBANs, tax IDs, postal codes, passports, or residence permits.
import datafog
text = "Steuer-ID 12345678901 liegt vor."
print(datafog.scan(text, engine="regex").entities)
# []
print(datafog.scan(text, engine="regex", locales=["de"]).entities)
# [Entity(type='DE_TAX_ID', text='12345678901', ...)]
Guardrails
import datafog
# Reusable guardrail object
guard = datafog.create_guardrail(engine="regex", on_detect="redact")
@guard
def call_llm() -> str:
return "Send to [email protected]"
print(call_llm())
# Send to [EMAIL_1]
Engines
Use the engine that matches your accuracy and dependency constraints:
regex:- Fastest and always available.
- Best for default structured entities:
EMAIL,PHONE,SSN,CREDIT_CARD,IP_ADDRESS,DATE,ZIP_CODE(DOBandZIPare accepted as input aliases). - Use
locales=["de"]for German structured IDs such asDE_VAT_ID,DE_IBAN,DE_TAX_ID,DE_POSTAL_CODE, and passport or residence permit numbers.
spacy:- Requires
pip install datafog[nlp]. - Useful for unstructured entities like person and organization names.
- Requires
gliner:- Requires
pip install datafog[nlp-advanced]. - Stronger NER coverage than regex for unstructured text.
- Requires
smart:- Cascades regex with optional NER engines.
- If optional deps are missing, it degrades gracefully and warns.
Optional OCR And Spark Surfaces
The 4.x line keeps the main package story centered on lightweight text PII screening. OCR and Spark remain supported optional surfaces for users who already rely on them, but they are not required for the core import, default scan/redact helpers, or guardrail helpers.
- OCR:
- Install
datafog[ocr]for local image OCR helpers. - URL-based image downloading also needs
datafog[web,ocr]. - Tesseract usage requires the system
tesseractbinary. - Python 3.13 is validated for the OCR install profile, Pillow, pytesseract, and system Tesseract smoke checks.
- Donut OCR requires
datafog[nlp-advanced,ocr]and a model already available locally.
- Install
- Spark:
- Install
datafog[distributed]forSparkService. - Spark PII UDF helpers also require
datafog[nlp]and an installed spaCy model. - A Java runtime is required by PySpark.
- Install
OCR and Spark are not deprecated. Their broader API and packaging overhaul is deferred; the 4.x goal is to keep them explicit, documented, and isolated from the lightweight core path.
Backward-Compatible APIs
The existing public API remains available.
DataFog class
from datafog import DataFog
result = DataFog().scan_text("Email [email protected]")
print(result["EMAIL"])
TextService class
from datafog.services import TextService
service = TextService(engine="regex")
result = service.annotate_text_sync("Call (555) 123-4567")
print(result["PHONE"])
CLI
# Scan text
datafog scan-text "[email protected]"
# Redact text
datafog redact-text "[email protected]"
# Replace text with pseudonyms
datafog replace-text "[email protected]"
# Hash detected entities
datafog hash-text "[email protected]"
# Enable German regex identifiers
datafog redact-text "Steuer-ID 12345678901" --locale de
Telemetry
DataFog telemetry is disabled by default.
To opt in:
export DATAFOG_TELEMETRY=1
To force telemetry off:
export DATAFOG_NO_TELEMETRY=1
# or
export DO_NOT_TRACK=1
Telemetry does not include input text or detected PII values.
Development
git clone https://github.com/datafog/datafog-python
cd datafog-python
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[all,dev]"
pip install -r requirements-dev.txt
pytest tests/
Comments (0)
Sign in to join the discussion.
No comments yet
Be the first to share your take.