Back to Blog
Python

Convert PDF Pages to Images with PyMuPDF

python pymupdf convert pdf pages to images: Convert PDF pages to images with PyMuPDF: render with get_pixmap, control DPI and zoom, choose PNG or JPEG, and handle larg...

PyMuPDFPDF processingfitzimage conversiondocument rendering
A PDF page transforming into a PNG image file, illustrating PyMuPDF page-to-image conversion.

python pymupdf convert pdf pages to images requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

To convert PDF pages to images with Python and PyMuPDF, the core pattern is short: open the document, load a page, render it to a pixmap, and save that pixmap as an image file. PyMuPDF is imported as fitz, and the rendering step gives you direct control over resolution, output format, and which part of the page gets captured. This article covers the minimal conversion, then the details that matter when you apply it to real documents: DPI and zoom, format and colorspace, memory use, and error handling.

The Core Conversion Pattern

import fitz with fitz.open("document.pdf") as doc: page = doc.load_page(0) pix = page.get_pixmap() pix.save("page-0.png")

fitz.open returns a Document. load_page(0) returns the first Page. get_pixmap() renders the page into an in-memory Pixmap, and pix.save() writes it to disk, inferring the image format from the file extension. Using the document as a context manager closes it and releases the underlying file handle when the block exits.

The default render is at 72 dpi, meaning one PDF point becomes one pixel. A letter-size page therefore becomes a 612×792 image, which is usually too small for printing or for display at high zoom. The next section shows how to change that.

Controlling Resolution with Zoom and DPI

PDF coordinates are measured in points, where 72 points equal one inch. Rendering at the default scale maps each point to one pixel. To produce a higher-resolution image, you scale the page before rendering.

zoom = 2.0 matrix = fitz.Matrix(zoom, zoom) pix = page.get_pixmap(matrix=matrix)

A zoom of 2.0 doubles the pixel dimensions: the letter-size page above becomes 1224×1584. The matrix parameter is the fundamental control, and it also allows non-uniform scaling when the x and y factors differ.

PyMuPDF's get_pixmap also accepts a dpi parameter as a convenience. It is equivalent to building a zoom matrix where the zoom factor is dpi / 72.

pix = page.get_pixmap(dpi=150)
Target DPIZoom factorEquivalent matrix
721.0fitz.Matrix(1, 1)
1502.08fitz.Matrix(2.08, 2.08)
2002.78fitz.Matrix(2.78, 2.78)
3004.17fitz.Matrix(4.17, 4.17)

Use dpi when you think in terms of a print-quality target, such as 150 or 300 dpi. Use matrix when you need an exact scale factor or non-uniform scaling, such as fitting a page into a fixed pixel width.

Choosing Output Format and Colorspace

The output format is determined by the extension you pass to pix.save(). PNG and JPEG are the common choices, and the right one depends on the content.

pix = page.get_pixmap(dpi=200) pix.save("page.png") # lossless, supports alpha pix.save("page.jpg") # smaller files, no alpha

PNG is lossless and is the safer default for text, diagrams, and anything with sharp edges. JPEG produces smaller files for photographic content but introduces compression artifacts and does not support transparency. If a page contains a transparent background and you want to preserve it, render with alpha=True; the default pixmap has no alpha channel.

For documents where color is irrelevant, rendering in grayscale reduces the output size.

pix = page.get_pixmap(dpi=200, colorspace=fitz.csGRAY) pix.save("page-gray.png")

If you need the image in memory rather than on disk, pix.tobytes("png") returns the encoded bytes, which is useful when you are uploading the result or embedding it in another document.

Converting Every Page in a Document

Real documents usually need every page converted, not just the first one. Iterate over the page count and save each page with a predictable name.

import fitz with fitz.open("document.pdf") as doc: for i in range(doc.page_count): page = doc.load_page(i) pix = page.get_pixmap(dpi=150) pix.save(f"page-{i:03d}.png")

doc.page_count gives the number of pages, and doc.load_page(i) returns the page at index i. The doc[i] shorthand is equivalent to load_page(i). Zero-padding the index keeps the filenames in sorted order once you have more than nine pages.

Each pixmap is written to disk and then goes out of scope, so this loop keeps only one rendered page in memory at a time.

Memory Behavior at High Resolution

A pixmap holds raw pixel data: width × height × bytes-per-pixel. An RGB pixmap uses three bytes per pixel, and four with alpha. At 300 dpi, an A4 page renders to roughly 2481 × 3507 pixels, which is about 25 MB in memory for a single page.

That has a direct consequence for batch conversion: collecting every rendered page in a list will exhaust memory on any document longer than a few pages.

# This holds every page in memory at once. pixmaps = [doc.load_page(i).get_pixmap(dpi=300) for i in range(doc.page_count)]

Render, save, and discard one page at a time instead. If you only need previews, render at a lower dpi such as 72 or 96; the memory cost scales with the square of the zoom factor. When you need only part of a page, use clip rather than rendering the full page and cropping afterward.

Handling Encrypted and Invalid PDFs

Not every file you open is a clean, readable PDF. Password-protected documents and corrupt files fail in predictable ways, and the conversion code should handle them explicitly.

import fitz try: with fitz.open("protected.pdf") as doc: if doc.needs_pass: if not doc.authenticate("secret"): raise RuntimeError("wrong password") for i in range(doc.page_count): pix = doc.load_page(i).get_pixmap(dpi=150) pix.save(f"page-{i:03d}.png") except FileNotFoundError: print("file not found") except Exception as exc: print(f"conversion failed: {exc}")

doc.needs_pass reports whether the document is encrypted. doc.authenticate(password) returns 0 when the password is incorrect and a positive value when authentication succeeds. A missing file raises FileNotFoundError; a file that is not a valid PDF raises an exception from the underlying MuPDF layer. A page index outside range(doc.page_count) raises IndexError, so validate the index when it comes from external input.

Rendering a Specific Region of a Page

When you only need a figure, a table, or a signature block, rendering the whole page wastes memory and disk space. The clip parameter limits rendering to a rectangle, with coordinates in PDF points.

import fitz with fitz.open("document.pdf") as doc: page = doc.load_page(0) clip = fitz.Rect(72, 72, 360, 360) pix = page.get_pixmap(clip=clip, dpi=200) pix.save("region.png")

The resulting image has the dimensions of the clipped region scaled by the zoom factor, not the full page. This is useful for extracting a specific section without cropping after the fact, and it keeps the pixmap small when the region of interest is a small fraction of the page.

python pymupdf convert pdf pages to images: Practical Usage | RYUSLOG DEV