CairoSVG

Renders SVG documents to PDF, PNG, PostScript, and EPS using Cairo, with a small Python API and command-line tool.

Library
PyPI
v2.9.0
951stars
LGPL-3.0-or-later

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
58/100Fair
Development Activity28
Maintenance36
Community80
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
68/100Good
Architecture68
Code Quality72
Innovation82
Learning Curve50

CairoSVG is a Python library that converts SVG documents into PDF, PNG, PostScript, and EPS output using the Cairo 2D graphics library as its rendering backend. It exposes a small set of functions — svg2pdf, svg2png, svg2ps, svg2eps, and svg2svg — that accept an SVG bytestring, file object, or URL and write the rendered result to a file or return it as bytes, alongside a cairosvg command-line tool for one-off conversions.

Under the hood it parses the SVG/XML tree itself and walks it node-by-node, dispatching each tag (path, rect, circle, text, gradients, filters, masks, clipping paths, use/symbol references) to a dedicated drawing function that issues the corresponding Cairo drawing calls. This makes it a common rendering backend for other Python projects that need to turn vector graphics into raster or print-ready output, most notably WeasyPrint, without requiring a browser engine or system SVG renderer.

What You Get

  • Five conversion functions — svg2pdf, svg2png, svg2ps, svg2eps, and svg2svg — each accepting a bytestring, file object, or URL as input
  • A cairosvg command-line tool for converting files without writing any Python
  • Broad SVG tag coverage — shapes, paths, text, gradients, patterns, filters, masks, clipping paths, and use/symbol references
  • Output controls for DPI, scale, explicit output dimensions, background color, color negation, and raster image inversion
  • An unsafe flag that gates external file access and XML entity resolution, off by default to avoid XXE and SSRF exposure

Common Use Cases

  • Generating PDF invoices, reports, or print assets from SVG templates in a Python backend
  • Rendering SVG icons and diagrams to PNG for use in emails, thumbnails, or static image pipelines
  • Powering HTML-to-PDF pipelines (e.g. via WeasyPrint) that embed vector graphics inside rendered documents
  • Batch-converting a design team’s SVG exports into PDF/EPS for print production from the command line

Under The Hood

Architecture CairoSVG separates SVG parsing from rendering: parser.Tree reads a bytestring, file, or URL into a tree of nodes with cascaded CSS applied via cssselect2/tinycss2, while surface.Surface and its per-format subclasses (PDFSurface, PNGSurface, PSSurface, EPSSurface, SVGSurface) walk that tree and dispatch each element through the TAGS lookup table to a dedicated drawing function in shapes.py, path.py, text.py, image.py, or defs.py, which in turn issues the matching cairocffi drawing calls. Geometry and paint-related helpers (bounding_box.py, helpers.py, colors.py) are factored out from the tag handlers, and defs.py owns the deferred/reference-based constructs (gradients, patterns, filters, masks, use/symbol) that must resolve against nodes defined elsewhere in the document. The TAGS dictionary in surface.py is the load-bearing abstraction — every shape or structural element is only reachable through it, so extending SVG coverage means adding both a drawing function and an entry there.

Tech Stack The library targets Python 3.10+ and declares five runtime dependencies in setup.cfg: cairocffi (CFFI bindings to the system Cairo library, the actual rendering engine), cssselect2 and tinycss2 for parsing and matching the CSS a document embeds, defusedxml for XML parsing that rejects entity expansion unless unsafe=True is passed, and pillow for decoding raster images referenced by <image> elements. Packaging is plain setuptools via setup.cfg/setup.py, with the version read from a checked-in VERSION file and a cairosvg console-script entry point defined declaratively. There is no web or async framework involved — this is a synchronous, single-purpose conversion library with no database or network layer beyond the optional url= fetch of the input document.

Code Quality Two independent test layers exist: cairosvg/test_api.py exercises the public svg2* functions against the three supported input modes (bytestring, file object, URL), and test_non_regression/ renders 281 fixture SVGs and diffs the pixel output against a pinned reference version of CairoSVG pulled in as a git submodule, parametrized with pytest. CI (.github/workflows) runs the full suite on two Python versions, plus flake8 and isort --check as style gates — but there is no static type checker, and the codebase carries no type annotations at all. Error handling is explicit in places (helpers.PointError for malformed geometry) and security-conscious by default (external entity resolution and large-file parsing are opt-in only via unsafe=True), with naming that mirrors SVG tag and attribute names directly, keeping the mapping between spec and code legible.

API Design The public surface is five verb-named functions (svg2pdf, svg2png, svg2ps, svg2eps, svg2svg) sharing one keyword-only parameter set (dpi, scale, parent_width/parent_height, background_color, negate_colors, invert_images, write_to, output_width/output_height, unsafe), so a minimal call like cairosvg.svg2png(url='in.svg', write_to='out.png') is a complete, working example with no setup boilerplate. The cairosvg CLI mirrors the same option set one-to-one via argparse, and the five functions’ docstrings are generated from a single shared template in Surface.convert, keeping the documented behavior consistent across formats without hand-duplicating prose.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search