mrkeyoor.com_
Sat 08 Aug 20:59 UTC
PyPIUtilsupdated 08 Aug 2026

pdf2image

pdf2image is a Python wrapper around Poppler's `pdfinfo`, `pdftoppm`, and `pdftocairo` command-line tools. It renders PDF pages from a path or bytes into Pillow Image objects, or writes images to disk and returns their paths. Callers can select page ranges, resolution, output size and format, grayscale or transparent output, passwords, crop boxes, thread count, timeouts, and either Poppler rendering backend. It does not parse or render PDFs itself.

Verdict

pdf2image is a convenient adapter when Poppler is already an accepted system dependency and the goal is simply pages as Pillow images. For self-contained deployment, deeper PDF work, or long-term active maintenance, evaluate PyMuPDF or pypdfium2 first.

API stability4/5The two conversion functions retain a long keyword-driven API, and version 1.17.0 still supports the established path, bytes, page range, DPI, format, output directory, and backend controls. Stability is helped by slow releases, but actual behavior also depends on the installed Poppler version, which can silently disable older unsupported JPEG or annotation options.
Docs4/5The README plainly explains the non-Python Poppler installation for Windows, macOS, Linux, and Conda, lists both function shapes, names the memory failure mode, and gives performance advice about SSD output, threads, JPEG, and PNG. The hosted docs expand installation and reference material, though the README signature is stale in places compared with source names such as hide_annotations.
Maintenance2/5The latest PyPI release, 1.17.0, was uploaded on 2024-01-07 and GitHub's last push is 2024-07-23, more than two years before this snapshot. The repository is not archived and GitHub shows recent reader activity, but 83 open issues and pull requests plus the release gap create meaningful risk around new Poppler, Pillow, Python, and platform behavior.
Ecosystem4/5The package connects the widely deployed Poppler renderer to Pillow, and weekly downloads are measured in millions. Its path and byte APIs fit web uploads, OCR pipelines, and thumbnail jobs. The effective ecosystem includes OS package managers and native shared libraries, however, so portability is weaker than a Python wheel that bundles its rendering engine.

Use it if

  • Your deployment already has Poppler and you want a small Python API that returns ordinary Pillow images
  • You need thumbnails, OCR inputs, previews, or page images rather than PDF text extraction or document editing
  • You want to limit conversion by page range, DPI, pixel size, format, timeout, and output directory
  • You need to avoid loading a large document into Python memory by returning generated file paths
Skip it if

Setup reality

`pip install pdf2image` installs the Python wrapper and Pillow, but the first call still fails unless Poppler's `pdfinfo` plus `pdftoppm` or `pdftocairo` are executable. On macOS the README uses `brew install poppler`; on Debian-family Linux images install the package that provides `poppler-utils`; on Windows download or build Poppler, add its `bin` directory to PATH, or pass `poppler_path` on every call. That external binary version changes supported flags and rendering behavior. The wrapper quietly disables `jpegopt` on Poppler 0.57 and older and annotation hiding on 0.83 and older. By default conversion uses 200 DPI, PPM, one worker, and returns a Pillow image for every page, a combination that can consume a great deal of RAM. For untrusted or large documents set a page range, pixel `size`, a finite `timeout`, and an `output_folder`; add `paths_only=True` so images are not reopened into memory. Keep temporary output alive until all returned paths are consumed. The README recommends no more than four threads because I/O becomes the bottleneck, and PNG compression is specifically described as slow. `use_pdftocairo=True` may be faster and is required by some output modes, but it cannot hide annotations and changes default PPM requests to PNG internally. `strict=False` ignores Poppler syntax warnings; use strict mode only if a warning should reject the document. Passwords are passed to a child process, so treat host process visibility and logs as part of the threat model. Conversion is rasterization, not sanitization: set resource limits around hostile PDFs and never assume success means the source was safe or semantically intact.

Patterns

Render every page from a fileconvert-pdf-path

from pdf2image import convert_from_path

pages = convert_from_path('report.pdf', dpi=150)
for number, image in enumerate(pages, start=1):
    image.save(f'page-{number}.png')

The result keeps every Pillow image in memory. Use an output directory and paths_only for large documents.

Render an uploaded PDF byte stringconvert-pdf-bytes

from pdf2image import convert_from_bytes

pages = convert_from_bytes(
    upload_bytes,
    dpi=144,
    first_page=1,
    last_page=3,
    timeout=30,
)

The PDF bytes and rendered images coexist in memory. Enforce upload and page limits before conversion.

Return disk paths instead of Pillow imagesavoid-large-pdf-memory

from pathlib import Path
from pdf2image import convert_from_path

output_dir = Path('/var/tmp/rendered-pages')
output_dir.mkdir(parents=True, exist_ok=True)
paths = convert_from_path(
    'large.pdf',
    output_folder=output_dir,
    paths_only=True,
    fmt='jpeg',
    dpi=120,
)

paths_only requires output_folder. Clean the files after use and place the directory on storage with enough space.

Bound memory with a temporary output directoryuse-temporary-output

from tempfile import TemporaryDirectory
from PIL import Image
from pdf2image import convert_from_path

with TemporaryDirectory() as directory:
    paths = convert_from_path(
        'report.pdf', output_folder=directory, paths_only=True
    )
    for path in paths:
        with Image.open(path) as image:
            consume(image.copy())

Returned paths become invalid when the context exits. Finish reading or copy the required files before TemporaryDirectory cleanup.

Render only selected pagesrender-page-range

pages = convert_from_path(
    'appendix.pdf',
    first_page=10,
    last_page=15,
    dpi=200,
)

Page numbers are one-based and inclusive. If first_page ends up greater than last_page, the implementation returns an empty list.

Fit the first page into a thumbnail boxcreate-thumbnail

thumbnail = convert_from_path(
    'brochure.pdf',
    first_page=1,
    last_page=1,
    size=400,
    fmt='jpeg',
    jpegopt={'quality': 82, 'optimize': True},
)[0]

An integer size fits within a square while preserving aspect ratio. A two-number tuple forces that exact shape and may distort the page.

Render a page with transparencyrender-transparent-png

pages = convert_from_path(
    'overlay.pdf',
    fmt='png',
    transparent=True,
    use_pdftocairo=True,
)

Transparency is supported only for PNG and TIFF-style outputs and selects the pdftocairo path. It can be slower than JPEG.

Open a password-protected documentrender-password-pdf

pages = convert_from_path(
    'protected.pdf',
    userpw=user_password,
    ownerpw=owner_password,
    first_page=1,
    last_page=1,
)

Passwords are passed to Poppler child processes. Do not log the generated command or retain credentials longer than necessary.

Stop a slow or hostile conversionenforce-conversion-timeout

from pdf2image import convert_from_path
from pdf2image.exceptions import PDFPopplerTimeoutError

try:
    pages = convert_from_path('input.pdf', timeout=20)
except PDFPopplerTimeoutError:
    quarantine('input.pdf')

The timeout kills Poppler and raises PDFPopplerTimeoutError. Pair it with process memory and file-size limits for untrusted input.

Treat Poppler syntax warnings as failuresreject-pdf-syntax-errors

from pdf2image import convert_from_path
from pdf2image.exceptions import PDFSyntaxError

try:
    pages = convert_from_path('input.pdf', strict=True)
except PDFSyntaxError as error:
    print(f'PDF rejected: {error}')

strict defaults to False. Enabling it can reject PDFs that Poppler might otherwise render despite syntax warnings.

Read Poppler's page information before renderinginspect-pdf-metadata

from pdf2image import pdfinfo_from_path

info = pdfinfo_from_path('report.pdf', timeout=10)
page_count = info['Pages']
if page_count > 200:
    raise ValueError('Document is too long')

This still invokes the external pdfinfo executable. Metadata inspection should also have a timeout for untrusted files.

Point Windows at a Poppler installationset-windows-poppler-path

from pdf2image import convert_from_path

pages = convert_from_path(
    r'C:\documents\report.pdf',
    poppler_path=r'C:\tools\poppler\Library\bin',
    first_page=1,
    last_page=1,
)

poppler_path must contain the Poppler executables, including pdfinfo and a renderer. pip does not install them.

Alternatives

PackageRegistryPick it when
pymupdfPyPIYou want fast PDF rendering plus text extraction, annotations, editing, and a broader document API
pypdfium2PyPIYou prefer PDFium-backed rendering with platform wheels instead of shelling out to Poppler tools
WandPyPIYour stack already uses ImageMagick and needs one image API across PDF and many raster formats
pillowPyPIYou only manipulate images that are already rasterized and do not need a PDF renderer