Back to Blog
Python

Python Plotly: Save HTML and Export Images

Save Plotly figures as interactive HTML files and export static images in Python using write_html, write_image, and kaleido.

plotlydata visualizationhtml exportimage exportkaleido
A Plotly chart displayed both as an interactive HTML page and as a static PNG image, illustrating the two export methods.

Plotly provides two separate paths for saving a figure after you create it. write_html saves an interactive HTML document, while write_image exports a static image such as PNG, JPEG, or SVG. The image export depends on the kaleido package, so the setup is slightly different from HTML export.

Saving a Plotly Figure as HTML

With its default settings, write_html writes a complete, self-contained HTML document. Plotly.js is embedded in the file, so the chart works offline and can be shared without extra dependencies.

import plotly.graph_objects as go fig = go.Figure(data=go.Scatter(x=[1, 2, 3], y=[4, 5, 6])) fig.write_html('chart.html')

To embed a chart in an existing page instead, set full_html=False to write only the <div> and <script> tags. The include_plotlyjs parameter controls how Plotly.js is loaded: True embeds it in the output, 'cdn' loads it from a CDN, and False leaves it out if you want to include the library once in your own page.

fig.write_html('chart-embed.html', full_html=False, include_plotlyjs='cdn')

A CDN reference means the embedded chart will need internet access to load Plotly.js. For a standalone export, the default full_html=True is usually sufficient.

Exporting a Plotly Figure as a Static Image

Use write_image to export a figure as an image. The method depends on kaleido, so you need to install it in the same Python environment where your script runs:

pip install kaleido
fig.write_image('chart.png')

With recent versions of Plotly and kaleido, write_image supports the same formats as the format parameter: png, jpeg, webp, svg, pdf, and eps. For raster formats, use scale to control resolution. scale multiplies the pixel dimensions, so scale=2 makes the output width and height twice the values defined by width and height.

Choosing Image Formats and Controlling Output Size

The file format affects both quality and size. PNG is lossless and supports transparency. JPEG is lossy and smaller, but it does not support transparency. SVG is a vector format and remains sharp when scaled, which is useful for diagrams viewed at different zoom levels.

You can set output dimensions in pixel units with width and height:

fig.write_image('chart.png', width=800, height=600, scale=2)

This example creates a 1600×1200 PNG because scale=2 doubles the requested 800×600 dimensions. For PDF export, width and height control the output page size. For SVG, they define the initial viewport, while the vector coordinates remain resolution-independent.

Multiple Figures and Subplots

To export several figures, loop over them and call write_html or write_image for each. If you use Plotly's make_subplots, the resulting figure contains multiple subplots, and exporting it creates a single HTML page or image for the whole grid.

import plotly.subplots as sp fig = sp.make_subplots(rows=2, cols=1) fig.add_trace(go.Scatter(x=[1, 2, 3], y=[4, 5, 6]), row=1, col=1) fig.add_trace(go.Bar(x=['a', 'b', 'c'], y=[1, 2, 3]), row=2, col=1) fig.write_html('subplots.html') fig.write_image('subplots.png')

If you need each subplot as a separate image, create separate figures for each trace group. For large batch exports, keep memory usage in mind: holding many large figure objects in memory while kaleido runs as a separate process can add up. Reuse or release figure references after exporting.

Runtime and Operational Considerations

Because write_image runs through kaleido, which uses a separate Chromium subprocess, starting an export can add overhead beyond a simple HTML write. Install kaleido when you build a deployment image so it is available in the final environment rather than installing it only at runtime.

In serverless or containerized environments, kaleido may need system libraries required by headless Chromium. If an export fails with a missing shared library, install the equivalent Chromium dependencies for your base image. The exact package names vary by Linux distribution, so check the process output for the library name.

Image export is also more resource-intensive than HTML export. For concurrent or batch workloads, use a process pool or a task queue. Calling write_image from many threads at once can saturate CPU and memory without giving a throughput benefit.

Troubleshooting Common Export Failures

The most common failure is missing kaleido. Plotly raises an error similar to:

ValueError: Image export requires the kaleido package.

Install it with pip install kaleido in the same environment that runs the script.

If you get a non-zero exit code or a message about a missing shared object, the environment is missing system libraries for Chromium. On Debian-based systems, install packages such as libnss3, libatk-bridge2.0-0, and libx11-xcb1. The exact set depends on your base image, so match it to the library named in the error.

If you need a transparent background, use PNG or SVG because JPEG does not support transparency. If an SVG export looks blurry, confirm you are actually saving an .svg file rather than a raster format. SVG is vector output and should remain sharp at any zoom level.

Finally, if the exported image is blank or cropped, check that the figure has at least one trace and that the layout margins are not set to zero. An empty figure renders as an empty canvas, which can look like a rendering failure.

Save Plotly Figures as HTML and Export Images in Python | RYUSLOG DEV