FileDummy Logo
FileDummy
File Processing & Conversion

How to Compress and Reduce PDF File Size with JavaScript

Reduce PDF file size in Node.js using Ghostscript and pdf-lib. Compare compression methods and test results with 100MB–500MB sample PDF files.

September 17, 20269 min read1,420 views
nodejspdfcompressionghostscriptpdf-lib

Large PDF files generated by scanner devices or graphic design tools can consume excessive bandwidth and fail email attachment limits. Compressing PDFs involves downsampling high-resolution raster images, stripping unneeded metadata, and compressing internal font streams.

PDF Compression Techniques

  • Image Downsampling: Reducing embedded images from 300 DPI (print) to 150 DPI or 72 DPI (web screen).
  • Flate Object Compression: Compressing content streams with zlib/deflate.
  • Removing Orphan Objects: Purging unused font subsets, embedded thumbnails, and revision histories.
Verified Test Asset.pdf

Download our 50MB PDF test file to benchmark your compression ratios and processing speed.

Download 50MB PDF Sample →

Compressing PDFs in Node.js using Ghostscript

Ghostscript remains the gold standard for high-ratio PDF stream compression:

TypeScript
import { exec } from 'child_process';
import util from 'util';
import fs from 'fs';

const execAsync = util.promisify(exec);

export async function compressPdfWithGhostscript(
  inputPath: string,
  outputPath: string,
  quality: 'screen' | 'ebook' | 'printer' = 'ebook'
): Promise<{ originalSize: number; compressedSize: number; savingsRatio: string }> {
  // -dPDFSETTINGS:
  // /screen = lowest quality, smallest size (72 dpi)
  // /ebook  = moderate quality, great for web reading (150 dpi)
  // /printer = high quality (300 dpi)
  const gsCommand = [
    'gs',
    '-sDEVICE=pdfwrite',
    '-dCompatibilityLevel=1.4',
    `-dPDFSETTINGS=/${quality}`,
    '-dNOPAUSE',
    '-dQUIET',
    '-dBATCH',
    `-sOutputFile="${outputPath}"`,
    `"${inputPath}"`,
  ].join(' ');

  await execAsync(gsCommand);

  const origStats = fs.statSync(inputPath);
  const compStats = fs.statSync(outputPath);
  const savings = (((origStats.size - compStats.size) / origStats.size) * 100).toFixed(1);

  return {
    originalSize: origStats.size,
    compressedSize: compStats.size,
    savingsRatio: `${savings}%`,
  };
}

Client-Side Compression with pdf-lib

For lightweight PDF stream compression directly in the browser:

TypeScript
import { PDFDocument } from 'pdf-lib';

export async function optimizePdfInMemory(pdfBytes: Uint8Array): Promise<Uint8Array> {
  const pdfDoc = await PDFDocument.load(pdfBytes);
  // Re-saving with object stream optimization
  return await pdfDoc.save({ useObjectStreams: true });
}
NDL

Nguyen Dai Long

Author

Backend Lead • Distributed Systems & Cloud Edge Architecture Specialist

4+ years designing high-throughput file ingestion pipelines, database architectures, and distributed edge storage on Cloudflare R2 & AWS S3. Founder of FileDummy and the NDL Ecosystem.

Was this article helpful?

Click Like to support the author and help other developers discover this guide.

Engineering Discussion & Feedback (0)

Share benchmark results, report edge cases, or ask technical questions.

0/3000

No comments yet. Be the first developer to start the discussion!

Frequently Asked Questions

What is the best tool for compressing PDFs in Node.js?â–¾

Ghostscript achieves 60–80% size reduction on image-heavy PDFs using the ebook or screen quality preset. For pure-code compression without a binary dependency, pdf-lib can remove metadata and optimize object streams, but achieves less dramatic reduction on already-optimized PDFs.

Why does my compressed PDF look blurry?â–¾

PDF compression primarily downsamples embedded images. The screen preset targets 72dpi (web viewing), which degrades print quality. Use the printer preset (300dpi) for documents that need to be printed.

Can I compress a PDF without losing text quality?â–¾

Yes. Text and vector graphics are resolution-independent and do not degrade. Only embedded raster images are affected. Use Ghostscript's -dColorImageResolution flag to control image-only downsampling.

Related Articles