Computers & IT

qpdf vs Ghostscript for PDF Compression: A Measured Comparison

Every thread about shrinking PDFs on the command line ends the same way: someone says “use Ghostscript,” someone else says “use qpdf,” and nobody posts numbers.

So I ran both against three PDFs that fail in different ways — a text-only document, a 150dpi scan, and a 300dpi scan — and measured output size and wall-clock time for each. The result is not “one tool wins.” It’s that picking the wrong one costs you either 85% of your potential savings or a 30% size increase, and the choice comes down to two properties of your file that most guides never mention.

The short version

Does your PDF carry large images, or fonts embedded without subsetting? Either one → Ghostscript. Neither → qpdf. Getting this backwards is the entire problem.

Test 1 — Text-only document (40 pages, 18,643 bytes)

Command Output Change Time
qpdf max compression 18,530 b −0.6% 28 ms
gs /ebook 24,514 b +31.5% 334 ms
gs /screen 24,859 b +33.3% 549 ms
gs /printer 31,266 b +67.7% 307 ms
qpdf --linearize 25,812 b +38.5% 10 ms

Ghostscript made this file bigger in every configuration, and the most aggressive preset was the second worst. There are no images to downsample, so the presets have nothing to act on while the rewrite cost applies anyway.

The mechanism behind that growth is worth knowing if it happens to you: pdfwrite leaves page dictionaries outside its object streams, and the overhead scales with page count rather than content. I measured it in why Ghostscript made your PDF bigger.

qpdf saved 0.6% — which sounds like failure until you notice it’s the only tool that didn’t make things worse, and it did so 12× faster. On this particular file there was genuinely nothing left to squeeze, and not damaging it is the correct outcome — but that is a property of this document, not of text PDFs in general, as the next section shows.

The exception that matters: embedded fonts

Before you conclude “text means qpdf,” check what the file actually carries. My test document had no embedded fonts at all — and that turns out to be the unusual case. Real text PDFs from LaTeX, Word or InDesign almost always embed their fonts, and often ship them unsubsetted: the entire typeface, when the document uses forty characters of it.

Ghostscript subsets embedded fonts. qpdf cannot — it restructures the file without re-encoding font programs. So I built a second text-only document, same 20 pages, with one non-base-14 font embedded and unsubsetted:

Text PDF, 73,378 bytes, no images Output Change
gs /ebook 17,437 b −76.2%
qpdf max compression 70,322 b −4.2%

The verdict flips completely. pdffonts shows why — before: emb yes / sub no; after Ghostscript: emb yes / sub yes, with the tell-tale LSMYYW+ subset prefix on the font name. That 56 KB was one typeface the document barely used.

So “text file” is not the deciding property. Unsubsetted embedded fonts are a Ghostscript job even with zero images.

Watch the last row. qpdf --linearize grew the file by 38.5%. Linearization restructures a PDF for fast web viewing — it is a delivery optimization, not a compression one, and it costs space. If you reached for it expecting smaller output, that’s the wrong tool.

Test 2 — 300dpi scan (1 page, 1,774,318 bytes)

Command Output Change Time
gs /screen 107,369 b −93.9% 195 ms
gs /ebook 270,988 b −84.7% 213 ms
gs /printer 1,776,871 b +0.1% 159 ms
qpdf max compression 1,774,085 b −0.0% 16 ms

Complete reversal. Ghostscript cut the file by 93.9%; qpdf removed 233 bytes out of 1.77 MB.

This is not a defect in qpdf. It restructures a PDF without re-encoding page content, so it never touches the embedded images — and on a scan, the images are the file. qpdf did exactly what it is designed to do; on this file that amounts to nothing.

Note gs /printer also achieved nothing. Its target is 300dpi, the source is 300dpi, and Ghostscript only downsamples when the source exceeds ~1.5× the target. Same tool, same file, one preset saves 94% and another saves zero.

Test 3 — 150dpi scan (3 pages, 1,914,753 bytes)

Command Output Change Time
gs /screen 285,462 b −85.1% 200 ms
gs /ebook 1,914,754 b +0.0% 138 ms
qpdf max compression 1,914,213 b −0.0% 45 ms

The middle row is the trap that sends people to forums. /ebook targets 150dpi and the source is 150dpi, so the ratio is 1.0 and not a single image is touched — the command completes silently having done nothing. Drop to /screen (72dpi) and the same file loses 85%.

I measured that threshold behavior separately in Ghostscript /ebook not reducing PDF size.

The two-stage pipeline is not worth it

A common suggestion — one I have made myself — is to run Ghostscript first for image downsampling, then qpdf to recompress the structure Ghostscript rebuilt. It sounds right. I measured it:

File After Ghostscript After qpdf pass Extra gain
300dpi scan 270,988 b 270,787 b 201 bytes (0.07%)
150dpi scan 285,462 b 284,924 b 538 bytes (0.19%)

Under a fifth of one percent. The logic is sound but the arithmetic kills it: on an image-heavy file, structural overhead is a rounding error next to the image data. And on a text file whose fonts are already subset, you shouldn’t be running Ghostscript at all.

Skip the second pass on image-heavy files. The exception is the one text case this article does route to Ghostscript: on a text PDF with unsubsetted embedded fonts, a qpdf pass over the Ghostscript output recovered a further 9% in testing, because Ghostscript’s structural output is not size-optimal on text-only files.

Speed, since nobody mentions it

qpdf finished in 16–45 ms across all three files. Ghostscript took 138–549 ms — roughly 10× slower, because it interprets and regenerates the entire page description rather than restructuring the file.

Irrelevant for one document. Very relevant for a batch job over ten thousand: at 300 ms each that’s about 50 minutes of CPU, versus under 8 minutes with qpdf. If most of your corpus is text with already-subset fonts, routing those files to qpdf is a large win on both size and time — but check pdffonts first, because unsubsetted fonts are worth the slower Ghostscript pass.

Decision table

Your file Use Expect
Text, no images, fonts already subset qpdf (full command below) 0–25% smaller depending on how redundant the structure is; can grow files with very few objects
Scan or photo-heavy, 300dpi+ Ghostscript /ebook 80–95% smaller
Scan at 150dpi or lower Ghostscript /screen 85% smaller (/ebook does nothing)
Text with unsubsetted embedded fonts Ghostscript /ebook up to −76% from font subsetting alone
Mixed / unsure Run both, keep the smaller qpdf costs ~30 ms to try
Needs fast web streaming qpdf --linearize Larger file, faster first-page render

Full commands — the table abbreviates; these are the runnable forms:

gs -sDEVICE=pdfwrite -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=out.pdf in.pdf
qpdf --object-streams=generate --recompress-flate --compression-level=9 in.pdf out.pdf

Checking which case you’re in

The whole decision rests on whether your PDF is image-dominated. pdfimages from poppler-utils answers it:

pdfimages -list yourfile.pdf

Ignore the x-ppi column for this first decision. It reports resolution, not how much of the file the image occupies — a single 300ppi logo shows x-ppi 300 while contributing a couple hundred bytes. Read the size column instead: if the image rows account for most of the file, Ghostscript does the heavy lifting. Once you know images dominate, then compare x-ppi against the preset targets (72 / 150 / 300) to pick which preset actually fires.

If there are no image rows — or they are trivially small — check the fonts before defaulting to qpdf:

pdffonts yourfile.pdf

An emb of yes with sub of no means Ghostscript has a subsetting win available. How large depends on what share of the file the font programs occupy and how much of the typeface the document actually uses — measured cases here ranged from roughly 45% to 76%. If fonts are already subset, or not embedded at all, qpdf is the right call.


Test setup. Measured 26 July 2026 · Ghostscript 10.05.1 · qpdf 12.2.0 · Linux. Test files: a 40-page text-only PDF generated from PostScript, and grayscale scan-style PDFs at 150dpi (3 pages) and 300dpi (1 page). Times are wall-clock for a single run on an otherwise idle machine and will vary with hardware; the ratio between the two tools is the durable figure. Sizes are the actual output files.

References: Ghostscript High Level Devices · qpdf manual