Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Most wkhtmltopdf npm errors are not JavaScript errors. The npm module is only a Node.js wrapper; it starts a separate wkhtmltopdf executable. Install a compatible executable, make it available to the Node process, and verify that its operating-system libraries can load. Then diagnose URL and asset failures separately from process-startup failures.

This guide covers spawn ENOENT, “command not found,” exit code 127, HostNotFoundError, ContentNotFoundError, npm installation failures, Docker and Lambda deployments, and a repeatable way to capture useful stderr.

Understand what the npm package does

The package commonly installed as wkhtmltopdf is described as “A Node.js wrapper for the wkhtmltopdf command line tool.” It does not contain the PDF converter itself. Your Node process launches the external program and passes it a URL or HTML document.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

That separation explains the error pattern:

  • If the executable cannot be found or started, you see command not found, spawn ENOENT, or an immediate process failure.
  • If the executable starts but a shared library is missing, the operating system can return exit code 127.
  • If the executable starts and cannot fetch a page or one of its resources, wkhtmltopdf reports errors such as HostNotFoundError or ContentNotFoundError.

The official project’s stable series is 0.12.6, released June 11, 2020. Its builds use patched Qt features that are absent from some distribution packages. Even a “static” build still needs compatible system libraries, fonts and other runtime files.

Install and verify the converter before debugging Node

Install the wrapper and record versions

npm install wkhtmltopdf
node --version
npm --version
npm ls wkhtmltopdf

Install an operating-system build of wkhtmltopdf separately. Record the exact wrapper version, converter version, operating system or distribution, CPU architecture and deployment target. A binary built for a different architecture or distribution can be present and executable yet still fail to load.

Resolve the executable in the same environment as Node

Run these commands as the same account that runs your service, worker or container:

command -v wkhtmltopdf
wkhtmltopdf --version

On Windows, use:

where wkhtmltopdf
wkhtmltopdf.exe --version

A successful interactive shell lookup does not prove that an IDE, systemd service, queue worker, GUI-launched process or serverless function has the same PATH. Test from that actual runtime. On Unix, also check execute permission with ls -l. On Windows, account for spaces in the installation path.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set an absolute command path

The most reliable configuration is an environment variable containing the full path, with a development fallback:

const wkhtmltopdf = require('wkhtmltopdf');

wkhtmltopdf.command = process.env.WKHTMLTOPDF_BIN || '/absolute/path/to/wkhtmltopdf';

Use a Windows path appropriate for your machine, such as C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe. Do not assume that changing your interactive shell profile changes the environment inherited by a service.

Run a minimal conversion from Node

First remove network, authentication and application-template variables from the test. Inline HTML isolates the converter and wrapper:

const fs = require('node:fs');
const wkhtmltopdf = require('wkhtmltopdf');

wkhtmltopdf.command = process.env.WKHTMLTOPDF_BIN || '/absolute/path/to/wkhtmltopdf';

const html = '<!doctype html><html><body><h1>Test PDF</h1><p>wkhtmltopdf started.</p></body></html>';

const output = fs.createWriteStream('test.pdf');
const pdf = wkhtmltopdf(html, {
  debug: true,
  debugStdOut: true
});

pdf.pipe(output);
pdf.on('error', (error) => {
  console.error('wkhtmltopdf error:', error);
});
pdf.on('end', () => {
  console.log('Wrote test.pdf');
});

If your wrapper version supports direct output, this shorter form is also useful:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const wkhtmltopdf = require('wkhtmltopdf');
wkhtmltopdf.command = process.env.WKHTMLTOPDF_BIN || '/absolute/path/to/wkhtmltopdf';

wkhtmltopdf('https://example.com', { output: 'example.pdf', debug: true }, (error) => {
  if (error) {
    console.error(error);
    process.exitCode = 1;
    return;
  }
  console.log('PDF created');
});

The wrapper accepts URL input, inline HTML, streams, output files and callbacks. Enable its debug options and preserve both stdout and stderr while troubleshooting; the operating system often explains a generic Node error.

Use this diagnostic sequence

  1. Record the environment. Save Node, npm, wrapper and wkhtmltopdf versions, distribution, architecture, current working directory and the account running the process.
  2. Resolve the command inside the deployment. Use command -v, where, or the configured absolute path. Log the value that Node actually uses.
  3. Execute the binary directly. Run its absolute path with --version, then convert a tiny local HTML file outside Node. If that fails, JavaScript is not the first problem.
  4. Log process details. Capture configured command, selected environment variables, working directory, exit code, stdout and stderr. Use debug and debugStdOut where available.
  5. Convert inline HTML. This separates executable and library problems from DNS, TLS, authentication and missing-resource problems.
  6. Add the real URL or template. Test the exact address from the same server or container and inspect every stylesheet, image, font and script URL.
  7. Recheck deployment dependencies. In Docker and Lambda, inspect shared libraries, fonts and writable temporary storage instead of assuming a copied executable is self-contained.

Fix “wkhtmltopdf: command not found” and spawn ENOENT

These messages mean the child process could not be discovered or started. A shell may find the program while Node receives a shorter or entirely different PATH. Configure an absolute path or set the service’s environment explicitly:

const wkhtmltopdf = require('wkhtmltopdf');
const binary = process.env.WKHTMLTOPDF_BIN;

if (!binary) {
  throw new Error('WKHTMLTOPDF_BIN is not configured');
}
wkhtmltopdf.command = binary;

Then verify all of the following in the same runtime:

  • The file exists and is executable on Unix.
  • The path is correctly quoted on Windows, especially when it contains spaces.
  • The file is built for the host CPU and operating system.
  • The service account can traverse the parent directories and execute the file.
  • The process has not sanitised or overwritten PATH and WKHTMLTOPDF_BIN.

If the absolute binary fails when run directly, fix that failure before changing wrapper code.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fix exit code 127 and shared-library errors

Exit code 127 generally means the operating system could not run the program. In an Amazon Linux 2 Lambda deployment, wkhtmltopdf reported error while loading shared libraries: libXrender.so.1: cannot open shared object file and exited 127. Copying only the executable did not solve it.

Run the binary inside the final image or function package and read stderr. Install or bundle the libraries required by that exact distribution. A static Qt build reduces some dependencies but does not make the program dependency-free; distribution-specific library versions still matter. Include fonts used by your documents and provide writable temporary storage for intermediate files.

For a container, make the image build reproducible: install the chosen binary and its libraries in the Dockerfile, run wkhtmltopdf --version during an image check, and perform a local conversion before deploying. For Lambda, test in the Lambda-compatible runtime rather than on your workstation.

Fix HostNotFoundError, TLS and URL failures

Once the process launches, wkhtmltopdf must resolve and reach the source URL and every referenced resource. HostNotFoundError points to DNS or reachability trouble from the conversion environment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Request the exact URL from the server or container with a suitable HTTP client.
  • Check DNS configuration, outbound firewall rules, proxy variables and private-network routes.
  • Confirm that the hostname in the PDF job is resolvable from the worker, not merely from your laptop.
  • Check certificate and TLS behavior. A warning such as “SSL error ignored” is not proof that all resources loaded.
  • Use a reachable internal address or local file when the page is intentionally private.

Preserve wkhtmltopdf stderr and inspect the generated HTML’s absolute and relative URLs. If authentication is required, make the relevant cookies, headers or other credentials available to the conversion process without logging secrets.

Fix ContentNotFoundError and missing assets

A document can look partly rendered and still fail because an image, stylesheet, font or script returned 404 or was inaccessible. An upstream report documents ContentNotFoundError for a missing image and exit code 1.

Open each resource URL from the same runtime and check its status, redirects and authentication requirements. Relative paths are resolved against the document URL, so a template that works from a browser may fail when supplied as a temporary file. For critical, stable assets, embed small images or styles as data URIs or use local files. Ensure local paths are readable by the service account and use the correct file URL format where required.

Separate npm installation failures from runtime failures

If the error occurs during npm install, wkhtmltopdf has not necessarily run yet. npm can report ENOENT or ENOTEMPTY races, permissions and ownership problems, path-length limits, proxy or SSL failures, and invalid package conditions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Read the complete npm log and identify whether the failing path is npm’s cache, the project directory or a post-install script.
  2. Update npm and retry with a clean, writable cache.
  3. Correct directory ownership rather than running the whole project as an unsafe elevated user.
  4. Check proxy and certificate settings used by npm.
  5. After installation succeeds, run npm ls wkhtmltopdf and test the external executable separately.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Choose a build deliberately

Option Potential benefit Risk to check
Official 0.12.6 build Patched-Qt behavior documented by the project Still needs compatible system libraries, fonts and CPU support
Distribution package Integrated dependency management for that operating system May omit patched features; versions and behavior vary by distribution
Alternative HTML-to-PDF engine May fit a newer rendering or deployment model Requires a separate compatibility, security and maintenance evaluation

Compare patched-Qt feature support, operating-system and CPU compatibility, shared-library and font requirements, network and authentication behavior, maintenance status and reproducibility in your container. Do not select a package solely because its filename says “static.”

Security, reliability and performance safeguards

Sanitize untrusted HTML

The official project warns not to use wkhtmltopdf with untrusted HTML unless user-supplied HTML and JavaScript are sanitized; otherwise the converter can lead to complete server takeover. Treat templates, URLs, cookies and custom headers as privileged inputs. Isolate conversion workers, restrict outbound network access where practical, and never pass secrets into a document that an untrusted author can inspect.

Make failures observable

Log a job identifier, URL or template identifier, binary path, versions, duration, exit code and sanitized stderr. Do not log access tokens or cookie values. Keep the original stderr long enough to distinguish startup, library, network and missing-resource failures.

Control resource use

Run conversions with bounded concurrency and a process timeout. Large pages, remote assets and JavaScript can consume substantial CPU, memory and temporary disk. Reuse a verified worker image instead of discovering binaries at request time, and test representative documents after every image or library update.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If your requirement is simply a clean screenshot or PDF of a URL, ScreenshotNeo avoids installing wkhtmltopdf and its OS dependencies. It accepts cookie and consent banners before capture, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and lets you turn each cleanup step off. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed; each response identifies the result with X-Page-Verdict and X-Billed headers.

One GET request returns PNG, JPEG, WebP or PDF. The API also supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, device presets or custom viewports, retina scale, PDF paper size and margins, custom CSS and JavaScript, clicks, waits, blocked requests, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of 100 URLs per call, a usage API and an OpenAPI specification. An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.

See the ScreenshotNeo documentation for parameter details. The same parameter names used by many screenshot APIs are accepted, which can simplify migration.

cURL

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

Python

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)

Node.js

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 failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', buffer);

The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Create a free ScreenshotNeo account to try the 1,000-shot allowance without a card.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.