PDF internals research

What Our PDF Analyzer Cannot Tell You

A measurement tool earns trust by stating where it stops. Our PDF analyzer reports byte structure, and it is deliberately narrow. It does not render, it does not decrypt, it does not validate fonts, and it does not evaluate readability. Each of those omissions bounds which claims this repository is entitled to make, so we list them explicitly rather than leaving a reader to discover them.

What this guide helps you decide

If the analyzer reports object counts, stream shares, and inflation ratios, what is it still not able to say about a PDF?

This research documents the boundaries of this repository's PDF analyzer. It does not claim the analyzer is unsuitable for its stated purpose, and it does not describe other PDF tooling.

Try it on the anchor product: BeanNest Tools /pdf/.

It does not render

The analyzer reads object structure and never draws a page. It can report that a content stream exists and how large it is. It cannot report what the page looks like, whether text overlaps, or whether a font actually has the glyphs a document needs. All appearance claims are out of scope.

It does not decrypt

An encrypted PDF stores streams that will not inflate without a key. The analyzer recognises an encryption filter name, but it cannot decompress those streams, so a size claim about an encrypted file would rest on encrypted byte counts rather than content. We do not make those claims.

It does not analyse font subsetting

The analyzer lists font objects and whether each appears embedded, which is enough to say a file carries a font. It does not determine which glyphs a subset contains. A claim about text extraction reliability would require that deeper analysis, so we do not make extraction claims.

It does not validate conformance

Nothing here checks PDF/A, PDF/UA, or any standard profile. A file that parses cleanly and reports sensible object counts can still fail a conformance validator. Structure measurements and conformance are separate questions and we answer only the first.

It does not generalise beyond the corpus

The published ratios come from four small generated files. They describe those files exactly and demonstrate a mechanism. They do not predict behaviour for a scanned document, a form, a presentation, or a file with embedded video. Every number in these guides is scoped to the corpus that produced it.

Why publishing limits strengthens the result

A tool with unstated limits invites misuse. By naming exactly what the analyzer does not do, these guides can state their claims narrowly and remain correct. The corpus is small, the tool is narrow, and the conclusions are correspondingly precise.

Why a narrow tool is more useful than a broad one

A tool that claims to do everything must be trusted on everything, and any single capability it lacks undermines the whole. A tool that states a narrow purpose can be checked against that purpose precisely. This analyzer measures byte structure and inflation on small controlled files. Within that boundary its output is exact and reproducible. Outside it, it is silent rather than approximate, and silence is the safer failure mode for a measurement tool.

The gap between parsing and rendering

A file can parse perfectly and render badly, or render perfectly and parse oddly. These are different questions answered by different software. The analyzer answers only the structural one, which matters because the guides make structural claims about size. If they made appearance claims, this evidence would be irrelevant to them. Keeping the claim type aligned with the evidence type is the discipline that the limits list enforces.

What the corpus deliberately excludes

The four corpus files contain no images, no embedded fonts, no encryption, no forms, no annotations, and no multi-page structure. Each of those would add analysis work the current tool does not perform. Excluding them keeps the corpus small and the claims exact. It also means the guides cannot cite a measured number for any of those cases, and they do not try to.

How to extend the tool without weakening it

The correct way to broaden this analyzer is to add one capability at a time with its own corpus case and its own honest claim. Adding rendering support would mean adding a renderer and a means of comparing output, not inferring appearance from structure. Adding encryption support would mean handling a key exchange and a decryption step, not guessing at plaintext. Each addition is a project, and the limits list should shrink only as each one is actually completed.

What the analyzer does report reliably

It reports the PDF version from the header, the object count, the stream count, total stream bytes and their share of the file, the Flate stream count and bytes, the JPEG stream count and bytes, the font count with an embedded flag per font, the image count with dimensions and filters, and one verified inflation sample. Each of those is a direct reading of the bytes or a verified decompression, not an inference, which is the property that lets the guides cite them individually.

Why image filters matter to a size claim

The analyzer distinguishes DCTDecode, which is JPEG, from JPXDecode and from the fax and JBIG2 filters. This matters because those streams are already compressed and will not inflate. A file whose streams are mostly DCTDecode has a compression ceiling that no text-oriented compressor can raise. Reporting the filter kinds per stream is what allows the guides to explain why a photo-heavy document compresses differently from a text document without measuring a photo-heavy document.

How the corpus would need to grow

To support a claim about image-heavy PDFs the corpus would need at least one file containing a real image stream with a known encoder and dimensions, plus a comparison against the same page with the image stored differently. That is a legitimate extension and it is not attempted here. Until it exists, the guides say that already-compressed streams set a ceiling and cite the filter classification rather than a measured photo corpus.

Why the limits list is part of the evidence

The evidence contract in this repository treats claim, evidence, and review as separate steps. A limits list is how the claim step stays honest about its scope. If the guides omitted it, a reader could reasonably assume the analyzer handles rendering or encryption, and could then build on a claim the evidence never supported. Including the list converts an unknown boundary into a stated one, which is the same discipline applied in every other cluster in this corpus.

What the analyzer reports and why each field is trustworthy

It reports the PDF version read from the header, the object count and stream count from the byte scan, total stream bytes and their share of the file, the Flate and JPEG stream counts and byte totals, the font count with an embedded flag per font, the image count with dimensions and filter kinds, and one verified inflation sample. Every field is either a direct reading of bytes or a verified decompression, which is why the guides can cite them individually without hedging each one.

Why filter classification matters to a size claim

The analyzer distinguishes DCTDecode, which is JPEG data, from JPXDecode, from fax and JBIG2, and from the text-oriented filters. Image streams are already compressed and will not inflate, so their presence sets a ceiling no compressor can raise. Reporting filter kinds per stream lets the guides explain why a photo-heavy document behaves differently without needing a photo corpus, because the explanation rests on the filter classification rather than on a measured photo file.

How the corpus would need to grow to support broader claims

Supporting a claim about image-heavy PDFs would require at least one file containing a real image stream with known dimensions and an encoder, plus a comparison against the same page stored differently. Supporting a claim about encrypted files would require a key and a decryption path. Each is a legitimate extension and none is attempted here, which is why the guides describe filter behaviour and decline to measure a corpus they do not have.

Why the limits list belongs to the evidence

The evidence contract in this repository separates claim, evidence, and review. A limits list is how the claim step stays honest about its scope, because it converts an unknown boundary into a stated one. If the list were omitted, a reader could reasonably assume the analyzer handles rendering or encryption and build on a claim the evidence never supported. Including it is the same discipline the other research clusters apply to their own definitions.

How to extend the tool without undermining it

Add one capability at a time, with its own corpus case and its own honest claim. Rendering support would mean adding a renderer and an output comparison rather than inferring appearance from structure. Decryption support would mean handling a key exchange rather than guessing at plaintext. Each addition is a project, and the limits list should shrink only as each one is actually completed and its corpus exists.

First-party evidence and provenance

How we checked this

We generated four single-page PDFs with this repository's own writer, then parsed each file's raw byte structure with this repository's own analyzer. Both tools are dependency-free and deterministic, so the same commands reproduce the same numbers on any machine. For this guide we enumerated the analyzer's actual capabilities against a rendering, decrypting, font-subsetting, and conformance-checking baseline, and recorded each capability the analyzer does not have.

Method
We generated four single-page PDFs with this repository's own writer, then parsed each file's raw byte structure with this repository's own analyzer. Both tools are dependency-free and deterministic, so the same commands reproduce the same numbers on any machine.
Environment
Node.js on a desktop workstation. No PDF library, no network access, and no third-party file was used. The corpus is produced from text this repository owns.
Captured
Reviewed by
BeanNest Studio

Repository evidence artifacts:

  • tools/research-evidence/pdf/analysis-2026-09-20.json
  • tools/research-evidence/pdf/README.md