Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsUse wkhtmltoimage’s JavaScript wait controls, not just its JavaScript switch. JavaScript is enabled by default in the documented renderer. For asynchronous page setup, add a fixed --javascript-delay in milliseconds or have the page set window.status to a value passed with --window-status. IMGKit is only the Ruby wrapper; the wkhtmltoimage executable it invokes determines the actual rendering behavior.
This guide shows the command-line, IMGKit, and C-binding configurations, then provides a diagnostic sequence for pages that still capture too early.
How the rendering layers fit together
IMGKit converts Ruby calls into wkhtmltoimage options. The binary loads the HTML, runs its JavaScript, waits according to its settings, and writes the image. Consequently, changing Ruby code cannot fix a missing or unexpected renderer binary. First establish exactly which executable IMGKit runs and inspect that executable’s version and help output.
IMGKit’s README says to specify the binary when it is not in the expected location and documents passing JavaScript files with kit.javascripts. Its options are passed through to wkhtmltoimage, although the exact Ruby syntax for individual options can differ between IMGKit releases. Confirm the interface in the version installed in your application.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →#1 Best Overall
Choose a JavaScript readiness strategy
| Method | How it works | Best use | Trade-off |
|---|---|---|---|
--javascript-delay <msec> |
Waits a fixed period after page loading before capture. | Pages with a predictable startup time that you cannot modify. | Too short produces an incomplete image; too long wastes time. |
--window-status <value> |
Waits until the page sets window.status to the exact value. |
Pages you control, where an application can signal completion. | Requires reliable page code and matching spelling and case. |
| Renderer diagnostics | --debug-javascript reports script errors; --run-script runs supplied script code. |
Separating “script did not run” from “capture happened too soon.” | Diagnostics do not add waiting by themselves. |
These controls address timing. They do not guarantee that every modern browser API, framework, font, codec, or network behavior is supported by your particular wkhtmltoimage build.
Command-line configuration
Fixed delay
Enable JavaScript explicitly and wait 1.5 seconds:
wkhtmltoimage --enable-javascript --javascript-delay 1500 input.html output.png
1500 is only an example. Measure the page’s normal startup time and add margin for the slowest environment you support. The option is documented in milliseconds.
Readiness signal with window.status
Have the page signal completion after its asynchronous work has actually updated the DOM:
<script>
(async function () {
await loadDashboardData();
renderDashboard();
window.status = 'rendered';
})();
</script>
Then wait for that exact value:
wkhtmltoimage --enable-javascript --window-status rendered input.html output.png
The string must match exactly. Set it only after data, templates, and visual changes needed in the screenshot are complete. If a promise can reject, add error handling that records a useful diagnostic rather than silently leaving the renderer waiting.
Free tools Windows power users keep installed
One-click scans. No signup required.
Use a minimal local test page
Before debugging a large application, isolate the timing behavior:
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
<!doctype html>
<html><body>
<div id="result">Starting</div>
<script>
setTimeout(function () {
document.getElementById('result').textContent = 'Ready';
window.status = 'rendered';
}, 500);
</script>
</body></html>
Capture it with --window-status rendered. If “Ready” appears, the renderer’s basic JavaScript and status wait work; investigate your application’s network requests or framework timing next.
Configure IMGKit in Ruby
IMGKit’s documented JavaScript-file input is exposed through kit.javascripts:
require 'imgkit'
kit = IMGKit.new('
Use the option names accepted by your IMGKit release. If a release does not accept the Ruby-style keys shown above, pass the equivalent wkhtmltoimage arguments through that release’s documented options interface. The important renderer settings are --enable-javascript, --javascript-delay, and --window-status.
For a status-based capture, replace the delay with the matching status option in your IMGKit configuration, and ensure the page assigns window.status = 'rendered'. Because IMGKit and wkhtmltoimage are separate layers, log the final command or inspect IMGKit’s configuration when diagnosing an option that appears to be ignored.
Verify the executable IMGKit actually uses
- Locate the wkhtmltoimage binary configured for your process, including any explicit IMGKit binary path.
- Run that exact path with its version command and
--help. - Confirm that the help output lists JavaScript, delay, window-status, and diagnostic options.
- Run the minimal local test page with the same user account, working directory, and environment as the application.
- Only then tune the production page’s delay or readiness signal.
A historical issue reported that --javascript-delay and --window-status appeared ineffective; that report records a fix milestone of 0.12.2.1. This is a version-specific historical report, not proof that every current or downstream package behaves identically. Treat the installed binary, not the gem version alone, as the thing to validate.
Rank #3
Diagnose pages that still capture too early
JavaScript was disabled upstream
Look for an explicit --disable-javascript in IMGKit configuration, a wrapper, a container entrypoint, or a shared options hash. The documented default is enabled, but an explicit disable wins. Add --enable-javascript and retest.
The delay is shorter than the real work
Network latency, slow APIs, timers, and client-side rendering can exceed a fixed delay. Increase it temporarily to prove the diagnosis, then prefer a status signal that is set after the final DOM update. A delay cannot know whether a request has failed or whether a late component is still rendering.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →The status value never matches
Check spelling, capitalization, and assignment timing. The page must set the exact value requested by --window-status. If an exception occurs before that line, the renderer may wait indefinitely or finish according to build-specific behavior. Add visible error output and test the page without minification.
Scripts load from an inaccessible origin
Run the renderer under the same network, proxy, DNS, certificate, and authentication conditions as production. A browser session that works interactively may not be available to a headless process. If the page needs a local script, add it with IMGKit’s kit.javascripts mechanism or make the URL reachable to the renderer.
It is a renderer capability issue, not timing
If a long delay still produces missing controls, inspect JavaScript errors with --debug-javascript. Test a stripped-down page and remove framework features one at a time. “JavaScript enabled” does not mean that all APIs used by a modern application are implemented by every wkhtmltoimage build.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
IMGKit and the binary disagree
Inspect the generated options and the executable path. A system package, container image, and developer workstation can contain different builds. Reproduce with a direct CLI invocation before changing Ruby code.
C-binding settings
The wkhtmltoimage C settings expose the same concepts under different names. web.enableJavascript controls whether JavaScript runs. load.jsdelay specifies the post-load wait; the documented behavior allows the wait to end when the delay expires or when JavaScript calls window.print(). This interface is useful when your application embeds the renderer directly rather than invoking the CLI or IMGKit.
Use the binding’s own versioned API documentation for object creation, error handling, and units. Do not assume a Ruby option name maps directly to a C structure field.
Reliability and performance guidance
- Prefer deterministic readiness. A status signal usually avoids both premature captures and unnecessary waiting, provided your page controls all required asynchronous work.
- Bound your waits. A page that never signals readiness needs an operational timeout around the rendering process so a stuck request cannot consume workers forever.
- Keep capture pages small. Remove unrelated third-party widgets and requests where possible; they add failure and timing variability.
- Record renderer identity. Log the binary path, version, selected delay or status value, URL, and failure reason for reproducibility.
- Test cold and warm loads. Cached scripts and API responses can hide a race that appears on a first request or under load.
Or skip the browser setup
If maintaining a wkhtmltoimage binary, JavaScript timing, and compatibility is more work than your project needs, ScreenshotNeo provides a website screenshot API and MCP server. A single request returns PNG, JPEG, WebP, or PDF; use the API options to wait for a selector, delay, or network idle when those controls fit your page.
cURL (see the ScreenshotNeo documentation):
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)
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}`);
Before capture, ScreenshotNeo can accept consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. 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 server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots.
Create a free ScreenshotNeo account to try the API with 1,000 screenshots per month and no card.
Best Value
Frequently Asked Questions
Should I always use a fixed delay instead of window.status?
No. Use a fixed delay when you cannot change the page and its load time is predictable. Use window.status when you control the page and can signal completion after the final asynchronous update.
Does IMGKit execute JavaScript itself?
No. IMGKit is the Ruby wrapper; the wkhtmltoimage executable performs rendering and applies the JavaScript options.
What does window.print() have to do with the C API?
The documented C setting for load.jsdelay allows the post-load wait to end when the delay expires or JavaScript calls window.print(). This is separate from the CLI window-status mechanism.
Why does a screenshot remain incomplete after increasing the delay?
The cause may be a disabled script, a failed network request, an exception, an unmatched status value, or an API unsupported by the installed renderer. Use a minimal page and --debug-javascript to identify which category applies.
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.

