screenpipe-pii-redactor
A screenpipe project.
A fine-tuned PII redactor for the three surfaces an AI agent actually sees a user's machine through:
- Accessibility-tree dumps — the structured AX hierarchy macOS /
Windows expose to assistive tech. Short, structured, often containing
labels like
AXButton[Send to marcus@helios-ai.io]. - OCR'd screen text — what tools like screenpipe extract from screen recordings. Mix of window-title-shaped artifacts, app chrome, and occasional long-form (emails, docs).
- Computer-use traces — what an agentic model (Claude Computer Use, GPT operator, etc.) reads when it controls a desktop.
These surfaces are short, sparse-context, and full of identifiers that slip past redactors trained on chat-style prose. This model is fine-tuned specifically for them — while still handling long-form text at competitive accuracy.
Built on top of the OpenAI Privacy Filter (1.5B parameters, 50M active).
License: CC BY-NC 4.0 (non-commercial). For commercial use — production redaction, SaaS / API embedding, AI-agent privacy middleware, custom fine-tunes — contact louis@screenpi.pe. See
LICENSE.
Headline numbers
| base OPF | this model | |
|---|---|---|
| Accessibility / window-title PII zero-leak | 38.6% (33.6–43.8) | 79.1% (74.8–83.5) |
| Long-form PII zero-leak (English) | 14.0% (11.7–16.2) | 77.5% (74.5–80.3) |
| Long-form PII macro-F1 (English) | 0.591 | 0.934 |
| Targeted secret-redaction (34 realistic shapes) | not measured | 31/34 |
| p50 inference latency (CUDA) | ~23 ms | ~23 ms |
95% bootstrap CIs in brackets. Zero-leak: % of cases where the model caught all gold spans (the metric that matters for privacy).
Why this exists (vs the base Privacy Filter)
The OpenAI Privacy Filter (and most other public PII redactors) is trained on prose-shaped data. A typical accessibility-tree node, OCR'd window title, or computer-use log line looks nothing like that:
AXButton[Send to marcus@helios-ai.io]
Welcome | Acme Corp | xAI Console
[ScreenCapture 09:14] Slack — #compai-tessera (12 unread)
These are 30-character strings with one or two PII tokens and almost
no surrounding context. A model trained on chat corpora will conflate
brand names with people, miss Arc | Marcus Chen because it expects
sentence context, and tag Raycast and Claude as people.
If you're building an agentic system that reads screen state — a desktop-control agent, a memory layer for browsing, anything that streams accessibility / OCR / screen-capture data into an LLM — this is the redactor designed for that pipe.
What it does
Span-level redaction. Given a string, returns [(start, end, label, text)]
where each span is a region the model thinks is PII, classified into one
of 12 canonical categories:
private_person, private_email, private_phone, private_address,
private_url, private_company, private_repo, private_handle,
private_channel, private_id, private_date, secret
secret covers passwords, API keys, JWTs, DB connection strings,
PRIVATE-KEY block markers, etc.
Inference
# pip install opf (currently from source: github.com/openai/privacy-filter)
from opf import OPF
filt = OPF(model="./model", device="cuda") # or "cpu"
out = filt.redact("Welcome | Marcus Chen — Confluence")
for span in out.detected_spans:
print(f" [{span.start}:{span.end}] {span.label} = {span.text!r}")
# -> [10:21] private_person = 'Marcus Chen'
See examples/inference.py for a longer example
covering window titles, long-form text, and secrets.
Multilingual
This model handles 6 languages. Performance on a public long-form PII benchmark (n=200 per language):
| Language | zero-leak |
|---|---|
| English | 76.8% (70.1–83.1) |
| Spanish | 73.2% (66.5–79.3) |
| Italian | 70.8% (64.3–77.4) |
| German | 70.6% (63.5–77.1) |
| French | 68.1% (61.5–75.3) |
| Dutch | 56.1% (48.9–63.3) |
Romance + Germanic languages drop −3 to −9 pp from English. Dutch is the weakest — flagged as a known gap.
Limitations
- Sudo / login password prompts leak. Pattern like
[sudo] password for alice: hunter2results in the username being redacted but the password surviving. One known hard miss in the targeted secret probe; mitigate with an OS-level keystroke-suppression policy alongside this model. - Dutch is the weakest language at −20.7 pp from English. Indic, Asian, African, Cyrillic scripts not evaluated at meaningful sample sizes — don't deploy without a locale-specific eval pass.
- Synthetic training data only. No real user data was used during fine-tuning. Validate on YOUR data before deploying.
- Oversmash. 7.8% on accessibility / window titles, 16.5% on long-form text. The model over-redacts. Acceptable for privacy-first deployments; flag if you need clean OCR text downstream.
- Strict label-space evaluation. The numbers above use a 12-class taxonomy and a strict per-example zero-leak metric. Absolute values depend on the evaluator's label taxonomy and metric choice; macro-F1 is a more lenient point of comparison.
Reproducing inference
git clone https://huggingface.co/screenpipe/pii-redactor
cd pii-redactor
git lfs pull
pip install git+https://github.com/openai/privacy-filter.git
python examples/inference.py
Reproducing the eval scores requires our held-out benchmark, which is not redistributed. Contact louis@screenpi.pe for benchmark access or commercial licensing.
License
CC BY-NC 4.0 — non-commercial use only. The base model is
Apache-2.0; obligations are preserved (see NOTICE).
For commercial licensing (production deployment, redistribution rights, SaaS / API embedding, custom fine-tunes for your domain): louis@screenpi.pe.
Citation
@misc{screenpipe-pii-redactor-2026,
title = {screenpipe-pii-redactor: a PII redactor for accessibility
trees, OCR'd screen text, and computer-use traces},
author = {{screenpipe}},
year = {2026},
url = {https://huggingface.co/screenpipe/pii-redactor}
}
Model tree for screenpipe/pii-redactor
Base model
openai/privacy-filter