Exporting Vizly Charts to HTML, JSON, and Images
Vizly charts export in three forms: self-contained HTML for sharing and embedding, a plain JSON option for APIs and SPAs, and images rendered from the browser for reports and slides. Each export path serves a different need.
Self-contained HTML
to_html() returns a full HTML document with vendored ECharts inlined. It works offline, has no CDN dependency, and opens in any browser.
import vizly as vz
chart = vz.bar(data, x="region", y="sales", title="Sales")
html = chart.to_html()
# Or write it to a file directly
chart.render("sales.html")
JSON option dicts
to_option() returns the resolved ECharts option as a plain dict. This is the format for APIs, SPAs, and AI agents that render charts themselves.
option = chart.to_option() # dict
json_string = chart.to_json() # JSON string, optionally indented
json_string = chart.to_json(indent=2)
from_option() does the reverse: it wraps an existing ECharts option dict as a Vizly chart so you can theme and export it through the same pipeline.
chart = vz.from_option({...})
Browser-rendered images
Images come from the browser that already rendered the chart, via ECharts getDataURL. Vizly does not ship a server-side Chromium. After a chart is embedded, grab the chart id and call the image helpers.
const id = document.querySelector(".vizly-chart").id;
window.__vizly[id].toDataURL({ type: "png", pixelRatio: 2 });
window.__vizly[id].downloadImage("chart.png");
You can also enable the built-in toolbox save button so users export without any JavaScript.
chart.merge_option({
"toolbox": {
"feature": {
"saveAsImage": {"type": "png"},
},
},
})
Headless batch export
For scheduled reports and automated pipelines, render the HTML in headless Chromium. Vizly does not bundle a browser, so use Playwright (or similar) on the output of chart.to_html().
import asyncio
from playwright.async_api import async_playwright
async def export_png(chart, path: str) -> None:
html = chart.to_html()
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.set_content(html)
await page.wait_for_selector(".vizly-chart")
await page.locator(".vizly-chart").screenshot(path=path)
await browser.close()
asyncio.run(export_png(chart, "report.png"))
Choosing an export path
| Need | Export |
|---|---|
| Share a file or open in a browser | chart.render("out.html") |
| Embed in a page or app | chart.to_html() / chart.to_html(fragment=True) |
| Send options to an API or SPA | chart.to_option() / chart.to_json() |
| PNG, JPEG, or SVG for reports | Browser toDataURL / downloadImage, or toolbox saveAsImage |
| Scheduled batch images | Playwright on chart.to_html() |
Tips
| Tip | Detail |
|---|---|
| No server-side rendering | Vizly does not bundle Chromium. Browser export uses the page that already rendered the chart. |
| Screenshots need a wait | Wait for the .vizly-chart element before screenshotting so GL and animations settle. |
| JSON skips GeoJSON | to_option() returns the ECharts option only. Maps register GeoJSON in the HTML path. |
| Emails like images | For email reports, render PNG via Playwright rather than embedding live HTML. |