ScreenshotNeo

BlogHow-to

How to Convert an HTML File to PNG with wkhtmltoimage

Convert a local HTML file to PNG with wkhtmltoimage, control dimensions and timing, automate it with Python or Node.js, and troubleshoot common issues.

By the ScreenshotNeo team4 October 20268 min read

To convert a local HTML file to PNG with wkhtmltoimage, run this from a terminal:

wkhtmltoimage input.html output.png

Replace the paths with your input HTML file and desired PNG destination. The command-line form is wkhtmltoimage [OPTIONS]... <input file> <output file>. If the executable is installed and available on your PATH, this produces an image from the rendered page. The project describes wkhtmltoimage as a headless renderer built on Qt WebKit; its main repository was archived in January 2023. That maintenance status and its older rendering engine are worth considering for new long-lived systems. (project repository, command reference)

1. Install and check wkhtmltoimage

Install the wkhtmltopdf package for your operating system using its official package or distribution instructions; the package commonly includes both wkhtmltopdf and wkhtmltoimage. Package availability and build features vary. Then check that the command resolves and inspect the installed version and supported options:

wkhtmltoimage --version
wkhtmltoimage --help

If the shell says “command not found” or “not recognized,” the executable is missing or its directory is not on PATH. Install the appropriate package or call the binary using its full path. For scripts and deployments, record the binary path and version, since two machines may have different builds and flags.

2. Convert the HTML file

From the directory containing the file:

wkhtmltoimage input.html output.png

Or use absolute paths to avoid ambiguity:

wkhtmltoimage /srv/reports/input.html /srv/reports/output.png

After conversion, open output.png and check the content, dimensions, fonts, image loading, and clipping. A successful command does not guarantee that the output matches a modern browser exactly.

Use an explicit output format

The filename extension usually indicates the output format. You can also request one with --format, if supported by your build:

wkhtmltoimage --format png input.html output.png

Consult wkhtmltoimage --extended-help or the installed manual for the formats supported by that binary.

3. Set the viewport and crop the image

--width sets the screen width used to lay out the page. By default it acts as a guide; the renderer may adjust it to fit content. Use --disable-smart-width where available to make width strict. --height sets the screen height, which otherwise may be calculated from page content. For example:

wkhtmltoimage --width 1200 --height 900 input.html output.png

To capture a rectangle, provide its origin and size with crop options:

wkhtmltoimage \
  --crop-x 100 --crop-y 80 \
  --crop-w 800 --crop-h 500 \
  input.html output.png

Crop coordinates and dimensions are pixels. Make sure the selected rectangle lies within the rendered page; otherwise the result may be clipped or include empty area. Exact layout and dimensions depend on the binary build and page content, so inspect the generated image.

4. Wait for JavaScript-rendered content

If the HTML relies on scripts that update the page after initial load, a capture can happen too early. One option is a fixed delay, if supported by the installed version:

wkhtmltoimage --javascript-delay 1500 input.html output.png

A more targeted option is to have page JavaScript set window.status when the content is ready, then wait for that value:

<script>
  // Set this only after the content needed in the image is ready.
  window.status = 'capture-ready';
</script>
wkhtmltoimage --window-status capture-ready input.html output.png

Check local help for availability and exact behavior. A readiness signal is more reliable than guessing a long delay, but it only works if the page sets the expected status at the right time. Slow or stuck scripts can still prevent useful output.

5. Handle local assets and images

Relative references in HTML, such as images/logo.png or styles.css, are resolved in relation to the document location and renderer behavior. If assets fail to load, use absolute file paths or correct the relative paths, and confirm local-file access settings. Some builds restrict access to local files unless explicitly allowed. The manual documents --allow for allowing files from a specified folder, and --no-images to disable image loading; image loading is normally enabled.

wkhtmltoimage --allow /srv/reports/assets input.html output.png

Only allow directories the conversion job needs. When a page references remote assets, the machine running wkhtmltoimage needs network access and the remote hosts must respond during the conversion.

6. Useful options at a glance

Need Option Notes
Choose output format --format Check supported formats in the local help.
Set viewport width --width May be a guide unless smart width is disabled.
Set viewport height --height Otherwise may be calculated from page content.
Crop the result --crop-x, --crop-y, --crop-w, --crop-h Set the crop origin and size in pixels.
Wait for a page signal --window-status Wait until window.status matches the supplied string.
Wait for scripts --javascript-delay Fixed milliseconds; not all builds expose identical options.
Allow local assets --allow Can be repeated for permitted directories.
Disable images --no-images Useful only when images are not wanted or for diagnosis.
Inspect flags and version --extended-help, --version Use the installed binary’s documentation as final authority.

Other documented options include cookies, custom headers, encoding, JavaScript controls, and zoom. Refer to the wkhtmltoimage manual and local help before putting less common flags into automation.

7. Automate the conversion

Python with subprocess

This invokes the executable directly and raises an error if conversion fails. Install wkhtmltoimage separately; Python code alone does not include the renderer.

from pathlib import Path
import subprocess

source = Path("input.html").resolve()
destination = Path("output.png").resolve()

subprocess.run(
    [
        "wkhtmltoimage",
        "--format", "png",
        "--width", "1200",
        str(source),
        str(destination),
    ],
    check=True,
    timeout=60,
)

if not destination.is_file() or destination.stat().st_size == 0:
    raise RuntimeError("Conversion did not produce a non-empty PNG")

print(f"Created {destination}")

Use an argument list rather than constructing a shell command string. This handles spaces in paths safely and avoids shell interpretation of input values. Tune the timeout to the expected page complexity and environment.

Python with imgkit

imgkit is a Python wrapper around the wkhtmltoimage executable, so the binary remains a system dependency. Install the wrapper with pip install imgkit, then convert a local file:

import imgkit

imgkit.from_file(
    "input.html",
    "output.png",
    options={"format": "png", "width": 1200},
)

The imgkit package documentation includes file and URL conversion examples. If the executable is not on PATH, configure its location using the wrapper’s documented configuration mechanism.

Node.js with child_process

This example works with a Node.js installation and a separately installed wkhtmltoimage binary:

const { execFile } = require('node:child_process');
const { promisify } = require('node:util');
const path = require('node:path');

const execFileAsync = promisify(execFile);

async function convert() {
  const input = path.resolve('input.html');
  const output = path.resolve('output.png');

  const { stdout, stderr } = await execFileAsync(
    'wkhtmltoimage',
    ['--format', 'png', '--width', '1200', input, output],
    { timeout: 60_000, maxBuffer: 1024 * 1024 },
  );

  if (stdout) process.stdout.write(stdout);
  if (stderr) process.stderr.write(stderr);
  console.log(`Created ${output}`);
}

convert().catch((error) => {
  console.error('wkhtmltoimage failed:', error.message);
  process.exitCode = 1;
});

execFile passes arguments separately instead of through a shell, which is preferable when paths or values may contain spaces or untrusted input. Treat a nonzero exit as failure and check that the output file exists and is non-empty.

cURL note

wkhtmltoimage is a local command-line program, not an HTTP endpoint, so cURL does not invoke it directly. Use the shell command above, or expose a separately managed service if an HTTP interface is required.

8. Troubleshooting

Symptom Likely cause What to try
wkhtmltoimage: command not found Not installed or absent from PATH. Install the package, add its binary directory to PATH, or configure the absolute executable path in your script.
Output file is missing or empty Conversion failed, output directory is unwritable, or wrong destination path. Check the exit code and stderr; use an absolute path and confirm directory permissions.
PNG is blank or content is missing Page load failed, JavaScript has not completed, or local/remote assets are inaccessible. Open the source in a browser, verify asset paths and access, and use a supported readiness option.
Fonts or images differ from the expected result Fonts may not be installed in the runtime environment; the page may use resources that fail to load. Install required fonts, check network and asset access, and render in the same environment used in production.
Layout width is unexpected --width can be a guideline rather than strict. Check local help for --disable-smart-width; inspect output dimensions and tune crop options.
Only part of a long page appears Viewport, page content, or cropping settings limit the captured area. Remove crop flags, adjust height or width, and compare the result with the intended capture region.
Unsupported option error Installed build differs from the documentation being followed. Run wkhtmltoimage --version and --extended-help; use only flags exposed by that binary.
Python wrapper cannot find wkhtmltoimage Installing imgkit did not install the external executable. Install wkhtmltoimage separately and configure the executable path using imgkit’s documentation if needed.
Conversion hangs or times out Network resources or scripts are slow or never become ready. Set a bounded timeout, remove unnecessary scripts/resources, and use an explicit readiness condition where supported.

9. Performance, reliability, and cost

Conversion time depends on the HTML, scripts, images, fonts, network resources, machine, and binary build. Avoid loading assets that are not needed, prefer local assets for repeatable jobs, and select only the viewport and crop area you require. A readiness signal can avoid both premature captures and unnecessarily long fixed waits.

For repeatable output, pin the operating-system image and wkhtmltoimage package version, include the required fonts, and test representative pages after any environment change. The main project repository is archived and read-only, so weigh maintenance and rendering compatibility before making it a new long-term dependency. The project describes the Qt WebKit renderer in its README; no performance benchmark is asserted here.

The command-line tool has no per-capture service fee in the cited documentation, but operating cost includes packaging, machine resources, maintenance, and debugging rendering differences. A hosted API shifts the browser installation and runtime operation out of your application, with usage pricing depending on the provider and plan.

10. Or skip the browser setup

If you need a screenshot of a web page rather than a local file, ScreenshotNeo turns one GET request into a PNG, JPEG, WebP, or PDF. See the API documentation for request options. For example:

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

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. These examples capture a URL, not a local HTML file; use wkhtmltoimage when the source must remain a local file.

Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.

Frequently asked questions

Can wkhtmltoimage convert an HTML string without saving a file?

The documented command takes an input file or page source argument. For a simple workflow, save the HTML to a temporary file and pass its path; confirm any alternative input support in your installed build’s help.

Does it capture a full web page?

It renders the page into an image, but dimensions and resulting capture depend on the page and options. Inspect the output and adjust viewport or crop settings to meet your needs.

Does wkhtmltoimage use Chromium?

No. The project describes it as using Qt WebKit. This is relevant when a page depends on newer browser behavior.

Is wkhtmltoimage still maintained?

The main GitHub repository was archived by its owner on January 2, 2023. Check the package and binary you plan to use, and factor that status into adoption decisions.