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

A JavaScript alert does not automatically tell PHP what URL to capture or prove that a page is ready. The reliable approach is to have the page report the needed URL or signal readiness explicitly, then run wkhtmltoimage from PHP with safely escaped arguments and check the process exit code. If you cannot change the page, test the installed renderer’s wait options against that exact build; support can vary.

First decide what “capture a URL after an alert” means

There are three different tasks that are easy to conflate: capturing the browser’s current address, extracting a URL or value shown in an alert, and waiting until the page has finished work before taking a screenshot. An alert is a dialog in the page’s browser context; it is not inherently a message channel to the PHP process that launched the renderer.

If you need the current page address

Have the page report location.href to your application, or otherwise make that value available to PHP. A screenshot command takes a URL as input; it does not automatically return the page’s final address to PHP just because JavaScript navigated or displayed an alert.

If the alert contains the URL or value you need

Change the page code to send that value explicitly, for example to a server endpoint that records it. Do not rely on PHP to read the alert text from a separate rendering process. Treat any reported value as untrusted input: validate its format and allowed destinations before using it in another request or command.

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

If the alert means “the page is ready”

Replace that implicit signal with an application-controlled readiness signal, such as a DOM element with a known selector or a documented window.status value where the renderer supports waiting for it. The page should expose the signal only after the content needed in the screenshot is actually ready. A dialog appearing is not a dependable substitute for an explicit completion contract.

Choose a readiness signal the renderer can observe

For a page you control, define a clear contract between the page and the capture job. For example, render a hidden or visible element such as <div id="capture-ready">ready</div> only after required asynchronous work has completed. Then verify whether your installed wkhtmltoimage build has an option that can wait for that condition. The CLI documentation lists JavaScript as enabled by default and documents JavaScript delay, scripts to run, and window-status waiting, but option behavior is version- and build-sensitive. See the wkhtmltoimage command reference and the Debian Bookworm wkhtmltoimage manual.

Check the binary you will actually call, not a different wkhtmltopdf installation or a version on another server. Run its version and help commands, confirm that the desired option appears for wkhtmltoimage, and test a small page whose readiness state is easy to observe. The project’s settings reference distinguishes image settings from page/object settings and notes that some settings do not apply to the image executable.

A historical issue reported that --javascript-delay and --window-status were ignored in wkhtmltoimage 0.12.2, with a fix associated with milestone 0.12.2.1. That is a reason to validate old or packaged builds, not proof that current builds share the bug. See issue 2142.

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

Invoke wkhtmltoimage safely from PHP

Use an argument array with PHP’s process API where available, or escape every individual shell argument if you use exec(). Never concatenate a URL supplied by a request directly into a shell command. Also validate the scheme and destination: shell escaping prevents shell syntax from being interpreted, but it does not make an unsafe URL an acceptable capture target.

PHP example using exec()

This example takes a URL and output path from application-controlled variables, escapes both for the shell, captures command output, and checks the exit status. Add the readiness option only after confirming it is supported by your installed executable and that the page sets the corresponding signal.

<?php
$url = 'https://example.com/report';
$outputPath = __DIR__ . '/report.png';
$binary = '/usr/bin/wkhtmltoimage';

// Restrict the destination scheme and validate the URL before execution.
if (!filter_var($url, FILTER_VALIDATE_URL) || !in_array(parse_url($url, PHP_URL_SCHEME), ['http', 'https'], true)) {
    throw new InvalidArgumentException('A valid HTTP or HTTPS URL is required.');
}

$args = [
    $binary,
    '--format', 'png',
    // Example only: verify this option against the installed wkhtmltoimage build.
    '--window-status', 'capture-ready',
    $url,
    $outputPath,
];
$command = implode(' ', array_map('escapeshellarg', $args));
$output = [];
$exitCode = 0;
exec($command . ' 2>&1', $output, $exitCode);

if ($exitCode !== 0) {
    throw new RuntimeException("wkhtmltoimage failed (exit $exitCode):n" . implode("n", $output));
}
if (!is_file($outputPath) || filesize($outputPath) === 0) {
    throw new RuntimeException('wkhtmltoimage exited successfully but did not produce a usable image.');
}

The executable path, format option, and wait behavior depend on how wkhtmltoimage is installed. Use an absolute binary path in a service environment so the PHP process does not accidentally call another version found through a different PATH. The PHP exec() manual describes collecting output lines and the return code; it also recommends escaping shell arguments.

When to use a delay, script, or window status

  • JavaScript delay: a fixed wait can cover a known, stable load time, but it may waste time on quick pages or finish too early on slow ones. It is not a completion guarantee.
  • Run script: a script can adjust page state or set a marker, if supported by the installed build and timed correctly relative to page loading.
  • Window status: useful only when the page sets the expected status value and the image executable honors the wait option.
  • JavaScript disabled: do not disable it if the target relies on scripts to render content or set readiness. JavaScript is documented as enabled by default in the command reference.

Do not assume these options work the same across versions, packaging choices, or builds. A minimal reproduction with the exact binary and target page is more informative than increasing a delay blindly.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Get the URL or readiness result back to PHP

If the page itself knows the final URL or completion value, explicitly send it to your application. One pattern is a same-origin endpoint that records a validated result, keyed to a capture job ID. The PHP worker can poll that record with a bounded timeout, then run the renderer against the intended URL. Another is to render a machine-readable marker in the DOM and wait for the renderer’s supported status signal. The right choice depends on whether the page can be changed and whether you need a value, a readiness event, or both.

  • Use a unique, short-lived capture/job identifier; do not accept arbitrary callback destinations from page input.
  • Validate reported URLs against an allowlist or destination policy. A renderer that can access internal network addresses can create server-side request risks.
  • Set a maximum wait and return a clear timeout error instead of leaving PHP workers blocked indefinitely.
  • Log the input URL, binary version, exit status, and concise renderer output for diagnosis; avoid logging secrets embedded in query strings or headers.

Troubleshoot common failures

Symptom Likely cause What to check or change
The image shows an alert, blank area, or incomplete content The alert is being treated as a readiness signal, or asynchronous content has not finished. Have the page expose a readiness marker after required content is rendered. Confirm JavaScript is enabled and test the exact build’s wait behavior.
A configured delay or window-status wait appears to be ignored The installed version/build may not support the option reliably, or the page never sets the expected status. Check wkhtmltoimage --version and its help output; reproduce with a minimal page and verify the signal spelling and timing. Consult the command and settings references above.
PHP reports an error but the image process output is unclear Standard error may not have been captured, the binary path may be wrong, or required libraries/options may be missing. Capture stderr with 2>&1, inspect the exit code, and run the same command under the same operating-system user as PHP using a known test URL.
The command succeeds but the file is empty or absent The output path may be unwritable, malformed, or different from the path the application checks. Use an absolute destination path, ensure the PHP worker can write to its directory, and verify the file exists and has nonzero size after exit.
PHP hangs while waiting for the renderer A page load or wait condition may never complete, or the process has no enforced time bound. Set an application-level timeout, terminate stuck jobs, and make the page’s ready signal deterministic. A fixed delay alone does not resolve an unbounded load.
Unexpected command behavior with a user-provided URL Unescaped shell input or an unsafe destination may be involved. Escape each shell argument, validate scheme and allowed host, and reject destinations that your service should not fetch. Shell escaping alone does not prevent server-side request forgery.

PHP’s shell_exec() manual says it returns command output as a string, while null can mean either no output or an error. If you need a process exit code, use exec() or another process API that reports status rather than interpreting a null output as a diagnosis.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When a hosted screenshot API is a better fit

If you cannot make the page expose readiness and the installed legacy renderer cannot reliably wait for it, a browser-based hosted screenshot service is another category to assess. Before sending a page to any external provider, check its privacy, data handling, authentication, and commercial terms. The available PHP SDK surfaced in this context documents waiting for a CSS selector, but that fact alone does not establish the service’s quality, price, or terms.

Or skip the browser setup

ScreenshotNeo offers a URL-to-image or PDF API and an MCP server for AI agents. One GET request can return a screenshot; the service accepts cookie/consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture, with each step independently switchable. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP tools include take_screenshot, get_page_info, and capture_pdf. See the ScreenshotNeo site and API documentation.

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.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/report -o shot.webp

ScreenshotNeo’s free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. You can try it with the free sign-up.

Frequently Asked Questions

Can PHP read the text inside a JavaScript alert from wkhtmltoimage?

Not automatically. The page needs to send the value to an application endpoint or expose it in a machine-readable way.

Does wkhtmltoimage always honor –window-status?

No universal guarantee follows from the option documentation. Verify the installed executable and test its behavior on the target page.

Can I use shell_exec() instead of exec()?

You can capture textual output with shell_exec(), but use an API that returns a process status when you need to distinguish success from failure.

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.