ScreenshotNeo

BlogComparisons

wkhtmltoimage vs Puppeteer for Website Screenshots

Compare wkhtmltoimage and Puppeteer for website screenshots, with runnable examples, capture options, security guidance, and help choosing for your workload.

By the ScreenshotNeo team4 October 20268 min read

Short answer: Start with Puppeteer for new screenshot work when your pages depend on JavaScript or modern browser behavior. It offers page and element screenshots, full-page capture, clipping, and transparent backgrounds. wkhtmltoimage can still suit simpler pages and existing workflows, but its official project describes a Qt WebKit-based headless renderer, and the downloads page lists version 0.12.6 as released on June 11, 2020. Verify the exact build, compatibility, and security posture before relying on it in production. [Puppeteer screenshots; wkhtmltopdf project; project downloads]

This guide compares the tools by behavior and capture controls, gives runnable starting points, and outlines the checks needed before choosing one. There is no controlled, like-for-like benchmark here: speed, memory use, and fidelity depend on the pages and deployment environment, so measure those yourself.

1. How the tools differ

Area wkhtmltoimage Puppeteer
Architecture Command-line headless HTML renderer based on Qt WebKit. JavaScript browser-automation library with a screenshot API.
Typical use Invoke a renderer with an input URL and output options. Launch a browser, navigate to a page, then capture a page or element.
Documented controls Screen dimensions, crop dimensions, output format, JPEG quality, JavaScript enablement, and post-load delay. Full-page output, clipping, transparency, and element screenshots, among other screenshot options.
Dynamic pages JavaScript and a delay are configurable, but do not assume a modern site will render correctly. A stronger starting point when behavior depends on a browser and JavaScript. Validate page readiness explicitly.
Project history The official downloads page identifies 0.12.6 as stable and dates it to June 11, 2020. Check your package or fork directly. Consult current official documentation and security guidance for the version you deploy.

The wkhtmltopdf maintainer’s status essay historically advised users converting sites with dynamic JavaScript to consider Puppeteer or a wrapper. That is project commentary, not a current benchmark or proof that Puppeteer wins every workload. [wkhtmltopdf status essay]

2. Choose based on the page and the job

  • Choose Puppeteer as your starting point when a target needs JavaScript, browser-driven interactions, element-level capture, full-page output, clipping, or transparent backgrounds.
  • Consider wkhtmltoimage when you already operate it, target pages render correctly in your exact build, and its command-line sizing and output options meet your needs.
  • Run a migration comparison before replacing an established renderer. Different rendering engines can produce different fonts, line breaks, image sizes, and page heights.

For either choice, make the capture requirements explicit: viewport dimensions, full-page versus viewport capture, crop or element boundaries, output format and quality, transparency, and when the page is considered ready.

3. Capture a screenshot with wkhtmltoimage

Install a build appropriate for your operating system from the project’s downloads information, then confirm which executable is actually running:

wkhtmltoimage --version

Basic URL-to-image capture:

wkhtmltoimage https://example.com screenshot.png

Set the rendering width, output format, and JPEG quality with the documented image settings:

wkhtmltoimage --width 1440 --format jpg --quality 85 https://example.com screenshot.jpg

To capture a particular region, the image settings include crop width and height. A post-load delay can give some pages extra time, and JavaScript can be enabled or disabled. Check the options supported by your installed build with wkhtmltoimage --help; packaging and downstream builds can differ.

wkhtmltoimage --width 1440 --crop-w 1200 --crop-h 800 --javascript-delay 1500 https://example.com screenshot.png

Confirm exact option names and behavior against the installed executable and the project’s image settings reference. The command above illustrates common settings; it does not guarantee a particular crop origin or identical output across builds.

4. Capture a screenshot with Puppeteer

Install Puppeteer in a Node.js project using the package installation instructions for the version you intend to use. This runnable example opens a page, waits for navigation, and captures a full-page PNG:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1440, height: 900 });
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  await page.screenshot({ path: 'screenshot.png', fullPage: true });
} finally {
  await browser.close();
}

For a viewport-only image, omit fullPage. To capture an element, use the locator screenshot API:

const card = page.locator('.product-card');
await card.screenshot({ path: 'product-card.png' });

Screenshot options also document clipping and transparent backgrounds. Check the screenshots guide and ScreenshotOptions API for the current version’s types, defaults, and supported options. A clip is a rectangle in page coordinates; ensure it lies within the content you intend to capture.

5. Make the comparison fair

  1. Build a representative page set. Include static pages, JavaScript-rendered content, long pages, pages with custom fonts and images, and any pages that trigger consent banners or overlays.
  2. Match the capture geometry. Use the same viewport, device scale assumptions, target region, and full-page or viewport behavior.
  3. Define readiness. Decide whether you need navigation completion, a known selector, a delay, or another page-specific signal. Network quiet alone may be unsuitable for pages with long-lived requests.
  4. Compare artifacts. Inspect text wrapping, missing or late images, font substitution, sticky elements, blank regions, crop edges, and output dimensions.
  5. Measure in your deployment. Record latency and resource use under the same operating system, container limits, fonts, network conditions, and concurrency. No universal speed or memory winner is established by the cited documentation.
  6. Review operational risk. Check runtime and browser installation, package maintenance, security isolation, and how failed captures are detected and retried.

6. Security and reliability

A screenshot service that accepts arbitrary URLs or HTML is a security boundary. A remote page can trigger network requests, and untrusted HTML can exercise renderer capabilities. The wkhtmltopdf project warns about rendering untrusted HTML and provides AppArmor guidance. Puppeteer likewise says safe use of its powerful capabilities is the caller’s responsibility. [wkhtmltopdf AppArmor guidance; Puppeteer security policy]

  • Accept only intended input sources; validate URL schemes and destinations if users supply URLs.
  • Run rendering in an isolated process or container with restricted filesystem and network access appropriate to the job.
  • Set bounded timeouts and resource limits. Treat a hung navigation or oversized page as a failed job with a clear outcome.
  • Use a clean browser context per job when cookies or local storage must not leak between captures.
  • For reproducibility, pin and record the renderer/browser version, operating system image, installed fonts, and relevant capture settings.
  • On retries, use a bounded policy and distinguish transient network failures from deterministic page errors.

7. Performance, reliability, and cost

Neither project’s cited documentation establishes a universal throughput, memory, fidelity, or operating-cost winner. Compare total workload cost in your own environment: runtime and browser installation, machine resources, concurrency, timeouts, retries, maintenance, and the engineering time needed to correct rendering differences.

For reliability, capture a defined set of known pages repeatedly and track successful output, dimensions, completion time, and visual changes. Fonts, remote assets, asynchronous content, bot checks, and consent layers can all change the result. Keep the page set and environment fixed when investigating a regression.

8. Troubleshooting

Symptom Likely cause What to check
Blank or incomplete image Capture began before content rendered, the page failed, or scripts/resources did not load. Check navigation errors and page readiness. Wait for a meaningful selector or a bounded delay; verify network access and JavaScript behavior.
Modern page looks different in wkhtmltoimage The rendering engine or installed build may not support the page’s required behavior. Confirm the exact version and test the target in Puppeteer. Compare fonts, layout, and dynamic content on representative URLs.
Element screenshot fails or is empty The selector matched no visible element, the element is outside the rendered state, or it has zero size. Wait for the selector, verify it is visible, and inspect its dimensions before capture.
Full-page capture misses lazy-loaded images Images may load only as their regions approach the viewport. Scroll through the page or use a page-specific readiness routine before capture; check image completion before taking the screenshot.
Fonts or images differ between runs Remote resources were unavailable, fonts differ, or the capture ran before resources settled. Make fonts and assets available consistently, wait for the relevant resources, and record the runtime image and network conditions.
Output has the wrong dimensions or crop Viewport, crop, full-page, or device scale settings do not match. Set the viewport explicitly and inspect the tool’s crop and screenshot options for the installed version.
Process hangs or times out A page may keep requests open, load slowly, or consume excessive resources. Use bounded navigation and job timeouts, choose a page-specific readiness condition, and terminate isolated worker processes that exceed limits.
Different output after deployment OS, fonts, browser or renderer version, or package build changed. Pin and log environment details, then compare a fixed regression set.

9. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request returns an image or PDF; its clean-shot flow accepts consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture. Each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing outcome.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));

See the ScreenshotNeo API documentation for the request options and response details. It also has an MCP server for Claude, Cursor, and other MCP clients, with take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month.

10. FAQ

Does wkhtmltoimage execute JavaScript?

Its image settings include JavaScript enablement and a post-load delay. Whether that is enough depends on the page and the exact build; test the target instead of assuming modern app behavior will work.

Is Puppeteer a screenshot command-line tool?

It is a JavaScript browser-automation library. A Node.js script launches a browser, navigates to a page, and calls the screenshot API.

Which one is faster?

The reviewed sources provide no controlled comparison. Measure representative pages in the operating environment and concurrency level you plan to use.

Should an existing wkhtmltoimage deployment be replaced?

Not solely because of a version date. Verify the build’s maintenance and security posture, then compare its output and operations against your requirements before deciding.

Sources