Scripting Inkscape's CLI: Batch SVG Export in a Build Pipeline
Generate PNG and PDF assets from committed SVG sources using Inkscape's CLI actions in CI — with a multi-density export example, version-pinning advice, and the font-substitution trap to avoid.
21 Oct 2025, 18:42 UTC

The problem: binary assets in your repo
Your design team hands you SVGs, and your app needs PNGs at three densities plus a PDF for print. The lazy path — exporting by hand and committing the results — fills the repository with binaries that bloat clones and can't be meaningfully diffed. The better engineering decision: commit only the SVG sources and generate raster assets at build time using Inkscape's non-interactive command-line mode.
Inkscape can run without opening its GUI, converting SVG to PNG, PDF, and other formats from a shell. That makes it a workable CI tool — but the CLI changed significantly at version 1.0, and there are fidelity traps worth knowing about before you wire it into a pipeline.
Actions vs. legacy flags: pin your version first
Since Inkscape 1.0, the CLI is organized around an actions system. A typical export now looks like this, run from any shell with Inkscape on the PATH (no special permissions needed):
inkscape logo.svg --actions="export-filename:logo.png;export-do"Older scripts you find online use legacy verbs like --export-png=logo.png, which date from the 0.9x era. Flag and action names differ between 0.9x, 1.x, and later releases, so the first pipeline decision is to pin the Inkscape version in your container image or build environment and re-test after any upgrade. Before writing scripts, confirm what the installed build supports:
inkscape --version
inkscape --action-listThe action list tells you exactly which export actions exist on that machine — far more reliable than trusting a tutorial written for a different release.
A worked example: multi-density PNG export
Say your Android project needs logo.png at 1x, 2x, and 3x densities from assets/logo.svg. A small build script might look like:
#!/bin/sh
set -e
for dpi in 96 192 288; do
scale=$((dpi / 96))
inkscape assets/logo.svg \
--export-dpi=$dpi \
--export-area-drawing \
--actions="export-filename:out/logo@${scale}x.png;export-do"
doneThree details matter here:
--export-dpicontrols raster resolution. SVG is resolution-independent, so 192 DPI produces exactly double the pixel dimensions of 96 DPI for the same artwork.--export-area-drawingsizes the output to the artwork's bounding box rather than the page (--export-area-page), which avoids unexpected whitespace padding.- If you only need one object from a multi-object file,
--export-idrasterizes a single element by its XML id — handy for icon sheets.
Run the script anywhere Inkscape is installed; outputs land wherever export-filename points. The risk is low (it only writes new files), but set -e matters so a failed export fails the build rather than silently shipping a missing asset.
The font trap and other limitations
The biggest fidelity risk is text. Rendering is only deterministic when the fonts referenced by the SVG are installed on the build machine. Missing fonts cause silent substitution — the export succeeds, but text metrics shift and the output looks wrong. Two mitigations: install the exact fonts in your CI image, or convert text to paths in the source SVG (Object to Path in Inkscape) before committing. The latter makes sources less editable, so many teams keep an editable master and a path-only build variant.
Other practical limits:
- Headless environments: modern Inkscape can still pull in GUI libraries. Don't assume it works in a minimal container — build the image and actually run an export in CI before depending on it.
- Performance: filter-heavy or very large SVGs rasterize slowly. Set timeouts on the step and parallelize per file rather than invoking Inkscape once per file in a tight loop, since startup overhead dominates small exports.
Verify it, don't trust it
Two cheap checks catch most pipeline problems. First, sanity-check scaling: export a known test SVG at 96 and 192 DPI and confirm the pixel dimensions double. Second, render the same file on a developer machine and in CI and compare outputs — a byte comparison works if environments are identical; otherwise a perceptual hash catches font or library drift. If the hashes diverge after an Inkscape upgrade, that's your early warning.
The payoff for this setup is real: reviewable diffs, reproducible assets, and no designer-in-the-loop for routine density exports. Just treat Inkscape as a versioned build dependency, not a constant.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.