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