When a PDF Is Too Dense to Redact
The same request has come up several times in the last few months, always with roughly the same shape. Someone has a very large PDF, several hundred pages long, and it is dense. It might be a claim file assembled from a dozen systems, a patient chart, an underwriting packet, or a case bundle, and almost every line has a name, a date, an account number, or an address in it. They need to hand the document to someone who should not see any of that, and they want to know whether redaction will do the job. It arrives as a PDF often enough that the rest of this post talks about PDFs, but the format is incidental to the argument. A long Word document, a scanned bundle, an exported mailbox, a database dump rendered as a report, or a few thousand pages of chat transcript all run into the same wall.
Redaction will do the job. Philter will parse the document, apply the policy, and hand back a PDF where the original characters are actually replaced rather than covered with a black rectangle, which is harder than it sounds and is a solved problem at this point. The output will be defensible, and in these particular cases it will also be close to worthless.
Redaction keeps the container and empties it
Redaction is a subtractive operation that leaves the shape of the document intact. That is exactly what you want when the identifiers are incidental to the content. A fifty-page contract with six names in it survives redaction with essentially all of its meaning, because the meaning was in the clauses and the names were labels attached to them.
Dense records are not like that. In a claim file or a chart, the identifiers are load-bearing, because the content is mostly a record of who did what, when, under which account, at which provider, against which policy number. Strip those out and the remaining sentences are grammatical scaffolding around holes. The document is still four hundred pages, it still has to be transferred and stored and retained, and the person on the other end cannot answer a single question with it.
Two things make this worse as documents get longer. The first is that over-redaction compounds. A policy tuned for high recall will act on marginal spans, and on dense text there are a lot of marginal spans, so every false positive removes a real fact. On a two-page document you notice and fix it. On four hundred pages you either accept the loss or loosen the policy, and loosening the policy is how sensitive values get through.
The second is that nobody reviews the output. Human review is the honest answer to probabilistic detection, and Arbiter exists for exactly that. But a reviewer working through tens of thousands of spans across four hundred pages is not a workflow anyone sustains, so the review either does not happen or it quietly becomes a spot check.
Measure it in reviewer-hours
That second point is worth turning into an actual number, because it is the most useful test I know for deciding how to handle one of these files. Ask how long it would take one competent person to read the redacted output and satisfy themselves that nothing sensitive survived. Not how long the redaction takes to run, which is seconds either way, and not how long it took to write the policy. Just the verification read, on one document, by one person who is paying attention.
The answer sorts the problem for you. A two-page intake form is a couple of minutes and nobody thinks twice about it. A fifty-page contract with a handful of names is perhaps an hour, which is tedious but completely normal for something going to an outside party. A four-hundred-page claim file with identifiers on every line is a different category of thing. The reviewer cannot skim it, because a missed account number is a missed account number wherever it happens to sit, so they are reading every line at the pace of careful proofreading. Call it a page a minute if you are being generous, and that is most of a working day for one document. Then remember that these usually arrive by the thousand.
When that number comes back in hours or days, it is telling you something more useful than that you need more reviewers. It is telling you the artifact is the wrong shape. Nobody is going to spend two days verifying one file, so what actually happens is a look at a few pages and a note in the ticket saying the document was redacted. The verification did not fail so much as it was never really attempted, and the risk the review existed to catch is still sitting in the file.
Automated checks help at the margins without replacing the read. You can pull the text back out of the redacted output and search it for every value you know was in the source, which is a good habit and does catch real mistakes. It only catches the values you already knew about, though, and the whole reason detection is probabilistic is that some of what is in the document was never on your list. Philter Scope can measure a policy against gold-standard data before you deploy it, which is a different exercise from confirming that this particular document came out clean.
Run the same test against the distilled version and the answer changes completely. Forty extracted fields with their provenance is ten minutes of reading, and a person will actually do it, for every document, every time. That shift matters more than the utility argument does on its own, because an artifact small enough to verify is one you can defend having sent.
Ask what the other end is actually going to do
Before deciding how to redact one of these files, I have started asking a different question. What is the recipient actually going to do with it? The answer is almost never that they are going to read it. They want to know whether the claim shows a prior injury, or what the diagnosis codes and dates of service were, or which counterparties appear across the bundle, or whether anything in there changes the risk rating. Sometimes the recipient is not a person at all, and the file is on its way to a model that scores documents like this one.
In every one of those cases the payload is a few hundred bytes and the four hundred pages were the carrier. The recipient is asking for information rather than for the document. Handing over the document and calling it redacted is answering a question nobody asked, at the cost of moving a large sensitive artifact one step further out.
Regulators have been making a version of this argument for a long time. Data minimization and purpose limitation under GDPR, and minimum necessary under HIPAA, all ask for the smallest amount of data that serves the purpose. A four-hundred-page redacted PDF is a poor fit for any of those tests, and thirty extracted, checked, pseudonymized fields is a much better one.
Distill first, then redact
The instinct is to redact and then use the result. For dense documents I think that order is backwards, because redaction destroys the material the extraction would have drawn on. Reverse it.
- Keep the original where it already lives, inside your own perimeter.
- Distill it there, against the unredacted text, into the specific fields the downstream consumer asked for.
- Redact and pseudonymize the extract, which is now small.
- Have a person read the whole thing before it leaves.
The constraint that makes this work is the first step, because distillation has to run where the data already is. This is not “upload the chart to a hosted model and ask for a summary,” which trades a document problem for a much worse one. It means a model you run yourself, a rules-based extractor, a template-driven parser, or a trained human abstractor. If you have no way to do the extraction inside your boundary, you are back to redacting the whole file, and back to the problem this post is about.
There is a real tension here with our own advice to redact before anything reaches a model. That advice is about data crossing a trust boundary, and nothing crosses one here. The extractor sees the original because it is already inside, running on your infrastructure, and its output is what gets redacted on the way out.
What the distilled artifact should look like
Prose summaries are the wrong output. They read well, and they are hard to check, hard to diff, and prone to smuggling identifiers back in through a free-text sentence. Something structured works better.
- Typed fields. A defined schema of what the consumer needs, so anything not on the list is not in the output by construction. This is the largest single privacy win available, and it comes from the schema rather than from the detection model.
- Provenance. Each field carries the page and offset it came from, so a reviewer or an auditor can walk back to the source. Note that provenance pointers are only safe while the source stays put. Ship them alongside a copy of the original and you have built a re-identification index.
- Deliberate handling per field. For each field, decide whether the value survives as-is, gets generalized, or gets pseudonymized. Identifiers you need for joins are the interesting case, and consistent pseudonymization is what preserves them. Phileas strategies such as
CRYPTO_REPLACEandFPE_ENCRYPT_REPLACEwith areplacementScopeofDOCUMENTorCONTEXTmap the same source value to the same stand-in, so relationships across records survive without the real values going anywhere. Those two strategies are also the reversible ones, through Philter’s governedPOST /api/reidentify, if a narrow re-identification path is part of the design. - Small enough to read. This is the reviewer-hours test again. A few dozen fields lands on the ten-minute side of it rather than the two-day side, which is the difference between a review step that exists on the architecture diagram and one that happens.
The shape of it matters more than the particular field names. An excerpt from one of these extracts, for a claim file, looks something like this.
{
"document": { "id": "claim-2f9c41", "pages": 412, "schema": "claims-extract-v3" },
"claimant_ref": "p_7c4a8d09ca37",
"provider_ref": "p_1f0e3dad9990",
"jurisdiction": "OH",
"incident_month": "2025-11",
"prior_injury_indicated": true,
"diagnosis_codes": ["S83.511", "M25.561"],
"treatment_span_days": 84,
"reserve_amount_usd": 42500,
"provenance": [
{ "field": "prior_injury_indicated", "page": 137, "offset": 2841 },
{ "field": "diagnosis_codes", "page": 12, "offset": 940 }
]
}
Four hundred and twelve pages came out as a couple of dozen lines. The two _ref values are consistent pseudonyms rather than hashes of convenience, so a second claim file involving the same provider still joins to this one without either file carrying the real name. The incident date is generalized to the month, because the underwriting question being asked does not need the day. There is no free-text notes field anywhere in the schema, which is deliberate, since a free-text field is where an identifier the schema never anticipated finds its way back in.
Run the extract through the same redaction policy you would have run over the document. It is a cheap backstop against a free-text field carrying something you did not plan for, and now the human review afterwards is actually feasible.
What you give up
This is a trade rather than a free win, and it is worth being clear about the cost. You are trading fidelity to the source for usable output. A redacted document at least preserves everything the detector did not touch, while an extract preserves only what the schema anticipated. If a question comes up later that the schema did not cover, the extract cannot answer it and someone has to go back to the original.
The extraction step also introduces its own errors. A model can miss a field, misread a value, or invent one, and no amount of downstream redaction catches a wrong number that is not sensitive. That is a correctness problem sitting next to the privacy problem, and it needs its own evaluation against known-good documents. Philter Scope measures whether the redaction did what the policy said, which is a different question again from whether the extract is faithful. Both need answering, and the second one gets skipped more often.
And you now have two artifacts to govern instead of one. The source does not stop existing when the extract is created. Retention, access, and audit still apply to it, and the extract has its own lifecycle on top.
When redaction of the whole thing is still right
Distillation is for the case where the recipient wants information. When the recipient wants the document, redaction is the only answer. Court production, a FOIA response, a regulatory filing, and discovery all have the same property, in that the document itself is the deliverable, its completeness is the point, and a summary is not a substitute. Redact those in full, page by page, with the structural care those workflows demand.
Density is the other test. If the identifiers in your documents are incidental, redaction leaves you with something useful and there is no problem to solve here. It is the combination of length and density that breaks it.
The question to ask first
Detection is probabilistic wherever it runs. Redacting the extract rather than the document does not change that, and you are still responsible for validating what comes out against your own data. What changes is the scale of what you have to check. A small artifact can be measured, reviewed, and understood in a way that four hundred redacted pages cannot, and it carries less of your risk with it wherever it goes.
So before you point a redaction pipeline at a very large, very dense file, ask what the person on the other end is going to do with it. If the answer is that they will pull twenty facts out of it, then redact the twenty facts and leave the four hundred pages where they are.
These pipelines tend to be more particular than they look from the outside, especially around where the extraction step runs and how you measure whether it is faithful. If you are working through one and want to talk the architecture over, get in touch.