BASALT · JOURNAL

Hidden layers in a PDF, and why switching one off is not removing it

2026-08-06 · pdf layers

PDF layers are not layers in the image editing sense. They are optional content groups: a visibility switch applied to marks that are already in the page's content stream. Turning a group off changes what a viewer draws and changes nothing about what the file contains.

That distinction is the whole problem. A document can look correct on screen, print correctly, and still hand over draft language or an earlier version of a figure to the first person who runs text extraction on it.

How optional content is structured

The document catalog carries an /OCProperties dictionary. It lists every optional content group under /OCGs and holds configuration dictionaries: a default configuration under /D and any alternates under /Configs. A configuration says which groups start on and which start off, using /ON and /OFF arrays plus a /BaseState.

Each group is an object with a /Name, which is what appears in a viewer's layers panel, and optional usage information describing intent, for example that a group should be visible on screen but not in print.

Membership works two ways. Content inside a page's stream can be bracketed by BDC and EMC marked content operators referencing the group, making those drawing operations conditional. Alternatively an entire XObject or annotation can carry an /OC entry naming the group. In both cases the operators and objects are unconditionally present in the file. Only the drawing is conditional.

Off means invisible, not absent

This is the point that matters more than anything else here.

An optional content group that is switched off renders nowhere. It does not appear on screen, it does not appear in print, it does not appear in a rendered image of the page, and it does not appear in a rendering-based visual comparison of two documents.

Its text still extracts. Copy and paste, pdftotext, an e-discovery processing pipeline, a search index, a screen reader: all of these read the content stream rather than the rendered output, and most do not evaluate optional content state at all. The words come out in reading order alongside the visible text. The same is true of an image assigned to a hidden group, which remains a stream in the file, extractable by any tool that walks objects.

So switching a layer off is a display setting, not a removal. It is the visual equivalent of drawing a black box over text, which also leaves the words in the file, except worse in one respect: a black box is at least visible to a reviewer looking at the page. A hidden layer is visible to nobody.

Where hidden layers come from

Nobody sets out to ship a document with a concealed layer. They arrive through normal production.

CAD and engineering exports carry the source drawing's layer structure, which routinely includes dimension sets, revision clouds, contractor notes, and superseded geometry, so a drawing exported for a client can contain the internal markup layer with its default state off. Design files behave the same way: a proof from a layout tool can carry alternate headlines, unapproved pricing, notes to the designer, and the figure that was replaced last week.

Template-driven documents use optional content to switch between variants: one jurisdiction's language and another's, a draft watermark turned off before sending. All variants remain in the file; only the switch changes. Some workflows even do this deliberately for redaction, putting the sensitive material on a layer and turning the layer off, which produces a document that looks redacted and is not.

Detecting layers in a file you received

A viewer with a layers panel will show you the groups a document declares, which is the fast check. It is not complete, because a configuration can be built so a group does not appear in the panel, and a viewer without a layers panel gives you nothing.

The direct check is to expand the document with qpdf --qdf --object-streams=disable and look for /OCProperties in the catalog, then read the /OCGs array and the /D configuration's /ON and /OFF entries. That tells you how many groups exist, what they are named, and which start off.

The useful follow-up is comparing what you can see against what extracts. Run pdftotext and read the output next to the rendered pages. Text that appears in the extraction but nowhere on the page is either in a switched-off group, drawn in rendering mode 3, or covered by an opaque graphic, and the technique is the one described in how to check whether a PDF was really redacted.

Removing a layer for real

Getting rid of a hidden layer means removing its content, not changing its state. There are two honest ways.

The first is to delete the marked content sections referencing the group, along with any XObjects and annotations carrying an /OC entry naming it, then remove the group from /OCProperties and rewrite the file so orphaned objects are dropped. Done correctly, nothing extracts because the operators are gone.

The second is to flatten the document to its visible state: resolve every group according to the current configuration, keep what is on, discard what is off, and remove /OCProperties entirely. You lose the ability to toggle anything, which is usually the point when a file is going out.

Either way the result has to be written as a single generation, because incremental updates append changes while leaving the original bytes in place, so a layer removal saved as an increment leaves the layer recoverable in the previous revision. And removing a layer touches nothing else: metadata, embedded files, OCR text, and bookmark titles are separate structures with separate removal steps. How to see everything a PDF is actually carrying covers the rest of that pass.

Frequently asked questions

What are PDF layers?

PDF layers are optional content groups: named objects declared in the catalog's /OCProperties dictionary whose visibility can be switched on or off. Content joins a group either by being bracketed with marked content operators inside the page's content stream or by an object carrying an /OC entry naming the group. The grouping controls only whether marks are drawn, not whether they are in the file.

Does hiding a layer in a PDF remove the content?

No. A switched-off optional content group is invisible on screen and in print, but every drawing operator and image stream belonging to it remains in the file exactly as before. Text on a hidden layer still extracts with copy and paste, pdftotext, and any e-discovery pipeline, because those tools read the content stream rather than the rendered output. Switching a layer off is a display setting.

Can text on a hidden PDF layer be extracted?

Yes, routinely. Most text extractors do not evaluate optional content state at all, so glyphs belonging to a group that is off come out in reading order alongside the visible text. This is why a document that looks clean on every page can still disclose draft wording or internal notes to the first person who runs an extraction. Rendering-based review will never show you this.

How do I know if a PDF has hidden layers?

Open the layers panel if your viewer has one, and check the catalog directly for an /OCProperties dictionary by expanding the file with qpdf --qdf --object-streams=disable. The /OCGs array lists every group and the default configuration's /OFF array names the ones that start hidden. A useful cross-check is comparing pdftotext output against the rendered pages.

Why do PDFs from CAD or design tools have layers?

Because the exporters carry the source file's layer structure into the PDF. An engineering drawing exports with its dimension sets, revision clouds, and contractor notes as separate groups, and a layout tool exports with alternate headlines, superseded figures, and notes to the designer. Groups that were off in the source are off in the export, so the material ships without anyone seeing it.

How do I permanently remove a layer from a PDF?

Delete the marked content sections referencing the group and any XObjects or annotations carrying an /OC entry naming it, remove the group from /OCProperties, and rewrite the file so orphaned objects are dropped. The alternative is flattening the document to its current visible state and removing /OCProperties entirely. Either result must be written as a single generation, since an incremental save leaves the layer in the previous revision.

Is putting sensitive text on a hidden layer a safe way to redact?

No, and it is one of the more dangerous mistakes available, because the document passes visual review on every page while the sensitive text extracts in full. Real redaction removes the glyphs and re-encodes image pixels so the content is not in the file at all. How to redact a PDF so the text is actually gone covers what that requires.

Does printing a PDF to a new PDF remove hidden layers?

Usually yes for content that was switched off, because printing regenerates the page from what draws and hidden content draws nothing. It is a blunt instrument: you lose searchable text, bookmarks, tagging, and form structure across the entire document, the new file typically picks up fresh metadata naming your machine, and it silently discards layers you wanted to keep toggleable.

Doing it in Basalt

Basalt reports hidden layers in its inspect pass, alongside metadata, XMP, embedded files, annotations, OCR text layers, JavaScript, and saved generations, so you learn a document has optional content before you send it rather than after. Its clean up tool removes optional layers and embedded files and edits or removes bookmarks, then saves a cleaned copy, leaving your original untouched.

Documents are parsed only inside a sealed engine process with no network entitlement, enforced by macOS at the code signature level, which you can confirm with codesign -d --entitlements :- /Applications/Basalt.app/Contents/XPCServices/BasaltEngine.xpc. No account, no telemetry, no cloud. It is $29 once for up to three Macs, free for 24 hours.

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.

DOWNLOAD BASALT 2.3.0 BUY $29 FREE FOR 24 HOURS · MACOS 13+