Get started

How to crop a PDF

Crop a PDF page online for free, or automate it with pdf-lib, PyMuPDF, Ghostscript, and qpdf. Covers CropBox vs MediaBox and batch cropping.

benoitded8 min read

Cropping a PDF means reducing the visible area of each page, typically to remove unwanted margins, cut out a region of interest, or trim a scanned document to its content boundary. This guide covers the free online method and four programmatic approaches: pdf-lib (Node.js), PyMuPDF (Python), Ghostscript, and qpdf.

How PDF cropping works: CropBox vs MediaBox

A PDF page has several bounding boxes. The two you need to know when cropping are:

BoxPurposeDefault
MediaBoxFull physical page size (always present)Set at creation
CropBoxRegion shown by viewers and printersFalls back to MediaBox

Most cropping tools adjust only the CropBox. The content outside the CropBox stays in the file but is not displayed. This means a simple crop is reversible: reset the CropBox to the MediaBox and the full content reappears. To permanently discard the hidden area (and shrink the file), you must re-render the page through a PDF printer like Ghostscript.

How to crop a PDF online (free, no upload)

The PDF4.dev crop PDF tool runs entirely in your browser using pdf-lib. Files are never sent to a server.

  1. Open pdf4.dev/tools/crop-pdf and drop your PDF onto the upload area.
  2. A thumbnail of the first page appears. Enter margin values (in mm) for top, bottom, left, and right.
  3. Choose whether to apply the crop to all pages or a custom page range.
  4. Click Crop PDF and download the result.

The tool applies the crop by adjusting the CropBox on each selected page. For per-page cropping with different values, process the file in multiple passes.

Crop a PDF online, freeTry it free

How to crop a PDF with pdf-lib (Node.js)

pdf-lib is a pure-JavaScript library that runs in Node.js and the browser. It adjusts the CropBox directly.

npm install pdf-lib
import { PDFDocument } from "pdf-lib";
import { readFileSync, writeFileSync } from "fs";
 
async function cropPdf(
  inputPath: string,
  outputPath: string,
  margins: { top: number; bottom: number; left: number; right: number }
) {
  const bytes = readFileSync(inputPath);
  const doc = await PDFDocument.load(bytes);
 
  for (const page of doc.getPages()) {
    const { width, height } = page.getSize();
    // PDF coordinates: origin is bottom-left
    const x = margins.left;
    const y = margins.bottom;
    const w = width - margins.left - margins.right;
    const h = height - margins.top - margins.bottom;
    page.setCropBox(x, y, w, h);
  }
 
  const output = await doc.save();
  writeFileSync(outputPath, output);
  console.log(`Cropped PDF saved to ${outputPath}`);
}
 
// Crop 10pt from each side (1 point ≈ 0.353 mm)
cropPdf("input.pdf", "output.pdf", {
  top: 10,
  bottom: 10,
  left: 10,
  right: 10,
});

Convert mm to points

PDF dimensions use points (1 inch = 72 points). To convert millimetres:

const mmToPoints = (mm: number) => (mm / 25.4) * 72;
 
// Crop 5mm from each side
const margin = mmToPoints(5); // ≈ 14.17pt
page.setCropBox(margin, margin, width - margin * 2, height - margin * 2);

Crop to a specific page only

const pages = doc.getPages();
const pageIndex = 0; // first page
const page = pages[pageIndex];
const { width, height } = page.getSize();
page.setCropBox(20, 20, width - 40, height - 40);

How to crop a PDF with PyMuPDF (Python)

PyMuPDF (pymupdf) provides page.set_cropbox() which accepts a Rect in points.

pip install pymupdf
import pymupdf  # pip install pymupdf
 
def crop_pdf(input_path: str, output_path: str, margin_pt: float = 14.17):
    """Crop all pages by removing a uniform margin (in points)."""
    doc = pymupdf.open(input_path)
 
    for page in doc:
        rect = page.rect  # MediaBox as a Rect
        cropped = pymupdf.Rect(
            rect.x0 + margin_pt,
            rect.y0 + margin_pt,
            rect.x1 - margin_pt,
            rect.y1 - margin_pt,
        )
        page.set_cropbox(cropped)
 
    doc.save(output_path, garbage=4, deflate=True)
    print(f"Saved: {output_path}")
 
# Crop 5mm (≈ 14.17pt) from all sides
crop_pdf("input.pdf", "output.pdf", margin_pt=14.17)

Crop to content bounding box (auto-trim whitespace)

PyMuPDF can detect where the actual content sits and crop to that boundary automatically:

import pymupdf
 
doc = pymupdf.open("input.pdf")
 
for page in doc:
    # get_text("blocks") returns (x0, y0, x1, y1, text, block_no, block_type) tuples
    blocks = page.get_text("blocks")
    if not blocks:
        continue
    # Compute bounding box of all text blocks
    xs = [b[0] for b in blocks] + [b[2] for b in blocks]
    ys = [b[1] for b in blocks] + [b[3] for b in blocks]
    padding = 14  # add 5mm padding
    bbox = pymupdf.Rect(min(xs) - padding, min(ys) - padding,
                        max(xs) + padding, max(ys) + padding)
    page.set_cropbox(bbox)
 
doc.save("output.pdf", garbage=4, deflate=True)

Auto-trim works well for text-heavy documents. For scanned PDFs or image-only pages, use the image bounding box from page.get_image_info() instead.

How to crop a PDF with Ghostscript (command line)

Ghostscript re-renders the visible area into a new page, permanently removing content outside the crop region and reducing file size.

# Install on macOS
brew install ghostscript
 
# Install on Ubuntu/Debian
sudo apt install ghostscript

Set a new page size and translate the coordinate system

gs \
  -sDEVICE=pdfwrite \
  -dNOPAUSE \
  -dBATCH \
  -dFIXEDMEDIA \
  -dPDFFitPage \
  -g5954x8419 \
  -c "-14 -14 translate" \
  -f input.pdf \
  -sOutputFile=output.pdf

What each flag does:

FlagEffect
-dFIXEDMEDIALock the output page size instead of inheriting from input
-dPDFFitPageScale content to fit the new page size
-g<width>x<height>Output dimensions in pixels at 72dpi (so 1 unit = 1pt): 5954x8419 ≈ A4 minus 5mm on each side
-c "<x> <y> translate"Shift coordinate origin to skip the left/bottom margin

Calculate the output dimensions

For an A4 page (595 x 842 pt) cropped 5mm (≈ 14pt) on each side:

  • Width: 595 - 14 - 14 = 567 pt → -g5670x8140
  • Height: 842 - 14 - 14 = 814 pt
  • Translate: -c "-14 -14 translate" (shift origin past the left/bottom margin)
gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH \
   -dFIXEDMEDIA -dPDFFitPage \
   -g5670x8140 \
   -c "-14 -14 translate" \
   -f input.pdf \
   -sOutputFile=output_cropped.pdf

Ghostscript processes all pages with the same settings. For per-page crops, split the PDF first, crop each page, then merge with pdfunite or the merge PDF tool.

How to crop a PDF with qpdf (command line)

qpdf 11+ supports --crop which adjusts the CropBox without re-rendering, so it is fast and lossless.

# Install on macOS
brew install qpdf
 
# Install on Ubuntu/Debian
sudo apt install qpdf
# Syntax: --crop=left,top,right,bottom (in points from the page edges)
qpdf --crop=14,14,14,14 input.pdf output.pdf

This removes 14 points (≈ 5mm) from each side by setting the CropBox. The original content is preserved in the MediaBox. To apply to specific pages only:

# Crop pages 1-3 only
qpdf --crop=14,14,14,14:1-3 input.pdf output.pdf

Comparison: which method to use?

MethodRemoves hidden contentSpeedPer-page controlUse case
PDF4.dev toolNoInstantAll or rangeQuick one-off, no code
pdf-libNoFastFull (loop)Node.js automation, client-side
PyMuPDFNoFastFull (loop)Python scripts, data pipelines
GhostscriptYesSlowerOne crop for allPrint-ready, file size reduction
qpdfNoFastestPage rangesBatch scripts, lossless crop

Results marked "No" for hidden content removal mean the content outside the CropBox stays embedded in the file. Use Ghostscript or the compress PDF tool after cropping to strip it out.

Common use cases

Remove scanned borders. Flatbed scanners often capture a grey border outside the document area. Set a uniform margin of 8-15pt to trim it cleanly.

Crop a two-column PDF to one column. Set the right margin to 50% of the page width to show only the left column, then repeat with the left margin at 50% to extract the right column. Merge both outputs for a single-column reading layout.

Trim slide decks. PowerPoint-exported PDFs often include thick white borders. Crop 20-30pt from each side to make the content fill more screen space.

Prepare files for print. Professional printers request documents with 3mm bleed (content extending past the trim line). Use the crop tool to verify the visible area matches the intended trim size before sending to press.

Extract a region of a page. Combine cropping with page extraction: extract the target page with the extract pages tool, then crop it to the exact bounding box of the element you want.

Summary

  • Cropping a PDF adjusts the CropBox, not the MediaBox. Hidden content stays in the file unless you re-render with Ghostscript.
  • For quick crops with no code, use the PDF4.dev crop PDF tool — browser-only, instant, free.
  • For Node.js automation, pdf-lib with setCropBox is the simplest path.
  • For Python, PyMuPDF with set_cropbox handles single pages and whole documents equally well.
  • For permanent content removal and file size reduction, Ghostscript re-renders the visible area into a clean new page.
  • For fast lossless batch scripts, qpdf --crop is the most straightforward command-line option.

Free tools mentioned:

Crop PdfTry it freeResize PdfTry it freeCompress PdfTry it freeMerge PdfTry it freeRotate PdfTry it free

Start generating PDFs

Build PDF templates with a visual editor. Render them via API from any language in ~300ms.