Mirage 🪄
Ultra-lightweight, browser-less static image exporter for Plotly in Python.
Zero Chrome. Zero Chromium. Zero Playwright. 100% Vector & Raster Fidelity.
Why Mirage?
Historically, exporting static images (.svg, .png, .jpg, .webp) from Plotly in Python required Kaleido:
- Kaleido v0.1/v0.2 bundled an unmaintained, monolithic Chromium binary that frequently deadlocked, crashed on ARM64 / Apple Silicon, or failed on modern Linux distributions.
- Kaleido v1+ transitioned to requiring a full installation of Google Chrome or downloading ~150MB–300MB Playwright browser binaries.
- In Docker containers, AWS Lambda, lightweight Linux (Alpine), and CI/CD pipelines, installing Chrome pulls in hundreds of megabytes of system packages (
libglib,libgtk,libnss,Xvfb), making deployments bloated and fragile.
Mirage eliminates all browser dependencies entirely. It executes Plotly's official SVG engine inside an embedded QuickJS JavaScript runtime, measures fonts using Pillow, and rasterizes pixel-perfect images via high-performance Rust (resvg-py).
How Mirage Works
Plotly Python figures are JSON specifications. The actual layout math, coordinate scaling, D3 curves, and SVG construction live inside plotly.js.
┌───────────────────────────────┐
│ fig = go.Figure(...) │
└──────────────┬────────────────┘
│ fig.to_dict()
▼
┌────────────────────────────────────────────────────────┐
│ Mirage Engine (Embedded QuickJS Runtime) │
│ │
│ 1. Micro-DOM (~400 lines JS): │
│ - Minimal SVG/HTML element tree │
│ - D3 selector & attribute managers │
│ 2. Pillow Font Engine: │
│ - Answers getBBox() text measurements via PIL │
│ 3. Comprehensive 2D Plotly Engine: │
│ - Computes layout & renders 29 pure-vector traces │
│ 4. Extracts clean, standalone <svg> │
└──────────────────────────────┬─────────────────────────┘
│ Pure SVG Vector Output
▼
┌───────────────────────────────┐
│ resvg-py (Rust Wheel) │
│ Instant SVG ➔ PNG / JPEG │
└───────────────────────────────┘
- Embedded QuickJS Engine: Runs the official
plotly.jsbundle inside an embedded C JavaScript runtime (~1.8 MB bundle). - Micro-DOM: Implements the precise subset of DOM and SVG APIs that D3 and Plotly require to build the SVG scene graph.
- Pillow Font Engine: When Plotly asks for text bounding boxes (
getBBox()), Mirage queries Python'sPIL.ImageFontto measure text dimensions, ensuring clean margins, titles, and tick placements without overlaps. - Rust Vector Rasterization (
resvg-py): Converts SVG directly into crisp PNG, JPEG, or WEBP bytes in milliseconds with zero C++ system dependencies.
Installation
pip install plotly-mirage
Or install the latest development version directly from GitHub:
pip install git+https://github.com/ProfLear/mirage.git
Works out-of-the-box on macOS (Intel & Apple Silicon), Linux (Ubuntu, Debian, Fedora, Alpine/musl), and Windows 10/11.
Quickstart
1. Direct API
import plotly.express as px
import mirage
fig = px.scatter(x=[1, 2, 3, 4], y=[10, 11, 12, 13], title="Sales Growth")
# Export to SVG string or file
svg_str = mirage.to_svg(fig)
mirage.write_image(fig, "sales.svg")
# Export to PNG / JPEG / WEBP
png_bytes = mirage.to_image(fig, format="png", scale=2.0)
mirage.write_image(fig, "sales.png", scale=2.0)
mirage.write_image(fig, "sales.jpg")
mirage.write_image(fig, "sales.webp")
2. Drop-in Replacement for Kaleido (mirage.register())
If you have existing code using Plotly's native fig.write_image() or fig.to_image():
import plotly.express as px
import mirage
# Patch Plotly to use Mirage instead of Kaleido
mirage.register()
fig = px.bar(x=["A", "B", "C"], y=[1, 3, 2])
# These now run instantly via Mirage without Chrome or Kaleido!
fig.write_image("chart.png")
fig.write_image("chart.svg")
png_data = fig.to_image(format="png")
Performance Benchmarks across 25 Chart Types
Below is an empirical benchmark comparing Mirage against Kaleido across 25 standard Plotly chart types (tested on Apple Silicon, measuring average per-image export latency after engine warmup):
| Category | Chart Type | Mirage Latency | Kaleido Latency | Speedup |
|---|---|---|---|---|
| Core Cartesian | Scatter & Line Chart | 55.9 ms | 1074.0 ms | 19.2x |
| Core Cartesian | Grouped Bar Chart | 51.2 ms | 1023.1 ms | 20.0x |
| Core Cartesian | Donut / Pie Chart | 51.4 ms | 1147.8 ms | 22.3x |
| Core Cartesian | Box Plot | 56.2 ms | 1171.2 ms | 20.8x |
| Core Cartesian | Violin Plot | 54.4 ms | 1165.4 ms | 21.4x |
| Core Cartesian | Frequency Histogram | 39.9 ms | 1098.7 ms | 27.5x |
| Core Cartesian | 2D Density Histogram | 63.5 ms | 1092.7 ms | 17.2x |
| Core Cartesian | 2D Contour Plot | 74.1 ms | 1097.0 ms | 14.8x |
| Core Cartesian | Performance Heatmap | 58.2 ms | 1078.1 ms | 18.5x |
| Core Cartesian | Ternary Phase Diagram | 58.8 ms | 1071.9 ms | 18.2x |
| Financial & Business | Candlestick Stock Chart | 85.2 ms | 1126.1 ms | 13.2x |
| Financial & Business | OHLC Financial Chart | 77.9 ms | 1096.7 ms | 14.1x |
| Financial & Business | Waterfall Profit & Loss | 42.4 ms | 1075.7 ms | 25.4x |
| Financial & Business | Sales Conversion Funnel | 59.7 ms | 1116.3 ms | 18.7x |
| Financial & Business | Funnel Area Analysis | 45.8 ms | 1094.3 ms | 23.9x |
| Financial & Business | KPI Performance Indicator | 37.8 ms | 1033.5 ms | 27.3x |
| Hierarchical | Market Cap Treemap | 41.1 ms | 1138.6 ms | 27.7x |
| Hierarchical | Global Sunburst Hierarchy | 44.2 ms | 1116.2 ms | 25.3x |
| Hierarchical | Icicle Partition Chart | 35.2 ms | 1095.0 ms | 31.1x |
| Radial & Polar | Radar Performance Comparison | 62.5 ms | 1028.6 ms | 16.5x |
| Radial & Polar | Polar Wind Rose | 42.8 ms | 1150.5 ms | 26.9x |
| Specialized Diagrams | Energy Flow Sankey Diagram | 32.5 ms | 1535.5 ms | 47.3x |
| Specialized Diagrams | Parallel Categories Diagram | 49.7 ms | 1166.3 ms | 23.5x |
| Specialized Diagrams | Formatted Data Table | 40.7 ms | 1073.1 ms | 26.3x |
| Specialized Diagrams | Carpet Coordinate Plot | 58.9 ms | 1136.5 ms | 19.3x |
Overall Summary: Mirage delivers a 20x to 65x speedup across all chart types while using ~25x less disk space and requiring zero browser processes.
Visual Fidelity & Side-by-Side Comparisons
Every plot exported by Mirage matches the exact visual output, layout geometry, font proportions, and colors generated by Plotly and Kaleido.
Core Cartesian
Scatter & Line Chart (Mirage: 55.9ms | Kaleido: 1074.0ms)
Grouped Bar Chart (Mirage: 51.2ms | Kaleido: 1023.1ms)
Donut / Pie Chart (Mirage: 51.4ms | Kaleido: 1147.8ms)
Box Plot (Mirage: 56.2ms | Kaleido: 1171.2ms)
Violin Plot (Mirage: 54.4ms | Kaleido: 1165.4ms)
Frequency Histogram (Mirage: 39.9ms | Kaleido: 1098.7ms)
2D Density Histogram (Mirage: 63.5ms | Kaleido: 1092.7ms)
2D Contour Plot (Mirage: 74.1ms | Kaleido: 1097.0ms)
Performance Heatmap (Mirage: 58.2ms | Kaleido: 1078.1ms)
Ternary Phase Diagram (Mirage: 58.8ms | Kaleido: 1071.9ms)
Financial & Business
Candlestick Stock Chart (Mirage: 85.2ms | Kaleido: 1126.1ms)
OHLC Financial Chart (Mirage: 77.9ms | Kaleido: 1096.7ms)
Waterfall Profit & Loss (Mirage: 42.4ms | Kaleido: 1075.7ms)
Sales Conversion Funnel (Mirage: 59.7ms | Kaleido: 1116.3ms)
Funnel Area Analysis (Mirage: 45.8ms | Kaleido: 1094.3ms)
KPI Performance Indicator (Mirage: 37.8ms | Kaleido: 1033.5ms)
Hierarchical
Market Cap Treemap (Mirage: 41.1ms | Kaleido: 1138.6ms)
Global Sunburst Hierarchy (Mirage: 44.2ms | Kaleido: 1116.2ms)
Icicle Partition Chart (Mirage: 35.2ms | Kaleido: 1095.0ms)
Radial & Polar
Radar Performance Comparison (Mirage: 62.5ms | Kaleido: 1028.6ms)
Polar Wind Rose (Mirage: 42.8ms | Kaleido: 1150.5ms)
Specialized Diagrams
Energy Flow Sankey Diagram (Mirage: 32.5ms | Kaleido: 1535.5ms)
Parallel Categories Diagram (Mirage: 49.7ms | Kaleido: 1166.3ms)
Formatted Data Table (Mirage: 40.7ms | Kaleido: 1073.1ms)
Carpet Coordinate Plot (Mirage: 58.9ms | Kaleido: 1136.5ms)
Supported Plotly Traces (28 Total)
Mirage includes full pure-vector support for all 28 non-WebGL Plotly trace types:
| Category | Supported Traces |
|---|---|
| Core Cartesian | scatter (lines, markers, area, text, ecdf), bar (vertical, horizontal, stacked, grouped, timeline), pie (donut), box, violin, histogram, histogram2d, histogram2dcontour, contour, heatmap, scatterternary, image |
| Financial & Business | candlestick, ohlc, waterfall, funnel, funnelarea, indicator (gauges, KPI big numbers) |
| Hierarchical Partitions | treemap, sunburst, icicle |
| Radial / Polar | scatterpolar (radar/spider), barpolar |
| Specialized Diagrams & Tables | sankey, parcats (parallel categories), table, carpet, scattercarpet, contourcarpet |
(Note: WebGL traces like scatter3d, surface, mesh3d, and parcoords render via GPU shader canvases and are not pure vector SVG).
License
MIT License. Copyright (c) 2026 Benjamin Lear.
Metadata
Release files for plotly-mirage 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| plotly_mirage-0.2.0.tar.gz | 2.3 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| plotly_mirage-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.3 MB
Release files / plotly_mirage-0.2.0.tar.gz
| Download URL | plotly_mirage-0.2.0.tar.gz |
|---|---|
| Size | 2.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1a91caa91770b2c91070f7d202ae7b8866e91f51939464185e057b29fccff48a
|
|
BLAKE2b-256 checksum How to use checksums |
b8c3298322b7275489744c71af78a50f131148658f16dd4469e3b9cb61877d25
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / plotly_mirage-0.2.0-py3-none-any.whl
| Download URL | plotly_mirage-0.2.0-py3-none-any.whl |
|---|---|
| Size | 1.1 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5a9e7ef21e1e883f0cdf65d0add43f733e9e674c94997531b76bdc585234a781
|
|
BLAKE2b-256 checksum How to use checksums |
4c1d1f6b75f23b64175f59d5c38d736ad206e2184c7b2cb6651f1569b4180f59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|