OpenAI PrivacyFilter vs Protecto: 344 Annotations Compared

We ran OpenAI PrivacyFilter and Protecto on the same 150 enterprise prompts. PrivacyFilter detected about 68% of 344 annotations, but only 37% came back with a data type a policy engine can act on. Protecto correctly classified 90%.

Most evaluations of a PII protection layer ask one question: did it find the sensitive data?

That was the right question when data loss prevention meant blocking. A DLP system that found a Social Security number stopped the email, and nothing downstream needed to understand what had been stopped.

AI workflows are different. Sensitive data can enter through prompts, tool calls, retrieved RAG context, agent memory, and model outputs, including paths that may sit outside traditional DLP inspection points. Blocking every document or prompt containing sensitive data is also impractical: it can interrupt the agent, prevent legitimate work, and make the application unusable. The data often needs to be protected while the workflow continues.

The consequential question is now the second one: did the protection layer name the data type precisely enough for a policy engine to select a rule?

We ran OpenAI PrivacyFilter and Protecto against the same 150 enterprise prompts to measure that difference. Across 344 expected annotations, PrivacyFilter detected roughly 68% under some label. Only 37% came back with a data type specific enough to act on. Protecto correctly classified 90% under the same documented scoring rules.

The distance between 68% detected and 37% correctly classified is what this post is about.

Methodology and disclosure

This comparison was designed, run, and scored by Protecto. It was not independently validated. Both products were called through their public APIs under default configuration on the same input set on 29 July 2026. The 150-prompt set intentionally includes difficult and adversarial cases, so these rates describe this test set rather than universal production performance. False positives were outside the scope, so the results are not precision or F-score measurements. The full prompt set, expected annotations, scoring rules, and raw API responses are available on request from sales@protecto.ai.

Two further points belong here rather than in a footnote. The analysis was updated on 3 August 2026 after we found two rows in the source dataset with output columns transposed. Both were corrected before scoring. One correction lowered PrivacyFilter’s measured performance and the other raised it. And the 344 expected annotations were assigned before either product was run, which makes them the agreed basis of the comparison, not independently established ground truth.

What we tested 

We wrote 150 prompts to look like what an enterprise AI system actually receives: pasted records, casual service phrasing, structured document formats, mixed languages, and a deliberate set of hard cases such as OCR-like text, partially masked identifiers, character-spaced digits, decoys, homoglyphs, zero-width characters, and fullwidth digits. 

Before calling either API, we annotated each prompt with the expected sensitive value and its correct data type, which gave us 344 expected annotations across 51 data types. Each was scored into one of four outcomes: 

Outcome Definition
✓
Correctly classified
Detected and assigned the correct specific data type
!
Generalized
Detected, but the returned type is too broad to select a specific rule
✕
Specifically misclassified
Detected and assigned a specific type that contradicts the value
✕
Not detected
No span, label, or output returned

The headline result, with the nuance attached 

Across the 344 expected annotations: 

Outcome PrivacyFilter Protecto
Correctly classified ✓ 37% ✓ 90%
Generalized ! 28% n/a
Specifically misclassified ✕ 4% n/a
Not detected ✕ 31% n/a
Not correctly classified n/a ✕ 10%

Read the middle two rows before the top one. PrivacyFilter returned some label for about 68% of the values we checked, so it is a capable detector. For 28% the type was too broad for a downstream system to use, and for another 4% it was a specific type that contradicted the value. 

So the accurate statement is not that PrivacyFilter missed most of the data. It found most of it and did not name most of it. A span without a usable type only tells the pipeline that something is probably sensitive, not which retention window, masking strictness, residency rule, or access policy applies. 

The four layers, and the one we did not measure 

We think about runtime data protection in four layers. This comparison covers three of them. 

Layer What it produces What depends on it Evaluated here?
1 · Detection A span of sensitive text Whether the protection layer sees the value at all ✓ Yes
2 · Classification A specific data type Which policy rule a system can select ✓ Yes
3 · Transformation Protected text the application can consume Whether the pipeline runs without a custom substitution layer ✓ Yes
4 · Enterprise control Governed re-identification, audit, tenancy Whether it can be deployed in a regulated environment ✕ No

Layer 4 is a hard boundary on what this report can say. API output shows observed detection, classification, and masking behavior. It shows nothing about architecture, extensibility, vault capability, tenancy, access controls, deployment model, or operational integrations, for either product. Protecto Vault, Context-Based Access Control (CBAC), and GPTGuard MCP were not part of this test, so none of this is a Layer 4 comparison. If those properties matter to you, test them in a proof of concept. 

Open Ai Privacyfiiter

Why detection alone stopped being enough 

Three things now depend on what the protection layer returns. 

The model still has to answer the question. If a prompt says “the April invoice is wrong” and the layer swaps “April” for a generic person tag, the model can’t identify the invoice. Nothing leaked, and the answer is still wrong. 

The policy engine still has to pick a rule. Retention, redaction strictness, access, and regional handling all key off the data type, and a generalized label gives the pipeline nothing to select on. 

The audit trail still has to hold. A reviewer will ask which fields were protected, under which classification, and why. “The system flagged it as sensitive” doesn’t answer that. 

 The gap widens as the input gets harder

Category Prompts Annotations Protecto correct PrivacyFilter correct PrivacyFilter detected (any label)
Production conversational 92 164 ✓ 89% 38% ! 78%
Document and form-style 9 82 ✓ 94% 40% ! 68%
Dense multi-entity 5 24 ✓ 92% 46% ! 62%
Multilingual and code-switched 15 31 ✓ 97% 55% ! 84%
Edge case and adversarial 29 43 ✓ 79% 5% ! 19%

The healthcare row totals 99% after rounding. 

Government IDs are the clearest case. Of 72 government and national ID annotations, PrivacyFilter correctly classified none. That wasn’t a detection failure: 75% came back generalized and only 18% were not detected. The values were found and never named. 

Healthcare goes the other way. 72% of the 40 healthcare and PHI annotations were not detected at all, because clinical language doesn’t look like an identifier. Two different problems, two different fixes, and a single recall number would have hidden both. 

Grouped by enterprise domain, the pattern holds. These groupings are analytical and can overlap with the families above, so don’t add them together.

Domain n PrivacyFilter correct Protecto correct
Banking and financial 110 30% ✓ 93%
Healthcare and clinical 72 33% ✓ 93%
Insurance and claims 31 19% ✓ 87%
Identity and KYC 26 42% ✓ 96%
IT and security 17 24% ✓ 76%

One more domain group was omitted because its denominator was too small. 

The generalized-label problem, inside one label 

PrivacyFilter returned 111 ACCOUNT_NUMBER labels in this run. That is a raw label count, not comparable with the 344-annotation scorecard, and the two should never be combined. This is what was inside: 

Composition  Count 
Actual bank account numbers  13 
Identifiers Protecto classified across approximately 22 other specific types  92 
No corresponding Protecto value  6 
Total  111 

The 92 included 17 Social Security numbers, 9 India PAN numbers, 8 credit cards, 7 passport numbers, 7 national IDs, 6 driving license numbers, 5 vehicle identification numbers, and 3 routing numbers. 

Not all 111 labels are wrong. For 13 of them ACCOUNT_NUMBER is correct, and we scored those as correct. The problem is one label carrying more than twenty data types with different handling requirements. Here is the cost on one line of synthetic input: 

New employee Sarah Johnson’s PAN is AAAPS4321Q and her bank account for salary credit is 100234567890. 

  Tax identifier  Salary account 
Protecto  PAN  BANK_ACC_NO 
PrivacyFilter  ACCOUNT_NUMBER  ACCOUNT_NUMBER 

A payroll system consuming that output can’t tell which value is the destination account. Both are sensitive, but only one is a payment instruction, and the label doesn’t separate them. 

When the label is specific and wrong 

Fourteen expected annotations came back with a specific type that contradicts the value. 

Expected type  PrivacyFilter output type  Annotations 
IP address  PRIVATE_URL  3 
US Social Security number  PRIVATE_PHONE  3 
Card CVV  PRIVATE_ADDRESS  2 
Payment card  PRIVATE_DATE or PRIVATE_PHONE  2 
Aadhaar  PRIVATE_PHONE  1 
Bank account  PRIVATE_PHONE  1 
India PAN  PRIVATE_PERSON  1 
Medical code  PRIVATE_ADDRESS  1 

These are annotations, not test cases, and 14 is a small count that we won’t inflate. It matters for another reason. A generalized label signals uncertainty, so a downstream system can escalate, quarantine, or apply the strictest rule. A specific wrong label signals confidence. Nothing flags it for review, and the pipeline applies the wrong rule. 

Consequences from the report: 

  • IP address returned as PRIVATE_URL: indicator search, threat correlation, geolocation, and IP-specific retention logic can fail. 
  • Card CVV returned as PRIVATE_ADDRESS: card-security data can be routed into address handling instead of card-specific controls. 
  • US Social Security number returned as PRIVATE_PHONE: identity and tax handling can be replaced by phone-number policy. 

Clinical language: 19 of 21 against 0 of 21 

We isolated 21 annotations covering clinical concepts. 

Concept  Expected  Protecto  PrivacyFilter 
Medical condition  6  5  0 
Medical procedure  4  4  0 
Blood type  4  4  0 
Medication  3  3  0 
Health beneficiary number  3  2  0 
Biometric data  1  1  0 
Total  21  19  0 

Clinical language isn’t identifier-shaped. A diagnosis, a procedure name, or a blood type has no fixed pattern, checksum, or length rule, and “Patient was prescribed metformin” is a sentence, not a format. A system tuned to structured identifiers can do well on Social Security and card numbers and still return nothing for a whole protected class. Recognizing clinical language takes semantic classification, not format matching. If your workload touches PHI, reproduce this row on your own data first. 

Payment cards: found, but not typed 

Sixteen expected payment-card number annotations were scored separately from CVVs and expiry dates. 

  Result 
Protecto correctly classified  16 of 16 · 100% 
PrivacyFilter detected  9 of 16 · 56% 
PrivacyFilter correctly classified  0 of 16 · 0% 

Card numbers are among the most format-regular data in the set. PrivacyFilter located most of them and none arrived with a payment-card type. Detection without the correct type leaves a card-security control nothing to select on. It is the cleanest case we have of locating a numeric span without identifying what it is.  

Span granularity and the context the application still needs 

The two products also divided text differently. Take a composite address: 

My driving license number is DL-0420110149646, renewed last year, and my current address is 45 Baker Street, London, NW1 6XE. 

Protecto  PrivacyFilter 
DL-0420110149646 → DRIVING_LICENSE_NUMBER  DL-0420110149646 → ACCOUNT_NUMBER 
45 Baker Street → ADDRESS  45 Baker Street, London, NW1 6XE → PRIVATE_ADDRESS 
London → CITY   
NW1 6XE → PINCODE   

A merged span is not unsafe in itself. It reduces the policy granularity available and may remove context the application still needs. With separate spans you can mask the street and the license number while keeping city and postcode for residency, regional entitlement, or fraud analysis. One merged span forces an all-or-nothing choice on the whole string. 

A note on the API response contract 

Protecto returned rewritten, protected text on 149 of 150 prompts. The tested PrivacyFilter interface returned detected spans, labels, and character offsets but no rewritten input. That difference concerns the tested API response contracts, not detection accuracy or model quality. Returning spans leaves the transformation to the integrating application, which then needs its own step when rewritten text is required. Which you want depends on your architecture. 

On replacement consistency, 344 of 347 measured replacements were consistent across the 150 prompts (a count of replacements, unrelated to the 344 expected annotations). Replacements kept the shape of structured identifiers and were weaker on dates and IP addresses, where separators stayed but character classes and field widths did not. 

A second cut of the data, and why we score it against ourselves 

A secondary analysis in the report uses a different denominator: 351 reference values that Protecto identified. It doesn’t combine with the 344-annotation scorecard. 

  Result 
Protecto  351 of 351 
PrivacyFilter not detected  87 
PrivacyFilter detected, not identified precisely enough for policy action  149 
PrivacyFilter detected and identified  115 · 33% 

The 351 of 351 is coverage by definition within this internal comparison, not independently validated recall. Protecto identified all 351 values used to build the reference set, so the set can’t contain a value Protecto missed. It is not a 100% accuracy claim and shouldn’t be quoted as one. 

The more useful disclosure is how we handled ambiguity. Three scoring rules cover ambiguous cases, and each one resolves in PrivacyFilter’s favor: 

  1. Label synonyms scored as correct. PRIVATE_EMAIL counted as email. 
  1. ACCOUNT_NUMBER scored as correct wherever it was applied to an actual bank account. That is the 13 instances above. 
  1. Span overlap treated as sufficient for detection. 

Remove all three rules and PrivacyFilter’s correctly identified total in this cut falls from 115 to 2. We kept the rules, and we are telling you they exist because the generous reading is the one we published. 

What we got wrong 

Protecto made errors in this run: 

  • One US Social Security number was classified as a Canadian SIN. 
  • One phone number written in Arabic-Indic numerals was not detected. 
  • One email address using a Cyrillic homoglyph was not detected. 

These are specific cases, not a complete accounting of our misses. The aggregates say the same: Protecto correctly classified 79% of the 43 edge and adversarial annotations, so about one in five of the hardest cases did not come back with the right type. On the 6 character-spaced values it classified 67%. The 90% headline is what happened on this test set, in this run, under these rules. It is not a ceiling or a guarantee. 

If you evaluate us, push hardest on the adversarial and character-spacing cases, where we are weakest. 

What to actually test in a proof of concept 

If you are evaluating any PII protection layer, including ours, this is the test design we would use. Nothing in it is specific to Protecto. 

  1. Annotate before you run. Pull 100 to 200 prompts from your own logs and write down the expected value and data type for each, before any vendor sees them. The annotation is the whole experiment. 
  2. Score the type, not the hit. Grade each result as correctly classified, generalized, misclassified, or not detected. One recall number hides the gap between the government-ID pattern and the healthcare pattern. 
  3. Use your worst traffic. Pasted spreadsheet rows, OCR output, partially masked values, code-switched sentences. Clean text flatters every vendor equally. 
  4. Trace one label end to end. Take the most common generalized label and list what is inside it. If one label carries twenty data types, your policy engine has twenty rules it can’t select. 
  5. Measure false positives separately. We didn’t, and you should. Over-flagging breaks prompt utility as surely as under-flagging breaks compliance. 
  6. Check that the answer survives. Run the protected prompt through your actual model and grade the response. 
  7. Test Layer 4 directly. Re-identification controls, audit records, tenancy isolation, residency, and deployment model can’t be inferred from API output. Get answers in writing and test them yourself. 

The question we would put first: is the type this system returns the type I would have assigned myself? Everything downstream depends on the answer.

Data Protection for Generative AI Applications
Free whitepaper
Data Protection for Generative AI Applications

How placeholders, role-based access and data governance reduce leak risk in AI applications.

About the author

Amar Kanagaraj

Founder and CEO of Protecto

Amar Kanagaraj is the Founder and CEO of Protecto, a company focused on securing enterprise data for LLMs, AI agents, and agentic workflows. He is a second-time entrepreneur with 20+ years of experience across engineering, product, AI, go-to-market, and business leadership. Before Protecto, Amar co-founded FileCloud and helped scale it to over $10M ARR as CMO. Earlier in his career, he worked at Sun Microsystems, Booz & Company, and Microsoft Search & AI. He holds an MBA from Carnegie Mellon University and an MS in Computer Science from Louisiana State University.

Share article

Table of Contents

Data Protection for Generative AI Applications
Free whitepaper
Data Protection for Generative AI Applications

Turn these challenges into your next AI advantage.

Talk to a solutions engineer about securing your data privacy, governance, and compliance.

Protecto Privacy Gateway for AI Chat is LIVE!
See how it works