Skip to main content

Clean, deterministic, browser-free renderer for .excalidraw files (PNG/SVG/PDF/JPEG).

Project description

excalidraw-render

CI PyPI Python License: MIT Mentioned in awesome-svg

Clean, deterministic, browser-free renderer for .excalidraw files. Pure Python + cairosvg. No Node, no headless browser, no node-canvas.

hero

pip install excalidraw-render

excalidraw-render diagram.excalidraw                    # → diagram.png
excalidraw-render diagram.excalidraw -f svg             # → diagram.svg
excalidraw-render diagram.excalidraw -f pdf             # → diagram.pdf (vector)
excalidraw-render diagram.excalidraw --width 1200       # PNG at 1200px wide
excalidraw-render ./docs/                               # batch: every .excalidraw → .png

Why this exists

The Excalidraw ecosystem's existing exporters either need Node + node-canvas (excalidraw_export) or a headless browser running React (@excalidraw/excalidraw). Both are heavy, fragile in CI, and slow to start.

excalidraw-render is Python + cairosvg. Single-digit-megabyte install, instant startup, no native canvas libs, no Chromium. Useful for:

  • Static-site generators (Hugo, MkDocs, Sphinx) baking .excalidraw to PNG at build time
  • CI/screenshot pipelines where pulling Chromium is overkill
  • Doc + slide generators that want predictable, deterministic vector output
  • Terminal viewers (Kitty, iTerm2, Sixel) — on the roadmap

Trade-off: no hand-drawn style

Excalidraw's signature squiggly look comes from roughjs, a JavaScript library with no native Python port. excalidraw-render produces clean vector output instead. This is a deliberate trade-off — clean output is what most doc / slide / report pipelines actually want, and skipping roughjs removes the heaviest dependency.

A pure-Python roughjs port (pyroughjs) is on the roadmap. Until then, if you need the hand-drawn look, use Excalidraw's official export.

Comparison

excalidraw-render excalidraw_export @excalidraw/excalidraw
Language Python Node React + Node
Hand-drawn (roughjs) No (planned) Yes Yes
PNG output Yes via rsvg-convert Yes
SVG output Yes Yes Yes
PDF output Yes via rsvg-convert No
Headless browser needed No No Yes
Native canvas / image libs No Yes (node-canvas) No
Install size ~10 MB ~150 MB Depends
Batch / watch mode Batch ✓ / watch planned No No
Terminal protocols Planned (iTerm / Kitty / Sixel) No No

Install

pip install excalidraw-render

On Linux you may need libcairo2:

sudo apt-get install libcairo2          # Debian / Ubuntu
sudo dnf install cairo                  # Fedora
sudo pacman -S cairo                    # Arch

On macOS, Cairo is typically already present via Homebrew. If not:

brew install cairo

Usage

CLI

# Single file → PNG next to source
excalidraw-render diagram.excalidraw

# Specify output + format
excalidraw-render diagram.excalidraw -o /tmp/out.svg -f svg

# Higher resolution PNG
excalidraw-render diagram.excalidraw --width 1600

# Or scale instead of fixed width
excalidraw-render diagram.excalidraw --scale 2.0

# Transparent background
excalidraw-render diagram.excalidraw --no-background

# Vector PDF / compressed JPEG
excalidraw-render diagram.excalidraw -f pdf
excalidraw-render diagram.excalidraw -f jpg --quality 85

# Batch mode: every .excalidraw in a directory
excalidraw-render ./docs/diagrams/ -o ./public/diagrams/

Python API

from excalidraw_render.render import load_scene, render_svg, render_png, render_pdf, render_jpg

scene = load_scene("diagram.excalidraw")

# SVG as a string
svg = render_svg(scene)

# PNG to a file
render_png(scene, "diagram.png", width=1200)

# Vector PDF / JPEG
render_pdf(scene, "diagram.pdf")
render_jpg(scene, "diagram.jpg", quality=85)

# PNG to a binary stream
import io
buf = io.BytesIO()
render_png(scene, buf, scale=2.0)

What's supported

Formats: PNG, SVG, vector PDF, JPEG. Elements: rectangle, ellipse, diamond, arrow, line, text, freedraw, image, frame. Arrowheads: arrow, triangle, triangle_outline, bar, dot, diamond, diamond_outline, crowfoot_one, crowfoot_many, crowfoot_one_or_many. Styling: stroke color/width, fill color, stroke style (solid/dashed/dotted), opacity, per-element rotation. Text: multi-line, text-align (left/center/right), vertical-align (top/middle/bottom), Excalidraw font families mapped to web-safe fonts. Container-bound text (labels inside rectangles, ellipses, diamonds) is positioned with Excalidraw's own padding-aware layout algorithm and rotates with its container. Freedraw: smooth path via Catmull-Rom → cubic Bezier conversion. Image: embedded raster data from the scene's files dict. Frame: dashed boundary box with optional label.

Coverage matrix: docs/elements.md.

What's not supported yet

Documented in CHANGELOG.md. Highlights:

  • Roughness / hand-drawn look (needs roughjs port)
  • Hachure / cross-hatch / zigzag / dots fill patterns (currently fall back to solid)
  • Watch mode (coming in 0.3.0)
  • Terminal output (iTerm / Kitty / Sixel)
  • Markdown preprocessor subcommand

Contributing

This is pre-alpha and breaking changes between minor versions are likely until v1.0. Issues, ideas, and PRs welcome — please file at https://github.com/shivama205/excalidraw-render/issues.

Local dev:

git clone https://github.com/shivama205/excalidraw-render
cd excalidraw-render
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pytest
.venv/bin/ruff check src tests
.venv/bin/mypy src

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

excalidraw_render-0.2.0.tar.gz (52.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

excalidraw_render-0.2.0-py3-none-any.whl (22.8 kB view details)

Uploaded Python 3

File details

Details for the file excalidraw_render-0.2.0.tar.gz.

File metadata

  • Download URL: excalidraw_render-0.2.0.tar.gz
  • Upload date:
  • Size: 52.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for excalidraw_render-0.2.0.tar.gz
Algorithm Hash digest
SHA256 af33b908943c3290d5470f78f5248c28e8f546a83700f3c0e88b424f88f67c19
MD5 0d3df4952208e71644b5315af8eb86dc
BLAKE2b-256 3e2536fdf79d6a6ae15f302e0efb89e41ecd2dbd5ad3f1c95ce9846b54ae2900

See more details on using hashes here.

File details

Details for the file excalidraw_render-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for excalidraw_render-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 15fa6fac7472cbcdb4c9cabcab7cae7bb1ef5a73e413ad98ab7f02997d61fe78
MD5 82146bbd28a49fb7e458bf5c6fadc7e3
BLAKE2b-256 e2ade339428bf7c653a41b37a6de629ac1a74d1834fa65892b31b19bdc7292a6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page