This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /blog/pdfjs-generating-pdf-thumbnails-pdf2pic.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Generate PDF thumbnail previews with pdf2pic in Node.js

Table of contents

    Generate thumbnail images from PDF pages using pdf2pic in Node.js. This tutorial covers single-page previews, batch thumbnail generation, cloud storage integration, and a browser-side alternative using PDF.js canvas rendering.
    Generate PDF thumbnail previews with pdf2pic in Node.js
    TL;DR
    • fromBuffer(pdfBuffer, options) from pdf2pic converts any page of a PDF to an image; pick responseType: "buffer" for cloud uploads or "base64" for inline embedding.
    • For browsers, render to a canvas at a small scale (around 0.3) and canvas.toDataURL("image/jpeg", 0.8).
    • pdf2pic requires GraphicsMagick or ImageMagick on the host — package it into your Docker image or container.

    Prerequisites

    This guide is server-side first, with a browser-side variant at the end. You’ll need Node.js, plus a system-level image processing tool (pdf2pic shells out to either GraphicsMagick or ImageMagick).

    You’ll also need:

    • Node.js 14 or later
    • pdf2pic from npm
    • GraphicsMagick (brew install graphicsmagick/apt-get install graphicsmagick) — or ImageMagick as an alternative
    • Ghostscript (brew install ghostscript/apt-get install ghostscript) — required for PDF parsing alongside GraphicsMagick
    • For the browser variant — a loaded PDFDocumentProxy from pdfjs-dist

    When building a document management system, you often need thumbnail images of PDF pages for preview galleries, search results, or file cards. pdf2pic converts PDF pages to images in Node.js.

    Install

    Install pdf2pic from npm:

    Terminal window
    npm install pdf2pic

    System dependencies: pdf2pic shells out to GraphicsMagick (or ImageMagick) and Ghostscript. You need both — Ghostscript handles the PDF parsing, while GraphicsMagick handles the image conversion.

    Terminal window
    # macOS
    brew install graphicsmagick ghostscript
    # Ubuntu/Debian
    sudo apt-get install graphicsmagick ghostscript

    Basic usage: First page preview

    fromBuffer takes a PDF buffer and a set of conversion options. It then returns a function for converting individual pages:

    import { fromBuffer } from "pdf2pic";
    async function generatePreview(pdfBuffer) {
    const options = {
    preserveAspectRatio: true,
    height: 600,
    quality: 80,
    format: "png",
    };
    const convert = fromBuffer(pdfBuffer, options);
    // Convert page 1, get result as a Buffer.
    const output = await convert(1, { responseType: "buffer" });
    return output.buffer; // PNG image as Buffer.
    }

    Options

    OptionTypeDescription
    widthnumberOutput width in pixels
    heightnumberOutput height in pixels
    preserveAspectRatioBooleanMaintain original aspect ratio
    qualitynumberImage quality (1–100)
    formatstringOutput format: "png", "jpeg", "gif"
    densitynumberDPI for rendering (default: 72)

    Response types

    The responseType option controls what shape convert() returns the result in:

    // Get as Buffer (for storage/upload).
    const output = await convert(1, { responseType: "buffer" });
    output.buffer; // Buffer
    // Get as base64 string (for embedding in HTML).
    const output = await convert(1, { responseType: "base64" });
    output.base64; // string
    // Save to file.
    const convert = fromBuffer(pdfBuffer, {
    ...options,
    savePath: "./thumbnails",
    saveFilename: "preview",
    });
    const output = await convert(1);
    output.path; // "./thumbnails/preview.1.png"

    Multiple pages

    Looping over convert() with each page number generates a thumbnail for every page in the document:

    async function generateThumbnails(pdfBuffer, pageCount) {
    const convert = fromBuffer(pdfBuffer, {
    preserveAspectRatio: true,
    height: 200,
    quality: 60,
    format: "jpeg",
    });
    const thumbnails = [];
    for (let page = 1; page <= pageCount; page++) {
    const output = await convert(page, { responseType: "buffer" });
    thumbnails.push({
    page,
    image: output.buffer,
    });
    }
    return thumbnails;
    }

    For large documents, pdf2pic also exposes a .bulk() method that takes an array of page numbers (or -1 for all pages) and returns the same result objects in a single call:

    const convert = fromBuffer(pdfBuffer, options);
    const results = await convert.bulk(-1, { responseType: "buffer" });

    Integration: Upload preview to cloud storage

    The generated buffer can be uploaded directly to a storage bucket, without writing it to disk first:

    async function processNewPdf(pdfBuffer, fileId) {
    // Generate preview.
    const preview = await generatePreview(pdfBuffer);
    // Upload to cloud storage (e.g. Google Cloud Storage).
    await bucket.file(`previews/${fileId}.png`).save(preview, {
    contentType: "image/png",
    });
    }

    Alternative: Browser-side thumbnails with PDF.js

    If you need thumbnails in the browser (not server-side), use PDF.js directly:

    async function renderPageToCanvas(pdfDocument, pageNumber, scale = 0.3) {
    const page = await pdfDocument.getPage(pageNumber);
    const viewport = page.getViewport({ scale });
    const canvas = document.createElement("canvas");
    canvas.width = viewport.width;
    canvas.height = viewport.height;
    await page.render({
    canvasContext: canvas.getContext("2d"),
    viewport,
    }).promise;
    return canvas.toDataURL("image/jpeg", 0.8);
    }

    Key points

    • pdf2pic is the simplest Node.js solution for PDF-to-image conversion.
    • pdf2pic requires GraphicsMagick or ImageMagick as a system dependency.
    • fromBuffer is the most common entry point for server-side processing.
    • Use responseType: "buffer" for cloud storage uploads.
    • For browser-side thumbnails, use PDF.js’s page.render() with a small scale factor.
    • Keep quality at 60–80 for thumbnails — no need for full quality on small images.

    How Nutrient Web SDK handles thumbnails

    Nutrient Web SDK ships a built-in thumbnail sidebar that’s enabled with a single state change — no rendering, sizing, or DOM management required on your end:

    instance.setViewState((v) =>
    v.set("sidebarMode", NutrientViewer.SidebarMode.THUMBNAILS),
    );

    For server-side thumbnail generation, Nutrient Document Engine exposes a PDF-to-image REST API that produces page images without GraphicsMagick or ImageMagick on the host.

    Learn more about Nutrient Web SDK | Thumbnail sidebar guide | PDF-to-image conversion | Migration guide | Contact Sales

    FAQ

    Why does pdf2pic need GraphicsMagick or ImageMagick installed?

    pdf2pic is a thin Node.js wrapper that shells out to a system image-processing binary — it doesn’t rasterize PDFs itself. GraphicsMagick is usually faster and lighter; ImageMagick is more widely available. If you can’t install either (serverless functions, sandboxed environments), use the browser-side PDF.js variant, or call a hosted PDF-to-image API instead.

    What density should I set for thumbnails?

    For small thumbnails (200–600 px tall), a density of 100–150 is plenty. Higher values produce sharper images but take longer to render and consume more memory. For print-quality output, 300 is the conventional target — but you almost never need that for a sidebar preview.

    JPEG, PNG, or WebP for thumbnails?

    JPEG at quality 60–80 is the sweet spot for photos and dense pages — smallest file sizes and acceptable visual fidelity. PNG preserves crisp edges on text-heavy or line-art pages but balloons file sizes. pdf2pic doesn’t natively support WebP; you’d need to convert with sharp after rendering if size matters.

    Can I generate all page thumbnails in parallel?

    Technically yes (Promise.all over your convert(page) calls), but GraphicsMagick is single-process, and you’ll mostly be CPU-bound or I/O-bound on temp file writes. For documents with more than a handful of pages, a serial loop is just as fast and consumes less memory. Save parallelism for batching across multiple documents.

    How do I generate thumbnails in serverless/Lambda environments?

    GraphicsMagick isn’t available in standard Lambda runtimes. Your options are: (1) build a Lambda layer with the GraphicsMagick binary, (2) use container-based Lambda with your own image, (3) skip pdf2pic entirely and call a hosted PDF-to-image API. For low-volume cases, browser-side PDF.js rendering is often simpler.

    The browser thumbnail looks blurry on Retina screens — why?

    At scale: 0.3, the canvas’s intrinsic resolution matches its CSS size — but on a 2x Retina display, the browser stretches each canvas pixel across two physical pixels. To get crisp output, multiply the canvas’s intrinsic width/height by window.devicePixelRatio while keeping the CSS dimensions the same. See PDF.js coordinate systems for the full HiDPI pattern.

    Austin Nguyen

    Austin Nguyen

    AI Engineer

    When Austin isn’t pulling all-nighters to build new features, he enjoys watching science videos on YouTube and cooking.

    Explore related topics

    Try for free Ready to get started?