ScreenshotNeo

BlogHTML to image & PDF

How to Capture Every Page of a PDF as Screenshots

Render every PDF page into a separate image with Acrobat, PDF.js, Python, or an API—plus resolution, memory, troubleshooting, and automation guidance.

By the ScreenshotNeo team1 October 20268 min read

Short answer: render each PDF page at the scale you need, then save one image file per page. For a one-off conversion, use Acrobat’s export-to-image workflow. For repeatable jobs, render pages programmatically with PDF.js or another PDF renderer, processing pages sequentially so memory stays bounded. This captures the complete page, including text and layout; it is different from extracting only the original image objects embedded in the PDF.

Choose the right method

Need Best fit Why
One PDF, no code Acrobat page export Exports all pages to an image format from the desktop app.
Browser-based rendering PDF.js Renders each page to a canvas and lets you control dimensions with a viewport scale.
Repeatable local batch Python or Node.js renderer Automates naming, scaling, retries, and sequential processing.
Managed conversion service Adobe PDF Services Its export example produces one JPEG image per PDF page.

Method 1: Export every page in Acrobat

  1. Open the PDF in Acrobat.
  2. Open the export or convert workflow and choose an image format such as JPEG.
  3. Choose the output folder and quality or resolution settings offered by your Acrobat version.
  4. Make sure Export All Images is not selected when you want screenshots of whole pages. That option extracts image objects contained in the PDF instead.
  5. Run the export and verify that the output count matches the PDF page count.

Adobe’s support documentation describes exporting PDF pages to images and distinguishes page export from extracting embedded images. Menu names can differ between Acrobat releases and operating systems, so use the labels shown in your installed version: Adobe’s Acrobat export guidance.

Method 2: Render all pages with PDF.js

PDF.js loads a document, obtains a page, creates a viewport, sizes a canvas, and renders the page into that canvas. The viewport scale controls the output dimensions. To target a width, first read the unscaled viewport width and divide your desired pixel width by it. Repeat the process for every page and wait for each render to finish before reusing the canvas.

Browser example

<input id="pdf" type="file" accept="application/pdf" />
<div id="status"></div>
<script type="module">
  import * as pdfjsLib from "pdfjs-dist";

  // Configure the worker using the PDF.js build installed by your app.
  pdfjsLib.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.mjs";

  const input = document.querySelector("#pdf");
  const status = document.querySelector("#status");
  const targetWidth = 1600;

  input.addEventListener("change", async () => {
    const file = input.files[0];
    if (!file) return;

    const bytes = new Uint8Array(await file.arrayBuffer());
    const pdf = await pdfjsLib.getDocument({ data: bytes }).promise;
    status.textContent = `Rendering ${pdf.numPages} pages...`;

    for (let pageNumber = 1; pageNumber <= pdf.numPages; pageNumber++) {
      const page = await pdf.getPage(pageNumber);
      const baseViewport = page.getViewport({ scale: 1 });
      const scale = targetWidth / baseViewport.width;
      const viewport = page.getViewport({ scale });
      const canvas = document.createElement("canvas");
      const context = canvas.getContext("2d", { alpha: false });
      canvas.width = Math.ceil(viewport.width);
      canvas.height = Math.ceil(viewport.height);

      await page.render({ canvasContext: context, viewport }).promise;

      const blob = await new Promise(resolve =>
        canvas.toBlob(resolve, "image/png")
      );
      const link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = `page-${String(pageNumber).padStart(4, "0")}.png`;
      link.click();
      URL.revokeObjectURL(link.href);

      // Release the canvas before rendering the next high-resolution page.
      canvas.width = 1;
      canvas.height = 1;
      status.textContent = `Rendered ${pageNumber} of ${pdf.numPages}`;
    }

    status.textContent = "Finished";
  });
</script>

Install and bundle PDF.js with your application, then place the matching worker file at the path configured in workerSrc. The official examples show the page, viewport, canvas, and render steps: PDF.js examples.

Why the scale matters

  • scale: 1 uses the PDF page’s base viewport dimensions.
  • A larger scale creates a larger image and preserves more detail when zoomed.
  • A smaller scale reduces file size and memory use.
  • Set the scale from a target width when output consistency matters across differently sized pages.

Method 3: Python batch rendering

The following script uses PyMuPDF to render pages one at a time. Install it with pip install pymupdf. The matrix controls resolution; a 2× matrix renders approximately twice the page dimensions in each direction.

import sys
from pathlib import Path
import fitz  # PyMuPDF

pdf_path = Path(sys.argv[1])
out_dir = Path(sys.argv[2] if len(sys.argv) > 2 else "pdf-pages")
scale = float(sys.argv[3] if len(sys.argv) > 3 else "2")
out_dir.mkdir(parents=True, exist_ok=True)

with fitz.open(pdf_path) as document:
    for index, page in enumerate(document, start=1):
        pixmap = page.get_pixmap(matrix=fitz.Matrix(scale, scale), alpha=False)
        output = out_dir / f"page-{index:04d}.png"
        pixmap.save(output)
        print(output)
python render_pdf.py input.pdf output-pages 2

For very large documents, keep the loop sequential and avoid storing all pixmaps. If you need JPEGs, use the renderer’s JPEG output or convert each completed PNG immediately.

Method 4: Node.js batch rendering

In Node.js, PDF.js supplies page rendering while a canvas implementation supplies the drawing surface. The exact worker and canvas setup depends on your PDF.js version and bundler, so keep those dependencies pinned in your project.

import fs from "node:fs/promises";
import path from "node:path";
import { createCanvas } from "canvas";
import * as pdfjsLib from "pdfjs-dist/legacy/build/pdf.mjs";

const input = process.argv[2];
const outputDir = process.argv[3] || "pdf-pages";
const targetWidth = Number(process.argv[4] || 1600);
await fs.mkdir(outputDir, { recursive: true });

const data = new Uint8Array(await fs.readFile(input));
const document = await pdfjsLib.getDocument({ data }).promise;

for (let pageNumber = 1; pageNumber <= document.numPages; pageNumber++) {
  const page = await document.getPage(pageNumber);
  const base = page.getViewport({ scale: 1 });
  const viewport = page.getViewport({ scale: targetWidth / base.width });
  const canvas = createCanvas(Math.ceil(viewport.width), Math.ceil(viewport.height));
  const context = canvas.getContext("2d");
  await page.render({ canvasContext: context, viewport }).promise;
  const output = path.join(outputDir, `page-${String(pageNumber).padStart(4, "0")}.png`);
  await fs.writeFile(output, canvas.toBuffer("image/png"));
  console.log(output);
}
npm install pdfjs-dist canvas
node render-pdf.mjs input.pdf output-pages 1600

Automating conversion with Adobe PDF Services

Adobe PDF Services documents an export operation that returns JPEG page images. Its example describes a 15-page PDF producing 15 files with page indexes in the filenames. Use the current service documentation for authentication, SDK setup, quotas, and account conditions: Adobe PDF Services export documentation.

Output format, dimensions, and naming

  • PNG: lossless and useful for text-heavy pages, diagrams, and archival comparison.
  • JPEG: smaller for photographic pages; quality settings affect artifacts around text.
  • WebP: often compact for web delivery when your downstream tools support it.
  • Dimensions: choose a target width or a scale rather than relying on a screen screenshot. The PDF.js viewport determines the rendered pixel size.
  • Naming: use zero-padded numbers such as page-0001.png so lexical file ordering matches page order.
  • Color and transparency: set an explicit background when the PDF has transparency and your output format does not preserve it as expected.

Memory and performance

High-resolution pages can consume substantial memory. PDF.js explains that a canvas uses width × height × four bytes before device-pixel scaling; its FAQ gives an illustrative letter-page calculation of about 3.5 MB at 96 DPI. Actual use varies with page size, scale, pixel ratio, browser, and implementation. The PDF.js demo renders only visible pages to reduce memory: PDF.js FAQ.

  • Render one page, write it, then release the canvas or pixmap.
  • Use a queue with limited concurrency if throughput matters; do not render every page simultaneously by default.
  • Set a maximum pixel width or area for untrusted PDFs.
  • Measure output size and render time with your own documents; the supplied sources do not establish universal speed comparisons.
  • For a viewer, render only visible pages and render more as the reader scrolls.

Page screenshots versus embedded image extraction

A rendered page image includes the complete page composition: text, vector drawings, backgrounds, and placed images. Embedded-image extraction returns only image objects that already exist inside the PDF. Choose page rendering when you need a screenshot-like record of each page; choose extraction when you need the original placed image assets.

Common errors and fixes

Symptom Likely cause Fix
Only one page is exported The workflow is set to export the current page. Select all pages or loop from 1 through the document page count.
Output contains photos but no text Embedded-image extraction was selected. Use page export or a page renderer.
Blank canvas Rendering began before the page promise completed, or the worker is misconfigured. Await document loading, page loading, and page.render(...).promise; verify the PDF.js worker path.
Browser tab runs out of memory All high-resolution canvases remain allocated. Process sequentially, clear completed canvases, lower scale, or render only visible pages.
Images are too small The viewport scale is too low. Increase scale or compute it from a larger target width.
Images are huge The scale or target width is excessive. Set a maximum width and choose JPEG or WebP where appropriate.
Pages appear in the wrong order Filenames are not zero-padded. Use names such as page-0001 and sort numerically.
Some pages fail The PDF is damaged, encrypted, or uses unsupported content. Open it in a PDF viewer first, supply a password when supported, or re-save a repaired copy before rendering.

Or skip the browser setup

For a PDF or document exposed through a URL, ScreenshotNeo provides a single screenshot request. It can return PNG, JPEG, WebP, or PDF output; use a local PDF renderer when you specifically need every page of an existing PDF as separate files.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation for options. Cookie banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. Responses identify the page verdict and billing status with X-Page-Verdict and X-Billed headers. ScreenshotNeo also provides an MCP server so AI agents can take screenshots. The Free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

Checklist before you run a large batch

  • Confirm whether you need rendered pages or embedded image objects.
  • Choose PNG, JPEG, or WebP based on downstream use.
  • Set a target width or scale and test representative pages.
  • Use sequential rendering or bounded concurrency.
  • Zero-pad page numbers and verify the output count.
  • Open several first, middle, and last pages to check clipping, fonts, transparency, and color.
  • Keep the source PDF and record the renderer version and scale used.

FAQ

Does one PDF page always produce one image?

Yes, when you use page rendering or page export. A 15-page document therefore produces 15 page images in the Adobe PDF Services example.

Can I capture only selected pages?

Yes. Start and end your render loop at the requested page numbers, or maintain a list of page numbers to process.

Is a screenshot the same as extracting images?

No. A screenshot-style page render includes the entire composed page. Extraction returns image objects embedded in the PDF.

What resolution should I choose?

Choose the pixel dimensions required by the destination. Use a larger viewport scale for zooming or print-like detail, and a smaller one for thumbnails or previews.

Why does rendering use more memory than the saved PNG?

The renderer holds an uncompressed pixel buffer while drawing. The compressed file size on disk is not a reliable estimate of peak render memory.