Free tools Windows power users keep installed
One-click scans. No signup required.
If wkhtmltopdf fails when PHP calls it with exec(), first capture the command’s output and exit status in the same environment that runs your web application. Then check, in order, executable discovery, argument quoting, the PHP process user’s file access, the installed wkhtmltopdf build, and renderer errors such as inaccessible local assets. Without the exact command, operating system, PHP and wkhtmltopdf versions, runtime user, and diagnostics, there is no reliable way to identify one cause.
Capture the failure before changing the command
PHP’s exec() runs a command and can fill an output array with lines while assigning the process result code to a separate variable. Its own return value is only the last line of output; it does not tell you by itself whether the command succeeded. A successful command may produce no output, and a nonempty last line is not proof of failure.
Start with a minimal diagnostic wrapper. Use a fixed, trusted command while investigating, and avoid logging API keys, credentials, sensitive document contents, or untrusted input.
<?php
$output = [];
$status = null;
$command = '/verified/path/to/wkhtmltopdf --version';
$lastLine = exec($command, $output, $status);
error_log('wkhtmltopdf command: ' . $command);
error_log('wkhtmltopdf exit status: ' . var_export($status, true));
error_log('wkhtmltopdf output: ' . json_encode($output));
error_log('wkhtmltopdf last line: ' . var_export($lastLine, true));
?>
The example deliberately checks only the version command. Replace the executable path only after verifying where the binary is installed. Clear the output array before each call: PHP appends new lines to an existing array rather than clearing it for you. Consult the PHP exec() documentation for the function’s return and result-code behavior.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problems#1 Best Overall
Record the runtime context
A command that works in your terminal can fail from PHP because the web-server process may have a different environment, working directory, PATH, permissions, or user identity. Record the following alongside the diagnostic output:
- Operating system and architecture.
- PHP version and the web-server or PHP-FPM configuration that runs the request.
- The identity of the PHP process user, determined using the deployment’s normal administrative tools.
- The verified wkhtmltopdf executable path and the output of its version command.
- The current working directory, input path, output path, and relevant environment values such as
PATH. - The exact arguments used, with secrets and private document data removed from logs.
Compare the version command run by PHP with the one run in an interactive shell. A mismatch, or a “not found” result in PHP, points toward executable discovery or a different installed build—not necessarily a problem with the HTML.
Check executable discovery and build differences
Use a verified absolute path for wkhtmltopdf rather than assuming the web process inherits the same PATH as your login shell. Confirm that the PHP process can execute the file and that any required libraries or runtime dependencies are available to that process. The actual install location depends on the operating system and package.
Also inspect the version and build shown by the binary PHP launches. The wkhtmltopdf project describes 0.12.6 as its stable series, released June 11, 2020, but that release fact is not a guarantee that every operating system or repository still supplies it. The project cautions that package builds differ; in particular, patched-Qt features may not be available in every build. Check the project’s official downloads and build information and validate needed options against the installed executable’s own help and version output.
Rank #2
A useful distinction is whether the command itself can start and report its version, versus whether a conversion starts but fails. If the version check fails from PHP, focus on the binary path, executable permissions, environment, or process restrictions. If it succeeds but a particular conversion does not, continue with argument, file-access, and rendering diagnostics.
Fix argument quoting and avoid shell injection
A shell command is parsed before wkhtmltopdf receives its arguments. Paths containing spaces, quotes, percent signs, shell metacharacters, or non-ASCII characters can therefore be split or altered if they are assembled incorrectly. Quote each argument according to the invocation method and operating system; quoting the whole command as one string is not a substitute for quoting its individual arguments.
Never concatenate user-controlled URLs, paths, HTML-derived values, or other untrusted data into a shell command. The PHP manual warns: “When allowing user-supplied data to be passed to this function, use escapeshellarg() or escapeshellcmd() to ensure that users cannot trick the system into executing arbitrary commands.” For a string command that must go through a shell, use the relevant PHP escaping function for each dynamic argument and understand its platform-specific behavior. Escaping is not a reason to accept arbitrary executable options from a user.
On PHP 7.4 and later, proc_open() accepts an array of command arguments and can execute the process directly without going through a shell. This helps preserve argument boundaries and avoids shell interpretation, but Windows has additional process and argument-parsing behavior, so test on the actual target platform. The PHP documentation explains these distinctions in its proc_open() reference.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →<?php
$binary = '/verified/path/to/wkhtmltopdf';
$input = '/srv/app/private/report.html';
$outputFile = '/srv/app/var/reports/report.pdf';
$command = [$binary, $input, $outputFile];
$descriptors = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
];
$process = proc_open($command, $descriptors, $pipes, '/srv/app');
if (!is_resource($process)) {
throw new RuntimeException('Could not start wkhtmltopdf');
}
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$exitCode = proc_close($process);
error_log('wkhtmltopdf exit status: ' . $exitCode);
error_log('wkhtmltopdf stdout: ' . $stdout);
error_log('wkhtmltopdf stderr: ' . $stderr);
?>
This example is for PHP 7.4 or later and a Unix-style absolute path. Change the binary, input, output, and working-directory paths for your deployment. With proc_open(), the argument array keeps the path values as separate arguments; do not put shell quote characters around each array item. The descriptor setup captures stdout and stderr separately. For commands that may produce substantial output, design stream handling so both pipes are drained without blocking; otherwise a full pipe can prevent the child process from finishing. For platform-specific details, follow the PHP documentation rather than assuming Unix shell rules apply on Windows.
Verify input, output, and runtime permissions
Check access as the PHP process user, not only as your account. The source HTML must be readable, and the destination directory must be writable and accessible through every parent directory. Also ensure the output filename is not a directory and that an existing file can be replaced if the application expects that. A permissions test performed as an administrator or in a shell with a different identity does not establish that the web process has the same access.
Use a small, known-simple HTML file and a temporary output location that the PHP process is expected to access. If that conversion works, the invocation and basic output path are less likely to be the problem; investigate the original document, its resources, or its rendering behavior. If even the simple case fails, retain the exit status and error text while checking the executable, arguments, and directory permissions.
Some deployments apply additional filesystem restrictions, including AppArmor rules. wkhtmltopdf’s project guidance discusses an AppArmor configuration; whether it applies depends on the host’s security setup. Do not broaden filesystem access indiscriminately to make a conversion work. Grant only the access needed for the intended input and output locations.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #4
Separate renderer and resource-loading errors
A process can launch correctly and still fail to render the page. Local images, stylesheets, fonts, and other referenced files must be accessible to the wkhtmltopdf process under the deployment’s filesystem and security rules. JavaScript-dependent content can also behave differently depending on timing and build capabilities. Inspect stderr and the exact error text rather than treating every conversion failure as a PHP invocation problem.
The wkhtmltopdf 0.12.6 command documentation describes options including --allow, --disable-local-file-access, --enable-local-file-access, --load-error-handling, and --load-media-error-handling. Their availability and behavior should be checked against the installed binary; do not assume a switch or default from documentation for a different build. See the official command usage documentation.
- For a missing local resource, verify the referenced path and process-user access. If appropriate, allow only the specific resource directory needed rather than enabling broad local-file access.
- For a remote resource, verify that the PHP host can reach it and that the URL is valid from that host. A resource loading in your desktop browser does not prove it is reachable from the server.
- For content rendered by JavaScript, check whether the installed build supports the needed behavior and whether the document is ready before the conversion proceeds. Use only options supported by that binary.
- For errors that concern page loads or media loads, inspect the relevant load-error options and determine whether the document should fail or continue in that case. Do not suppress errors without deciding how missing content affects the PDF.
Do not process untrusted HTML as if it were inert data. A document renderer can access resources available to its process, and the wkhtmltopdf project warns about processing untrusted HTML. Restrict the process’s filesystem and network access to what the conversion requires, and isolate conversion work appropriately for your deployment.
Follow a diagnostic sequence
- Log a safe snapshot. Record the constructed command or argument list, executable path, working directory, PHP version, operating system, runtime identity, and relevant paths. Redact credentials and private document contents.
- Capture both exec results. Reset the output array, save the result code, and record all output lines. Do not judge success from the last-line return value alone.
- Run the version check through PHP. Compare it with the interactive-shell result. If PHP cannot start the binary, verify an absolute path, runtime
PATH, execute permission, dependencies, and host restrictions. - Inspect argument boundaries. Test paths with spaces and other characters actually present in your deployment. Use array-form
proc_open()on PHP 7.4 or later where it fits, and account for Windows parsing separately. - Test a simple input and known-writable output directory. Check readability and writability as the PHP process user. This isolates basic invocation and filesystem issues from document-specific rendering.
- Capture stderr and the exit status. If
exec()does not provide enough detail, useproc_open()with separate stdout and stderr pipes, retaining the exact error text. - Investigate resources and security controls. For a conversion-specific failure, check local and remote resource access, JavaScript needs, installed-build options, and filesystem restrictions. Allow only the access the document requires.
Common symptoms and what to check
| Symptom | Likely area to investigate | Next check |
|---|---|---|
| PHP reports that the command or file cannot be found | Executable discovery or a different runtime environment | Verify the absolute binary path and run --version through PHP; inspect the web process’s PATH. |
| It works in a terminal but not from the website | Different user, environment, working directory, or filesystem restrictions | Compare the PHP process identity, paths, permissions, and environment with the interactive session. |
| A path with spaces or special characters is mishandled | Shell quoting or platform argument parsing | Check each argument boundary; consider array-form proc_open() on PHP 7.4+ and test on the target OS. |
| The executable starts but the PDF is missing or incomplete | Output access, renderer failure, or resource loading | Check exit status, stderr, destination-directory access, and the document’s referenced resources. |
| A command-line option is rejected or behaves differently | Installed version or package-build feature differences | Inspect the actual binary’s version and supported options; verify whether the build has the needed patched-Qt features. |
| Only documents with local assets fail | Local-file access rules or filesystem permissions | Check the precise asset paths and process-user access; review the installed build’s --allow and local-file options. |
These symptoms narrow the investigation but do not prove a cause. The decisive evidence is the exact invocation, runtime context, process exit status, and captured error output.
Or skip the browser setup
If your goal is a clean screenshot of a web page rather than a PDF produced by wkhtmltopdf, ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return PNG, JPEG, WebP, or a PDF. It is a different tool from wkhtmltopdf, so it will not fix a PHP executable or repair a wkhtmltopdf deployment.
For a one-call web-page capture, the API accepts the URL and your access key. See the ScreenshotNeo API documentation for request parameters and response details.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up for ScreenshotNeo’s free plan to try it with 1,000 screenshots a month and no card.
Recommended Free Tools
Quick Recap
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.




