Convert PDF Pages to Images with PHP
Convert PDF pages to separate images with PHP Imagick. Set resolution and page limits, check Ghostscript and ImageMagick policy, and handle failures safely.
Use PHP’s Imagick extension to read a PDF and write its pages as image files. Imagick relies on ImageMagick, and ImageMagick needs Ghostscript to read PDF files. Your PHP runtime must have Imagick enabled, Ghostscript available through ImageMagick’s PDF delegate, and a security policy that permits the operation.
The example below writes each page as a JPEG, sets the raster density before reading, and uses generated temporary paths. Confirm the output filenames on your installed ImageMagick version before relying on them in production.
1. Check the runtime dependencies
Check from the same environment that will run the conversion: PHP-FPM, a queue worker, or another application process may use a different PHP installation or configuration from the command line.
- Confirm the Imagick extension is loaded in the application’s PHP SAPI.
- Confirm ImageMagick can read PDFs through its Ghostscript delegate.
- Check whether the active ImageMagick policy allows PDF reading and sets appropriate resource limits.
- Ensure the output directory is writable and has enough temporary and final storage.
- Set limits for upload size, page count, page dimensions, and conversion time.
<?php
if (!extension_loaded('imagick')) {
throw new RuntimeException('The Imagick PHP extension is not loaded.');
}
$imagick = new Imagick();
print_r($imagick->queryFormats('PDF'));
$imagick->clear();
$imagick->destroy();
A listed PDF format is a useful check, but it does not by itself prove that the delegate works or that policy permits a particular input. Test an innocuous PDF in the application runtime. ImageMagick documents that PDF reading requires Ghostscript and that policy can restrict coders, delegates, and resources: ImageMagick formats and ImageMagick security policy.
2. Convert every page to a separate image
Install and configure Imagick, ImageMagick, and Ghostscript for your deployment first. This runnable PHP script accepts an input PDF and output directory, sets resolution before reading, and writes sequential JPEG files. Run it only on PDFs your application is authorized to process.
<?php
declare(strict_types=1);
if ($argc < 3) {
fwrite(STDERR, "Usage: php convert.php input.pdf output-directory [dpi]\n");
exit(2);
}
$input = $argv[1];
$outputDir = rtrim($argv[2], DIRECTORY_SEPARATOR);
$dpi = isset($argv[3]) ? filter_var($argv[3], FILTER_VALIDATE_INT) : 150;
if (!is_file($input) || !is_readable($input)) {
throw new RuntimeException('Input PDF does not exist or is not readable.');
}
if ($dpi === false || $dpi < 36 || $dpi > 600) {
throw new InvalidArgumentException('DPI must be an integer from 36 to 600.');
}
if (!is_dir($outputDir) && !mkdir($outputDir, 0700, true) && !is_dir($outputDir)) {
throw new RuntimeException('Could not create output directory.');
}
if (!is_writable($outputDir)) {
throw new RuntimeException('Output directory is not writable.');
}
$pages = new Imagick();
try {
// Set density before reading so PDF vector content is rasterized at this resolution.
$pages->setResolution($dpi, $dpi);
$pages->readImage($input);
$count = $pages->getNumberImages();
if ($count < 1) {
throw new RuntimeException('The PDF contained no rasterizable pages.');
}
// Set an application-specific upper bound before doing expensive writes.
$maxPages = 100;
if ($count > $maxPages) {
throw new RuntimeException("PDF has {$count} pages; limit is {$maxPages}.");
}
$index = 1;
foreach ($pages as $page) {
$page->setIteratorIndex($index - 1);
$page->setImageFormat('jpeg');
$page->setImageCompression(Imagick::COMPRESSION_JPEG);
$page->setImageCompressionQuality(85);
$path = sprintf('%s/page-%04d.jpg', $outputDir, $index);
if (!$page->writeImage($path)) {
throw new RuntimeException("Could not write page {$index}.");
}
$index++;
}
fwrite(STDOUT, 'Wrote ' . ($index - 1) . " page images to {$outputDir}\n");
} finally {
$pages->clear();
$pages->destroy();
}
Save this as convert.php and run php convert.php input.pdf output 150. The example’s 100-page and 36–600 DPI bounds are application safeguards, not universal requirements; set limits to fit your workload and host.
The PHP manual documents Imagick::readImage() and includes a user-contributed example using writeImages() for a PDF sequence. The code above writes each iterator page explicitly, which gives the application control over names and per-page checks. See Imagick::readImage and the Imagick extension reference.
3. Select pages or adjust output
Render one page
Imagick supports page selectors in filenames. A user-contributed PHP manual note shows a zero-based selector such as document.pdf[0]. Validate indexing with your deployed ImageMagick stack, and validate page numbers before passing them into a filename.
<?php
$im = new Imagick();
try {
$im->setResolution(150, 150);
$im->readImage('/srv/private/document.pdf[0]');
$im->setImageFormat('png');
$im->writeImage('/srv/private/output/page-0001.png');
} finally {
$im->clear();
$im->destroy();
}
Choose resolution and format
- Resolution: Set it before
readImage(). Higher DPI increases pixel dimensions and generally raises memory, CPU, and storage use. Choose based on whether the result is a small preview, screen image, OCR input, or print asset. - JPEG: Often suitable for compact previews, especially for photographic pages. It is lossy.
- PNG: Lossless and can preserve transparency. It may use more storage, depending on the page content.
- Transparency: Decide whether to preserve it or flatten onto an explicit background when the chosen output format does not preserve it as required. Inspect pages with transparent content.
- Output names: Generate names on the server. Do not use a client-supplied filename as an output path.
There is no universally correct DPI or format. Compare output quality and resource consumption on representative documents from your workload.
4. Handle untrusted files and resource limits
PDF conversion invokes complex parsers and, in this stack, an external rendering delegate. ImageMagick policy can limit allowed coders, delegates, and resource consumption, and may intentionally deny PDF interpretation. Keep those controls in place unless you have assessed the deployment’s needs and risks.
- Restrict accepted file size, page count, page dimensions, and conversion duration.
- Run workers with least privilege and access only to required input and output locations.
- Use isolated workers where practical for untrusted uploads.
- Keep temporary files outside executable locations, generate their names server-side, and remove them after success or failure.
- Apply ImageMagick resource limits and review its policy before enabling PDF or delegates.
- Pin and verify the PHP, Imagick, ImageMagick, and Ghostscript versions actually deployed; the cited material does not establish a universal compatibility matrix.
The Imagick project recommends restricting scripts’ access to files and system resources, while noting that its guidance is not a security guarantee: Imagick project guidance.
5. Troubleshoot common failures
| Symptom | Likely cause | What to check or fix |
|---|---|---|
Class "Imagick" not found |
The extension is missing or disabled in the PHP runtime running the script. | Enable/install Imagick for that exact SAPI or worker, then restart the relevant process and check extension_loaded('imagick'). |
| PDF coder or delegate is unavailable | ImageMagick cannot access its PDF reader delegate, commonly Ghostscript. | Install/configure Ghostscript for the host and verify ImageMagick sees it from the application environment. ImageMagick’s format documentation identifies Ghostscript as required for PDF reading. |
| “not authorized” or policy error | ImageMagick policy denies PDF reading or the required delegate. | Inspect the active policy and deployment security requirements. Change policy only deliberately and narrowly; do not disable safeguards indiscriminately. |
| Only the first page appears | The code reads or writes one image instead of iterating the sequence, or writes a sequence as a single output. | Iterate the Imagick image sequence and write each page, or verify the semantics and resulting filenames of writeImages() on the installed version. |
| Output files have unexpected names | Sequence naming behavior varies with path and ImageMagick version. | Write pages individually with generated names, as in the example, and inspect the output directory in a staging conversion. |
| Out of memory, slow conversion, or worker termination | High DPI, large page dimensions, many pages, or insufficient policy/process limits. | Lower DPI, enforce page and dimension bounds, process smaller jobs, and review ImageMagick resource limits and worker memory/time limits. |
| Output is blurry or too large | Raster density is mismatched to the use, or compression/format choices do not fit the content. | Set density before reading; compare a few DPI and format choices with representative pages and downstream display requirements. |
| Write failure or missing pages | Output path is unwritable, storage is full, or an individual page failed. | Check directory permissions and free space, use server-generated paths, and report the failing page without leaving temporary output behind. |
6. Performance, reliability, and cost
Rasterization cost grows with page count and pixel dimensions. Increasing DPI in both page dimensions can multiply the number of pixels substantially, which affects memory, CPU time, and output size. Measure with representative PDFs rather than assuming a throughput figure. The research sources provide no controlled performance comparison or benchmark.
For reliability, use bounded jobs, timeouts, per-page error reporting, temporary storage with cleanup, and a queue for workloads that should not block web requests. Watch worker memory and disk use. A retry is useful for transient infrastructure failures, but repeated retries will not fix a denied policy, missing delegate, corrupt input, or deterministic resource limit.
Budget for the conversion worker’s compute, memory, storage, and any operational isolation you require. Output format and quality settings affect storage. No source in the research dossier establishes a universal conversion cost.
7. Other PHP wrappers
Pop PHP documents Pdf::extractAsImages(), which produces one image per page and requires Imagick. Spatie’s pdf-to-image provides a page-saving workflow and notes ImageMagick PDF policy as a possible cause of denied reads. These wrappers can simplify application code, but they do not remove the underlying Imagick/ImageMagick dependency. Check current releases and compatibility against your own stack before adoption. The available research does not establish a performance or security winner among these options.
8. Or skip the browser setup
If your goal is a screenshot of a PDF viewer page in a browser rather than raster files for every PDF page, ScreenshotNeo can capture a URL as an image or PDF. It is a website screenshot API, so it does not replace server-side PDF page rasterization when you need each original PDF page as its own image. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers say which outcome occurred. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up for 1,000 free screenshots a month, with no card.
9. FAQ
Does Imagick convert a PDF into one image or many?
It reads a PDF as an image sequence. Iterate the pages and write each one when you need separate files.
Does this produce searchable text?
No. Raster images contain pixels rather than the PDF’s searchable text structure. Keep the original PDF or run a suitable OCR workflow if searchable text is required.
Can I use this approach in a web request?
It can be called from PHP, but large or untrusted documents are generally better handled in bounded background jobs so conversion time and memory use do not consume a web request’s limits.
Is a wrapper library a way to avoid Ghostscript?
Not for the cited Pop PHP and Spatie paths: they use the Imagick/ImageMagick stack, so verify the same PDF delegate and policy prerequisites.


