BASALT · JOURNAL
Redacting scanned documents, where the text you cannot see is the problem
A scanned page looks like a picture, so people assume redacting it is a matter of painting over pixels. Then the document goes out, someone selects the black rectangle, and a name appears in their clipboard. The text was never visible, which is exactly why nobody checked for it.
This is the OCR text layer, and it is the most reliable way to leak a redacted scan. Understanding how it gets into the file explains how to get it out.
How a scan becomes searchable
A raw scan is a single image XObject per page. There is no text, no font, and no way to search it. Almost every workflow that touches scanned documents fixes this by running optical character recognition and adding the results back into the PDF.
The standard technique is a text layer. The recognizer produces character strings with bounding boxes. The tool writes those strings into the page content stream using ordinary text-showing operators, positioned to sit exactly under the corresponding glyphs in the image, and sets the text rendering mode to invisible using the Tr operator with mode 3. Nothing renders. Search, copy, and text extraction all work because they read the operators, not the picture.
This happens in more places than people realize. Multifunction copiers do it on the way to email. Document management systems do it on ingest. E-discovery platforms do it as a matter of course. Preview and other viewers can do it on demand. A PDF you received as a scan has frequently been through OCR at least once before it reached you, sometimes without any visible indication.
The result is a page with two independent representations of the same words: pixels and character codes. Redaction has to remove both.
The failure, precisely
A tool that treats a scanned page as an image will do one of two things when you draw a redaction mark.
It may append a filled rectangle to the content stream. This is the classic drawing failure, and it leaves both the pixels and the text intact underneath. Discussed further in the black box myth.
Or it may do the image work correctly, decoding the image XObject, zeroing the pixels inside the marked region, and re-encoding the image so the original samples are no longer in the file. That is genuine pixel destruction, and it is what you want. But if the tool's model of the page is "this page is an image," it never looks at the text-showing operators sitting in the same content stream. The invisible text survives an otherwise correct image redaction.
That failure mode is nastier than the drawing failure because it passes a visual check completely. Zoom in, select, drag: the pixels really are gone. The characters are still there.
What correct handling looks like
Treat the page as what it is, a content stream that happens to contain both an image and invisible text, and process both.
For the image. Decode the image XObject to samples, replace the samples inside the marked region with a constant, and re-encode. The output image must be a new stream that never contained the original data. Note that the marked region has to be mapped from page coordinates through the current transformation matrix into image space, because images are drawn into a unit square scaled by the CTM, and getting that transform wrong shifts the destroyed area. Rotation, downsampling, and image masks all complicate this and all have to be handled rather than approximated.
For the text. Find every text-showing operator whose glyph run intersects the marked region, including runs with rendering mode 3, and excise the affected character codes from the operands. Re-emit the surviving glyphs with corrected positioning so that partially covered runs keep their layout. Invisible text gets exactly the same treatment as visible text, because extraction does not care about rendering mode.
For everything else. OCR output sometimes lands in /ActualText entries on marked content, and some pipelines store recognition results in annotations or in a sidecar structure. Metadata often records the OCR engine and the original filename. Attachments may hold the original TIFF. A page-level operation touches none of these. See hidden data in PDFs.
Checking a file you received
Before you redact a scan, find out whether it has a text layer, because that determines what you are dealing with.
Open the document and try to select text on the page. If a selection highlight appears where the printed words are, there is a text layer. If you can select and copy, you can confirm the content. Alternatively run any command line text extractor over the file: output means a text layer exists, no output means the page is pure image.
A page with no text layer is simpler but not simple. You still have metadata, attachments, and annotations to deal with, and if anyone in the chain adds OCR later, the redacted image is the only thing protecting the content, so the pixel destruction has to be real.
Verify by extraction, not by eye
The only check that catches the OCR failure is a text extraction of the finished file.
Run an extractor over the output. Search the extracted text for the terms you removed. Then read the annotation values, the form field values, the embedded attachments, and the metadata packets and search those. A visual inspection cannot see invisible text, which is the entire problem.
If you redacted a photograph or a signature block, also extract the images from the output and look at them directly, since a viewer may be showing you a composited page rather than the stored image. How to verify a PDF redaction sets out the full procedure.
Should you OCR before redacting
There is a reasonable argument for doing OCR first: it makes the document searchable, which makes it far easier to find every occurrence of a name across hundreds of pages rather than reading each one. Searching for identifiers you might otherwise miss is a real benefit.
The condition is that your redaction step must handle the text layer you just created. If it does, OCR first is a net gain in thoroughness. If it does not, you have manufactured the leak yourself.
Frequently asked questions
Can you redact a scanned PDF?
Yes. A scanned page is an image, so redacting it means decoding the image, destroying the pixels inside the marked region, and re-encoding so the original samples are no longer stored in the file. If the scan has been through OCR, you must also remove the invisible text layer beneath the image, because that text is extractable even though nothing renders.
Why can I still copy text from a redacted scan?
Because the page carries an invisible OCR text layer that was not removed. OCR tools write recognized characters into the content stream using ordinary text-showing operators with rendering mode 3, positioned under the scanned image, so nothing displays but search, copy, and extraction all read them. Destroying the pixels alone leaves that text fully intact.
What is an OCR text layer in a PDF?
An OCR text layer is a set of invisible text-showing operators added to a page so that a scanned image becomes searchable. The recognizer produces strings with bounding boxes, and the tool writes those strings into the content stream positioned under the matching glyphs in the image, with the rendering mode set so nothing paints. Viewers show only the image, while extractors read the characters.
How do I know if my scanned PDF has a text layer?
Try to select text on the page in any viewer: if a selection highlight appears over the printed words, a text layer exists. You can also run a command line text extractor over the file, where output means a text layer is present and empty output means the page is pure image. Do this before redacting, because it determines what has to be removed.
Does drawing a black box on a scan hide the text?
No. Drawing appends a fill operation to the content stream, which paints over the earlier marks without deleting anything, so both the original image samples and any OCR text remain in the file. The image can be extracted intact and the text can be copied straight out from under the rectangle.
Should I run OCR before or after redacting?
Running OCR first is often better, because a searchable document lets you find every occurrence of a name across hundreds of pages instead of reading each one, which makes the redaction more thorough. The condition is that your redaction tool must remove the text layer you just created. If it only handles pixels, running OCR first creates the leak.
How do I check that a scanned redaction worked?
Extract all text from the finished file with a parser that had no part in writing it and search that output for the terms you removed, since invisible text cannot be caught by looking at the page. Then extract the page images and inspect them directly, because a viewer may be showing a composited page rather than the stored image. Also check metadata, annotations, and attachments.
Does flattening or printing to PDF remove the OCR layer?
Printing to PDF or rasterizing a page does generally destroy the text layer, because the output is regenerated as pixels. It also destroys everything else useful, including searchability, bookmarks, and fidelity, and it typically resamples the page at printer resolution. It leaves you with no record of what was removed and no way to prove it, so it is a blunt substitute for real redaction.
Doing it in Basalt
Basalt treats a scanned page as what it is: an image XObject and, usually, an invisible text layer in the same content stream. It destroys and re-encodes the pixels inside a mark and excises the text under that mark glyph by glyph, including runs in invisible rendering mode, then strips metadata, XMP, attachments, hidden layers, and stale thumbnails and writes the file as one generation. Before anything is saved, a built-in verifier re-opens the written bytes with an independent parser and proves the removal, and if it cannot prove it, nothing is written. Basalt also includes OCR, so you can make a scan searchable, find every occurrence of an identifier, and redact it in the same window. It is $29 once for up to three Macs, free for 24 hours, at basaltformac.com.
Redaction that proves itself
Basalt destroys the content you mark, then re-opens the file it wrote and proves the content is gone before it saves anything. Your documents never leave your Mac.