PDF internals research

Why the Same PDF Compresses 5 Percent and 70 Percent

A PDF is not one compressed blob. It is an object graph, and only part of that graph is typically compressed. Whether a file shrinks by five percent or seventy percent depends on how much of its total size is stream data that compresses well, against how much is structural overhead and already-compressed data that cannot shrink at all. We built a four-file corpus and measured the split, so this claim rests on numbers you can regenerate rather than on intuition.

What this guide helps you decide

Two PDFs look similar and have similar page counts, but one compresses to almost nothing and the other barely changes. What actually decides the ceiling?

This research explains and measures the structure that determines PDF compressibility using this repository's own four-file corpus. It does not claim a universal compression ratio, and it does not describe a specific commercial compressor's internals.

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

The measurement

We generated four single-page PDFs with our own writer. One stores its text stream raw; one Deflate-compresses it; one has five times as much text; one adds forty empty metadata objects to inflate structural overhead. We then parsed each file's byte structure with our own analyzer and recorded the byte split.

What the numbers show

The raw file is 5135 bytes and reports a stream share of 89.3 percent, with zero Flate streams. The equivalent compressed file is 821 bytes with one 250-byte Flate stream, a stream share of only 30.5 percent. The compressed file is 84 percent smaller, but the reason is not that compression is powerful on this content. It is that 84 percent of the raw file was compressible content that compression removed.

The ceiling is set before compression runs

In the padded file, forty metadata objects add roughly five kilobytes of structure while the actual page content stays identical. The stream share drops to 4.2 percent even though the same Deflate stream is still present. Compressing this file harder cannot help, because almost none of its bytes are content. This is the mechanism behind a disappointing compression result: the file is mostly not the thing you are trying to compress.

Already-compressed data is the other wall

A text stream inflates by 18.328x to 32.06x in our corpus, which means it had real redundancy to remove. A JPEG image stream inside a PDF has no such redundancy: it was already compressed by the camera or editor. A PDF dominated by photographs will compress poorly no matter how good the compressor is, because the largest streams in that file are already at their entropy floor.

How to tell which case you are in

The practical test is to look at the stream share before compressing. If a file is mostly streams and those streams are text or vector content, expect a large reduction. If a file is mostly structure, or mostly already-compressed image streams, expect a small one. Our analyzer reports both numbers, and the two published cases in this corpus bracket the range from 84 percent reduction to almost none.

Why we publish the corpus rather than a table

A published ratio table would be a claim about files we do not control. The corpus is four small files we generate from text we own, and the analyzer is in the same directory. Anyone can run the two commands and get these exact numbers, or change the corpus and get different ones. That is the difference between a measurement and a promise.

Reading the four files as a single experiment

The corpus is designed so that each file isolates one variable. The raw file and the compressed file differ only in whether the text stream is deflated, so the difference between 5135 and 821 bytes measures the effect of compression alone. The forty-line and two-hundred-line compressed files differ only in how much text they contain, so the difference between 821 and 1287 bytes measures how size grows with content. The padded file differs from the forty-line compressed file only in that it carries forty additional empty metadata objects, so the difference between 821 and 5930 bytes measures structural overhead. Reading any one file alone tells you nothing; reading the set tells you which variable moves the result.

Why the raw file proves the point best

The raw file is the clearest evidence that compression is not the whole story. At 5135 bytes it reports a stream share of 89.3 percent and zero Flate streams, meaning almost the entire file is the uncompressed text stream. Compare that with its compressed twin at 821 bytes and a 30.5 percent stream share. The compressed file is not simply smaller; it is differently shaped, because the operation removed the bulk of what the file contained. A reader who expects every PDF to behave like the compressed file will be surprised by the raw one, and both are legitimate PDFs produced by the same writer.

What the inflation ratios say about the content

The forty-line stream inflates by 18.328 times and the two-hundred-line stream by 32.06 times. Both are high, and the second is higher because five times as much repetitive prose contains proportionally more repeated substrings for the compressor to reference. This is a property of the content, not of the compressor. Text written in a repetitive pattern is the best case for Deflate; text with varied vocabulary, embedded fonts, or binary payloads is progressively worse. The corpus demonstrates the best case, and the guides say so rather than generalising.

How to apply this to a file you did not create

The procedure generalises even though the numbers do not. Open the file's structure, total the stream bytes, and identify how many of those streams are already-compressed image data. If streams dominate and they are text or vector, a large reduction is plausible. If structure dominates, or the largest streams are JPEG or JPEG 2000, a small reduction is the honest expectation. The corpus gives you the mechanism to reason about an unfamiliar file; it does not give you a percentage to apply to it.

A worked walk through the forty-line file

Start with the raw file at 5135 bytes. Its single stream is the text of forty lines at ten point with thirteen point leading, stored uncompressed, and it occupies 4583 bytes, which is 89.3 percent of the file. Now deflate that same text at maximum level and store it instead: the stream becomes 250 bytes and the file becomes 821 bytes. The content did not change, the page count did not change, and the appearance did not change, yet 84 percent of the file disappeared. Nothing about the file's description would tell you this was possible; only the byte totals do.

Why the fifth file was necessary

Without the padded file the corpus would suggest that PDF compression is consistently dramatic, because three of four files shrink substantially. The padded file breaks that pattern deliberately. It keeps the same 250-byte content stream and still reports an 18.328 times inflation ratio, yet the file is 5930 bytes because structure dominates. The same compression that removed 84 percent of one file leaves this one almost untouched relative to its total size, and the difference is entirely outside the content stream.

The relationship between inflation and reduction

A higher inflation ratio does not automatically mean a larger percentage reduction, because the reduction also depends on how much of the file the stream represents. The two-hundred-line file has the highest ratio at 32.06 times but only reaches 55.6 percent stream share, while the forty-line file has a lower ratio at 18.328 times and a lower share at 30.5 percent. Both reduce dramatically in absolute bytes, but the share figure, not the ratio, tells you how much of the file was content to begin with.

What a file with many small streams looks like

The corpus uses one content stream per page. A real document often has several: one per page, plus form data, plus annotation appearance streams, plus embedded font programs. Each adds its own dictionary and length field, so the structural fraction rises with stream count even when total content is unchanged. A fifty-page report of plain text can therefore compress worse than a two-page letter with the same words, because it carries fifty times the per-page overhead.

What the four-file set cannot tell you

The set contains no images, no embedded fonts, no multi-page documents, and no encrypted files. Each of those would change the stream composition in ways this corpus does not exercise, so the guides do not predict an outcome for them. What the set does establish is the relationship between stream share and achievable reduction, which is a mechanism rather than a per-file expectation. A reader who takes the mechanism and applies it to an unfamiliar file will get the right qualitative answer even though the numbers will differ.

Why the eighty-four percent figure is scoped

The reduction from 5135 to 821 bytes is exact for those two files. It is not a general claim about PDF compression, and repeating it as one would be a mistake the corpus itself warns against. The padded file, which reduces far less despite carrying a real compressed stream, is included precisely so that a reader cannot take the headline number and generalise it. Any published figure in these guides names the file it came from.

How a reader would use this before compressing

Open the file's structure, total the stream bytes, and note the filter kinds. If streams dominate and they are text or vector content with a Flate filter, expect a substantial reduction. If structure dominates, or if the largest streams are DCTDecode or JPXDecode image data, expect a small one. That decision takes about a minute and prevents the common disappointment of compressing a file whose size was never in its content.

What changed in our understanding while building this

The initial expectation was that compression quality would explain most of the variation between files. Building the corpus showed otherwise: the same compressor at the same level produced an eighty-four percent reduction on one file and a near-zero one on another, with the only difference being how much of each file was content. The corpus was extended with the padded file specifically because the first three files did not make that clear, and the guides reflect the corrected understanding rather than the initial one.

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 compared the four corpus files against each other on total bytes, flate bytes, stream share, and inflation ratio, to isolate which structural property decides how much a file can shrink.

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