← Back to Blog

Export ArcGIS Pro symbology to SVG: reuse your cartography on the web

Export ArcGIS Pro symbology to SVG: reuse your cartography on the web

You spent real time designing point symbols in ArcGIS Pro — the right shape, the right blue, the right proportions. Now you need those exact symbols on the web: as the legend in a custom app, as icons on a marketing page, as assets on your CDN. Screenshotting them from Pro is lossy and off-brand. There’s a clean path instead, and it’s simpler than it looks.

The whole trick rests on two facts most people never check: an ArcGIS Pro style file is an ordinary SQLite database, and a symbol inside it is just CIM JSON. Put those together and “export my Pro symbols as crisp SVG” becomes a small, dependency-light script. Here’s how it works — and a free notebook and Pro tool that do it for you.

A .stylx is a SQLite database

Rename a .stylx to .db and open it in any SQLite browser — it’s all there. Symbols live as rows in an ITEMS table, and each symbol’s definition sits in a CONTENT column as CIM JSON. You can read every symbol with nothing but the Python standard library — no arcpy required:

import sqlite3, json

con = sqlite3.connect(r"C:\path\to\Favorites.stylx")
for name, category, content in con.execute(
        "SELECT NAME, CATEGORY, CONTENT FROM ITEMS"):   # CLASS column tags point/line/fill
    cim = json.loads(content)        # the symbol, as CIM JSON
    # cim["symbol"]["symbolLayers"] -> the marker layers we turn into SVG

That one realization is what makes the rest cheap: symbol discovery, category listing, and the entire SVG conversion run as plain Python. arcpy only enters if you wrap the whole thing as a Pro geoprocessing tool — the logic itself doesn’t need it.

A symbol is CIM JSON

CIM — the Cartographic Information Model — is Esri’s documented JSON representation of everything in a map, symbols included (CIM specification, Python CIM access). A point symbol is a stack of marker layers; each vector marker carries a markerGraphic whose geometry is the actual shape — rings, paths, or a point — plus the fill and stroke to paint it with. Translating that to SVG is a direct, per-layer mapping.

CIM → SVG, layer by layer

For each marker layer the converter emits one <path> (or a <circle> for a bare point): polygon rings and paths become an SVG path’s d, and curved segments — cubic, quadratic, and true arcs — map onto SVG’s C, Q and A commands. CIM solid-fill and solid-stroke layers become SVG fill and stroke, and CIM’s 0–100 alpha is rescaled to SVG’s 0–1 opacity.

The one gotcha that’ll get you: CIM geometry is y-up (math convention); SVG is y-down (screen convention). If you forget, every symbol comes out vertically mirrored. Don’t negate every coordinate — flip once on a group transform, and set the viewBox with half the widest stroke as padding so thick outlines don’t clip at the edge:

# one sign-flip beats negating every vertex; pad the viewBox by half the max stroke
svg = f'<svg viewBox="{x-pad} {y-pad} {w+2*pad} {h+2*pad}" xmlns="http://www.w3.org/2000/svg">' \
      f'<g transform="scale({s}, {-s})">{paths}</g></svg>'

Picture markers (a symbol built from an embedded raster) are handled too: the base64 image is decoded to a sidecar file and referenced with <image href>, so those symbols survive the trip as well.

PNG when you need it

SVG is the right primary output — it’s resolution-independent and recolorable in CSS. When you also need a raster (favicon, slide, email), the tool rasterizes the SVG it just made: it uses cairosvg if it’s installed, falls back to a local Inkscape CLI, and if neither is present it still writes the SVG and simply skips the PNG with a note. The vector is never held hostage to a raster dependency.

What it handles (and what it doesn’t)

This is built for point / marker symbology — vector markers and picture markers, the symbols you actually want as web icons and legend swatches. It does not compose line or fill symbol layers; those are a different shape of problem. The SVG core is pure Python 3 standard library (sqlite3, json, base64, math), so it runs in arcgispro-py3 or any plain Python; only the optional PNG step and the Pro-tool wrapper add anything.

Grab the tool — free

Two ways to run it, same render core — take either or both. The notebook exposes a single CONFIG cell: set your .stylx path and output folder, Run All. The Pro tool is the same logic as a geoprocessing tool — drop the .pyt into a toolbox and fill in the dialog, no code at all. Both default to your Pro Favorites style when you leave the path blank.

MIT-licensed. The SVG core needs no extra packages; the optional PNG step needs cairosvg or Inkscape.

Tool parameterNotebook variableWhat it controlsDefault
Style file (.stylx)STYLX_PATHSource style; blank auto-detects your Pro Favorites.stylxblank → auto
ScopeSCOPEAll symbols / selected categories / single symbolAll
CategoriesCATEGORIESCategory list when scope = categories[]
SymbolSYMBOLOne symbol name when scope = single
SVG output folderSVG_DIRWhere .svg files are writtenrequired
Also write PNGWRITE_PNGRasterize a PNG per symboltrue
Target size (px)TARGET_PXOutput width = height in pixels200

References

Want your Pro cartography to live on the web?

We bridge ArcGIS Pro and the browser — symbol libraries exported to SVG, branded legends, and design systems that keep your maps consistent from desktop to web app. If you’re recreating symbols by hand, stop.

Book a free intro call