How to Capture FusionCharts with wkhtmltoimage
Capture FusionCharts reliably with wkhtmltoimage by waiting for renderComplete, configuring JavaScript timing, and troubleshooting blank charts.
Yes, wkhtmltoimage can capture a FusionCharts chart when the binary can run the page’s JavaScript and the capture waits until FusionCharts finishes drawing. FusionCharts renders charts with JavaScript using SVG and VML, while wkhtmltoimage uses Qt WebKit, which documents support for HTML, CSS, SVG, and JavaScript. This is compatibility by documented technology, not a guarantee for every chart type or packaged binary.
The reliable pattern is:
- Expose a page that loads FusionCharts, its data, fonts, and other assets.
- Listen for FusionCharts’
renderCompleteevent. - Set a unique
window.statusvalue from that callback. - Run
wkhtmltoimagewith--window-status, or use a deliberate--javascript-delayif status waiting is unavailable. - Set the viewport and output dimensions to include the chart, then inspect the image for clipping, missing fonts, or incomplete animation.
wkhtmltoimage’s project and manual document JavaScript execution, injected scripts, a delay, and waiting for a window-status value. Check the exact binary installed in your environment because distributions and versions differ. wkhtmltopdf project · wkhtmltoimage manual · Qt WebKit documentation
1. Create a capture page that signals readiness
Use a standalone HTML file first. Keeping the chart page deterministic makes it easier to separate FusionCharts problems from wkhtmltoimage problems.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>FusionCharts capture</title>
<style>
html, body { margin: 0; padding: 0; background: #fff; }
#chart-container { width: 1000px; height: 560px; }
</style>
<script src="https://cdn.fusioncharts.com/fusioncharts/latest/fusioncharts.js"></script>
<script src="https://cdn.fusioncharts.com/fusioncharts/latest/themes/fusioncharts.theme.fusion.js"></script>
</head>
<body>
<div id="chart-container"></div>
<script>
FusionCharts.ready(function () {
var chart = new FusionCharts({
type: 'column2d',
renderAt: 'chart-container',
width: '1000',
height: '560',
dataFormat: 'json',
dataSource: {
chart: {
caption: 'Monthly revenue',
xAxisName: 'Month',
yAxisName: 'Revenue',
theme: 'fusion',
animation: '0'
},
data: [
{ label: 'Jan', value: '42000' },
{ label: 'Feb', value: '51000' },
{ label: 'Mar', value: '47000' },
{ label: 'Apr', value: '62000' }
]
},
events: {
renderComplete: function () {
window.status = 'fusioncharts-render-complete';
}
}
});
chart.render();
});
</script>
</body>
</html>
The callback is the important part. A fixed delay alone can be too short on a busy machine and unnecessarily long on a fast one. Disable chart animation for deterministic captures unless the animation itself is part of what you need.
2. Capture with wkhtmltoimage
Wait for the render-complete marker
wkhtmltoimage \
--enable-javascript \
--window-status fusioncharts-render-complete \
--width 1000 \
--height 560 \
--quality 95 \
chart.html fusioncharts.webp
Confirm that your build accepts --window-status. Some packaged versions have had wait-option issues; a historical report concerned wkhtmltoimage 0.12.2 and identified a fix associated with 0.12.2.1. Treat that as a reason to check your installed version, not as a current universal defect. Historical issue #2142
Fallback: use a JavaScript delay
wkhtmltoimage \
--enable-javascript \
--javascript-delay 5000 \
--width 1000 \
--height 560 \
chart.html fusioncharts.png
Choose the delay from measured page behavior and leave headroom for slow data requests. A delay does not prove that the chart rendered; inspect the output and prefer the event marker when your binary supports it.
Inject a readiness script when you cannot edit the page
The manual documents post-load script injection. If the page exposes a chart instance or a DOM condition you can observe, inject a script that sets window.status after the condition. The exact injection syntax varies by build, so run wkhtmltoimage --extended-help and verify the option names in your binary before deploying.
3. Size the viewport and output correctly
- Chart dimensions: Set the FusionCharts
width/heightand the container CSS dimensions explicitly. - Viewport width: Use
--widthwide enough for labels, legends, and annotations. A narrow viewport can trigger responsive layout or clip the chart. - Page height: Set
--heightto the chart height plus any surrounding content. For a page with unknown height, render a larger canvas and crop afterward. - Output format: Use PNG for lossless text and thin lines, JPEG for smaller photographic pages, or WebP when your consumer supports it.
- Retina output: wkhtmltoimage itself does not provide a browser device-scale setting equivalent to modern Chromium. Increase CSS dimensions or post-process at a higher resolution when you need denser pixels.
If you need only the chart, give the chart container its own page. If you need page context, keep headings and explanatory text in the same document and size the capture for the complete layout.
4. Make external assets deterministic
The chart is not ready until its scripts, data, fonts, and images are available to the renderer. Check each dependency in the same network environment as the capture process.
- Use absolute HTTPS URLs for scripts and data.
- Make sure outbound DNS, TLS, and firewall rules allow every required host.
- Provide credentials with the page’s own request mechanism when data is private; do not assume wkhtmltoimage shares your browser session.
- Host critical JavaScript and font files locally when reproducibility matters.
- Use a consistent timezone and locale in generated data and labels.
- Wait for data fetching before constructing the chart, or set the status marker only from the final
renderCompletecallback.
5. Capture a chart element or crop the page
wkhtmltoimage captures a page rather than selecting a CSS node. To capture one chart from a larger application, use one of these approaches:
- Create a route that renders only the chart container.
- Use CSS to hide unrelated elements during a capture-specific request.
- Capture the full page and crop the resulting bitmap with an image tool.
A dedicated route is usually the most stable because it avoids scroll position, fixed headers, and responsive reflow.
6. FusionCharts native export versus a page screenshot
If the required artifact is only the chart, compare wkhtmltoimage with FusionCharts’ native export. FusionCharts documents PNG and JPG image export, plus SVG and PDF. Set the chart-level exportEnabled attribute to 1 to expose the export menu. Its API documents programmatic exportChart; call it after the chart has loaded and after renderComplete.
var chart = new FusionCharts({
type: 'column2d',
renderAt: 'chart-container',
width: '1000',
height: '560',
dataFormat: 'json',
dataSource: {
chart: {
exportEnabled: '1'
},
data: [{ label: 'Jan', value: '42000' }]
},
events: {
renderComplete: function () {
chart.exportChart({ exportFormat: 'png' });
}
}
});
FusionCharts describes client-side, server-side, and automatic export modes. Client-side export converts the chart SVG in the browser; server-side export sends chart data to an export service. Consider data privacy, network access, and the need for surrounding page layout before choosing. The documentation states that an active internet connection is required for the described export feature. FusionCharts export guide · FusionCharts API methods
7. Troubleshoot blank or incomplete charts
| Symptom | Likely cause | Fix |
|---|---|---|
| Blank white image | JavaScript is disabled, failed to load, or the capture starts too early. | Use --enable-javascript, inspect the page in a browser, and wait for renderComplete. |
| Chart container is present but has no series | Data request failed or credentials were unavailable. | Use absolute data URLs, allow the host through the firewall, and verify the request from the capture machine. |
| Only part of the chart appears | Viewport or page dimensions are smaller than the chart. | Set explicit container dimensions and increase --width/--height. |
| Fonts or icons differ | Remote font files were blocked or loaded after capture. | Make fonts reachable, self-host them, and signal readiness only after the chart has rendered. |
| Labels overlap | Responsive layout changed at the capture width. | Use the intended viewport width, set chart dimensions explicitly, or use a capture-only layout. |
--window-status never returns |
The callback did not run, the status string differs, or the binary does not honor the option. | Log the callback, use an exact marker, check --extended-help, and fall back to a tested delay. |
| Animated chart is inconsistent | The screenshot occurs during animation. | Disable animation or wait for the final render event and a stable data state. |
| Works locally but fails in production | Different binary, fonts, network policy, or locale. | Record the wkhtmltoimage version and run the same fixture in the deployment image. |
8. Performance, reliability, and cost considerations
- Performance: Reuse a small, local fixture for tests. Remote scripts, fonts, and data dominate startup time; reducing them makes delays shorter and outputs more repeatable.
- Reliability: Pin the wkhtmltoimage package used in production, record its version, and keep a golden chart image for visual regression checks. Test every chart type and data shape you depend on.
- Security: Treat chart URLs and injected JavaScript as untrusted input. Restrict outbound access when rendering user-supplied pages and avoid placing secrets in query strings or page source.
- Cost: Self-hosting wkhtmltoimage has no per-shot API charge, but you own browser processes, fonts, retries, isolation, and maintenance. Account for those operational costs when comparing with a capture API.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. It accepts the page URL and supports full-page capture, element selectors, custom CSS and JavaScript, waits for a selector, delay, or network idle, custom headers and cookies, blocking requests or resource types, viewport and device settings, dark mode, retina scale, and other capture controls. See the ScreenshotNeo documentation for parameter details.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const fs = require('node:fs');
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(`HTTP ${res.status}`);
fs.writeFileSync('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server lets Claude, Cursor, and other MCP clients use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Does wkhtmltoimage support every FusionCharts chart?
No compatibility matrix in the cited documentation covers every chart type, feature, or binary build. Test the exact chart, data, fonts, and installed version you will deploy.
Should I use SVG export instead of a screenshot?
Use native SVG, PNG, JPG, or PDF export when you need the chart alone. Use wkhtmltoimage when you need the chart together with page layout and surrounding content.
Why does a long delay still produce a blank image?
A delay cannot repair a failed script, blocked request, unsupported API, or incorrect page URL. Open the same page in the capture environment and inspect network and JavaScript errors.
Can I capture private FusionCharts data?
Yes, if the page can authenticate from the rendering environment. Configure the page or capture request with the required headers and cookies, and avoid exposing credentials in public URLs.


