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

If PHP’s shell_exec() returns null or an empty string when you run wkhtmltoimage, that alone does not tell you whether the renderer failed: the function does not expose the child process’s exit status, and null can also mean the command produced no output. For diagnosis, use PHP’s exec() to capture output and the exit code, run the renderer by its absolute path, and test it as the same operating-system account that runs PHP. Then check permissions, platform compatibility, libraries, fonts, and the input page.

Why shell_exec() is a poor failure detector

shell_exec() returns the command’s output as a string, or null if an error occurs or the command produces no output. It does not give you the child process’s exit code. The PHP manual recommends exec() when you need to know that status. That makes a check such as if ($result === null) inconclusive: it cannot distinguish a launch or rendering failure from a successful command that printed nothing.

Also distinguish PHP’s process-launch problem from a rendering problem. PHP may be unable to find or execute the binary, or the program may start but fail to load the page or write the image. Capture diagnostics first; do not assume a particular cause based on an empty result.

Capture the exit code and error output

For a short diagnostic, redirect standard error to standard output and collect both with exec(). Build the command with escaped arguments rather than concatenating untrusted values into a shell command:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<?php
$binary = '/usr/local/bin/wkhtmltoimage';
$input = '/var/www/app/test.html';
$output = '/var/www/app/tmp/test.png';

$command = escapeshellarg($binary)
    . ' ' . escapeshellarg($input)
    . ' ' . escapeshellarg($output)
    . ' 2>&1';

$lines = [];
$exitCode = -1;
exec($command, $lines, $exitCode);

error_log('wkhtmltoimage exit code: ' . $exitCode);
error_log('wkhtmltoimage output: ' . implode("n", $lines));

if ($exitCode !== 0) {
    http_response_code(500);
    echo 'Image generation failed. Check the server log.';
    exit;
}

echo 'Image generated.';
?>

Replace the example paths with paths valid on your server. Confirm that the input file exists and that the PHP service account can write to the output directory. Keep detailed renderer output in a protected server log; it can disclose filesystem paths, URLs, or other sensitive details and should not be sent to an untrusted browser user.

  • A zero exit code means the process reported success, not necessarily that the output is the image you intended. Check that the file exists, is non-empty, and can be opened.
  • A nonzero exit code together with captured output gives you a starting point for identifying whether launch, page loading, or output creation failed.
  • An exception-free PHP call is not proof that the renderer completed successfully. Check the recorded status and the output file.

For production code, a process library can provide structured error handling and configurable executable paths. The phpwkhtmltopdf project, for example, documents setting the binary path and retrieving detailed errors. Its wrapper does not remove the need to check the installed renderer and deployment environment.

Check the executable path and PHP service account

A command that works in your terminal may fail from a web request because PHP can run with a different account, environment, and PATH. Use the full path to the binary in your application configuration instead of relying on shell search paths. Find the path in the target environment and verify it is the intended wkhtmltoimage executable.

  1. Record the operating system and version, PHP version and SAPI, renderer version, executable path, exact arguments, and the captured exit status and output.
  2. Confirm the PHP service account can traverse the binary’s parent directories and has execute permission on the binary.
  3. Confirm the same account can read the input and write to the output directory. Check filesystem mount or service policies that might prohibit execution or writing.
  4. Run a minimal command as that account, not just as your interactive login. Avoid granting broad permissions such as 777; fix the specific ownership or permission boundary that is wrong.

The wrapper’s documentation notes that its binary setting can contain a full path and that its default assumes the command is available on the shell search path. Treat a path or account difference as something to verify in your own deployment, not as a universal explanation.

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

Reproduce the renderer failure outside the PHP request

Use a small local HTML file to separate PHP integration from renderer behavior. Invoke the exact binary with the same source and destination paths, under the PHP service account, and capture its standard error and return status. Then change one condition at a time: binary path, execute access, output-directory access, required libraries, fonts, or access to local and network resources.

If the direct command fails in the same way, focus on the renderer or its runtime dependencies. If it succeeds but the PHP invocation fails, compare the account, environment variables, working directory, quoting, and command arguments. A local test page also helps determine whether the failing input’s JavaScript, CSS, images, or other resources are involved.

Check operating-system and runtime compatibility

The renderer binary must match the target system; a downloaded executable is not automatically portable between Linux distributions. The wkhtmltopdf project downloads page says generic binaries generally do not work on Alpine Linux because Alpine uses musl rather than glibc, and recommends distribution-specific packages where available. Prefer a package intended for the server’s distribution rather than trying to solve an ABI mismatch with permissions changes.

Also check whether the deployment includes the libraries and fonts the renderer needs. Minimal containers, packaged applications, and serverless environments may omit runtime libraries or font configuration that exist on a developer workstation. The project downloads page identifies version 0.12.6 as its stable series and gives June 11, 2020 as its release date; that is a dated project statement, not a guarantee that the version is the latest or suitable for every current environment.

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

If your PHP application uses the wkhtmltox extension rather than launching the standalone wkhtmltoimage executable, the PHP extension requirements specifically tell Windows users to add wkhtmltox.dll to PATH. That extension requirement is distinct from finding the standalone command-line program.

Check inputs, output paths, and page resources

A process can start correctly but fail to produce a usable image. Verify that the input is reachable from the PHP process, the destination’s parent directory exists, and the service account has permission to write there. Check the renderer’s captured diagnostics for page-load or resource errors, then test with a simple HTML document and a local output file. If the minimal case works, add the original page’s CSS, scripts, images, and remote resources incrementally.

  • No output file: check the command arguments, destination path, parent directory, and write access.
  • File exists but is blank or incomplete: check whether the page loaded as expected and whether the capture ran before required content or images were ready.
  • Only some assets are missing: verify that the renderer can access the referenced URLs or local files from the server environment.

These are diagnostic branches, not a claim that one setting fixes every rendering failure. Use the actual command output and a minimal reproducible page to narrow the cause.

Keep rendering untrusted HTML inside a security boundary

Do not fix a rendering failure by granting the renderer unrestricted filesystem or command access. The wkhtmltopdf project warns against using wkhtmltopdf with untrusted HTML unless user-supplied HTML and JavaScript are sanitized, because it can lead to complete server takeover. Treat HTML, scripts, URLs, and file references that users can influence as security-sensitive inputs.

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

The project’s AppArmor guidance describes confining filesystem and command access on supported Linux systems. It also explains why the renderer’s --disable-local-file-access setting alone may not be a sufficient boundary in the presence of a binary vulnerability. Use operating-system isolation appropriate to your deployment, restrict what the process can read and execute, and avoid exposing raw diagnostic output to users.

When to ask for help

If the failure persists after a minimal test, prepare a reproducible report. The project support page asks for the renderer version, operating system and version, and a detailed test case.

  • Renderer version and exact executable path.
  • Operating system/version, PHP version, PHP SAPI, and execution account.
  • The command and options with secrets removed, along with the exit status and captured standard error.
  • A minimal HTML/CSS/JavaScript example that reproduces the issue, plus the expected and actual result.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your actual need is to capture a website rather than maintain a server-side browser-rendering installation, ScreenshotNeo is a screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF; its options include full-page capture, CSS selectors, device presets, custom headers and cookies, and waits for a selector, delay, or network idle. It can also capture PDFs, run asynchronous or bulk jobs, and serve AI agents through an MCP server.

For a one-request example, the API accepts a URL and returns an image:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for authentication and options. Cookie banners and consent overlays, newsletter popups, and chat widgets are removed before capture by default, and those cleanup steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; response headers identify the page verdict and billing status. An MCP server lets AI agents use screenshot tools. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

Sign up free for 1,000 screenshots a month, with no card required.

Frequently Asked Questions

Does an empty string from shell_exec() prove wkhtmltoimage failed?

No. Empty output does not establish whether the renderer succeeded; use an exit-status-aware call such as exec() and verify the output file.

Should I use chmod 777 to fix permission denied?

No. Check execute and directory traversal permissions for the binary, plus write permission for the output directory, and adjust only the required access.

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

Is wkhtmltoimage 0.12.6 necessarily the latest supported release?

The project downloads page identifies 0.12.6 as a stable series released in 2020; that statement alone does not establish current support or suitability for your environment.

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.