Horizon-Labs/pii-redactor-small
PII Redactor (small, 141M)
A small, fast, multilingual PII and secrets detector for redacting text before it reaches logs, LLM prompts, training data or a vendor API. It tags 29 entity types: names, contact details, addresses, government IDs, financial data, credentials and API keys, network and device identifiers, and more.
- Open: Apache-2.0, ungated, trained only on permissively licensed data.
- Multilingual: 30+ languages, Latin and non-Latin scripts.
- Small: 141M parameters, CPU-friendly. ONNX and transformers.js work in the browser and at the edge.
- Measured honestly: evaluated on four external benchmarks (plus one held-out set of our own) that no model below was trained on, against the most used open PII models. It is not the best on every benchmark; see the table.
Try it in the browser: Horizon-Labs/pii-redactor demo.
Part of Agent I/O Guards, alongside Prompt Injection Guard.
Source code (data, training, evaluation): github.com/horizon-ai-labs/agent-io-guards.
Quick start
from transformers import pipeline
ner = pipeline("token-classification", model="Horizon-Labs/pii-redactor-small", aggregation_strategy="simple")
ner("Hi, I'm Anna Müller. Mail anna.mueller@posteo.de, key sk-proj-9fQ2x7LmA1bC3dE4")For redaction, use redact.py from this repo. It merges sub-word pieces, trims whitespace, and handles long documents with overlapping windows:
from huggingface_hub import hf_hub_download
import importlib.util, sys
spec = importlib.util.spec_from_file_location("redact", hf_hub_download("Horizon-Labs/pii-redactor-small", "redact.py"))
redact = importlib.util.module_from_spec(spec); spec.loader.exec_module(redact)
r = redact.PIIRedactor("Horizon-Labs/pii-redactor-small")
r.redact("Bonjour, je m'appelle Jean Dupont, j'habite 12 rue de la Paix, 75002 Paris.")
# "Bonjour, je m'appelle [PERSON], j'habite [STREET_ADDRESS], [POSTCODE] [LOCATION]."Presidio
from presidio_analyzer import AnalyzerEngine
analyzer = AnalyzerEngine()
analyzer.registry.add_recognizer(redact.presidio_recognizer("Horizon-Labs/pii-redactor-small"))
analyzer.analyze(text="Call me at (415) 555-0132", language="en")LLM Guard (Anonymize scanner)
llm_guard_conf.py in this repo maps the labels to Presidio / LLM Guard entities. It is a permissive, multilingual alternative to the default Anonymize models:
spec = importlib.util.spec_from_file_location("conf", hf_hub_download("Horizon-Labs/pii-redactor-small", "llm_guard_conf.py"))
conf = importlib.util.module_from_spec(spec); spec.loader.exec_module(conf)
from llm_guard.vault import Vault
from llm_guard.input_scanners import Anonymize
scanner = Anonymize(Vault(), recognizer_conf=conf.horizon_pii_conf("small"), language="en")
scanner.scan("Hi, I'm Anna Müller, email anna.mueller@posteo.de, IBAN DE89370400440532013000.")[0]
# "Hi, I'm [REDACTED_PERSON_1], email [REDACTED_EMAIL_ADDRESS_1], IBAN [REDACTED_IBAN_CODE_1]."Entity types
ACCOUNT_ID, AGE, BANK_ACCOUNT, COORDINATE, CREDIT_CARD, CREDIT_CARD_CVV, DATE, DATE_OF_BIRTH, DEVICE_ID, DRIVER_LICENSE, EMAIL, IP_ADDRESS, LICENSE_NUMBER, LOCATION, MAC_ADDRESS, MEDICAL_ID, NATIONAL_ID, ORGANIZATION, PASSPORT, PASSWORD, PERSON, PHONE, POSTCODE, SECRET, STREET_ADDRESS, TAX_ID, URL, USERNAME, VEHICLE_ID
ORGANIZATION means an employer or company linked to a person. SECRET covers API keys, tokens, private keys, connection strings and session cookies. Gender and other sensitive attributes (religion, health conditions) are not tagged in this version.
Evaluation
External benchmarks
None of the models below were trained on these benchmarks. Every model uses its own label set, so the comparison ignores entity types. It measures what matters for redaction: redaction recall, the share of must-redact characters that get masked, and redaction precision, the share of masked characters that are PII. All models ran through the same transformers token-classification pipeline (code/pii/evaluate_pii.py), with at most 600 documents per benchmark.
Redaction recall / precision:
Redaction F1 (harmonic mean of the two):
Reading this table:
- RedactionBench marks a lot as mandatory (form field values, course codes, IDs), so every model's recall is low. Relative order is the useful signal.
- Privacy-Bench (email threads): gravitee and OpenMed catch more PII but mask much more non-PII. OpenAI's much larger model is the most precise.
- \ The last row is a held-out set we generated with Qwen3.8-27B: secrets in code, config files and logs, plus chat and email threads, in 36 languages. This model was not* trained on any of that generator's output, but we built the set ourselves, so read it as supporting evidence only.
- TAB counts DIRECT identifiers in court judgments, such as names and case-application numbers. Case numbers are not a type any of these models were trained for.
In-distribution held-out sets
These come from the same generators as the training data, so they overstate real-world quality.
Limitations
- Most training text is synthetic (OpenPII, Nemotron-PII, Gretel, plus Qwen3.8-generated documents in later versions). Real documents are messier, so expect lower recall on unusual formats, and review before relying on it for compliance.
- It is not a guarantee of anonymization. Quasi-identifiers (job title plus town plus age) and free-text descriptions can still identify people.
- Dates are tagged whether or not they are personal, which over-redacts public dates.
- Languages outside the training set, and long numeric strings with unusual grouping, are weaker. For example, a space-separated 16-digit card number can be only partly masked, and a bare CVV next to it can be missed.
Training
- Backbone: jhu-clsp/mmBERT-small (MIT), BIO token classification, max length 512 with stride windows, bf16, 1 epoch.
- Data (about 400k documents): OpenPII 1.5M (CC-BY-4.0, ai4privacy; language-balanced 256k sample), Nemotron-PII (CC-BY-4.0, NVIDIA), and Gretel PII masking EN v1 (Apache-2.0). Their label sets were mapped to one Presidio-aligned taxonomy (
code/pii/build_pii_v0.py). - Attribution: this model is trained on CC-BY-4.0 data from ai4privacy and NVIDIA. Please keep this notice when redistributing derivatives.
Citation
@misc{horizonlabs2026piiredactor,
title = {PII Redactor: small multilingual PII and secrets detection},
author = {Horizon Labs},
year = {2026},
url = {https://huggingface.co/Horizon-Labs/pii-redactor-small}
}