# IconVG: a compact binary format for icons, logos, glyphs and emoji

> A deliberately small vector format that drops everything SVG Tiny kept, from text to scripting to animation, in exchange for files that are an order of magnitude smaller than the SVG they came from. The specification is explicit that it is experimental, that it is not an authoring format, and that the canonical repository moved in February 2026.

**google/iconvg** — IconVG is a compact, binary format for simple vector graphics: icons, logos, glyphs and emoji.

- Repository: https://github.com/google/iconvg
- Stars: 694 · Forks: 10
- Language: C
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/google-iconvg

## A format defined by what it refuses to do

IconVG is a compact, binary format for simple vector graphics: icons, logos, glyphs and emoji. The interesting part is the sentence that follows, because it explains the design by its omissions.

It is similar in concept to SVG but much simpler. Compared to SVG Tiny, which is not actually tiny, it does not have features for text, multimedia, interactivity, linking, scripting, animation, XSLT, DOM, combination with raster graphics such as JPEG formatted textures, and so on.

That list is the specification of the format by negation. Every feature removed is one that an icon does not need, and removing features is what makes a binary format able to be compact rather than merely a renamed XML file.

The second constraint is equally important and less obvious. It is a format for efficient presentation, not an authoring format. For example, it does not provide grouping individual paths into higher level objects. Instead, the anticipated workflow is that artists use other tools and authoring formats like Inkscape and SVG, or commercial equivalents, and export IconVG versions of their assets, the same way that they would produce PNG versions of their vector art. And it is not a goal to be able to recover the original SVG from a derived IconVG.

So the intended pipeline is one directional. Author in a real vector tool, export to IconVG, ship it, and treat the original as the source of truth.

## The size argument, with real numbers attached

The example in the readme is a single cowbell asset measured three ways, and it is the clearest evidence of what the format is for.

The cowbell.png is 18555 bytes at 256 by 256 pixels. The cowbell.svg is 4506 bytes. The cowbell.iconvg is 1012 bytes.

So against the same vector source, the IconVG file is roughly a fifth of the SVG, and against a rasterised version of it, under a twentieth. For an application that ships a toolbar of icons to a phone on a mobile connection, that difference is the entire argument. An emoji font is the other case where the ratio matters, because a colour emoji set is exactly the kind of collection that is downloaded once and cached, and every kilobyte per glyph adds up.

The tree also contains an iconvg-root-directory.txt file, which suggests the intended layout is a directory of IconVG files that a client can fetch individually, and the example directory with iconvg-to-png and iconvg-viewer subdirectories shows the two directions a consumer needs: convert an IconVG into a bitmap for display, or view one interactively.

The format carries a magic number, 0x8A 0x49 0x56 0x47, which is the string 8aIVG, with a suggested file extension of .iconvg and a suggested MIME type of image/x-iconvg. The specification itself lives in the repository at spec/iconvg-spec.md, and the test/data directory holds the example files and other examples including a disassembly of the cowbell IconVG file.

## Three decoders, and two of them read an older format

The implementations section is short, and it contains the detail that decides whether the format is usable for you today.

This repository contains a decoder written in C, a decoder written in Dart, albeit for an older, obsolete, version of the file format, and a low-level decoder written in Go. Low-level means that it outputs numbers, meaning vector coordinates, rather than pixels.

So there is one current decoder, the C one, and two that read a format version that has since been superseded. The readme links the issue tracking the obsolete version in both cases, which is a helpful pointer but also a warning: the format changed incompatibly at least once, and the code in this repository for two of the three decoders is pinned to the older shape of the file.

The Go module makes the scope equally clear. The module is github.com/google/iconvg, built for go 1.25.0, and it has exactly one dependency:

```go
module github.com/google/iconvg

go 1.25.0

require golang.org/x/image v0.41.0
```

A single dependency on the Go image library is consistent with a low-level decoder that produces coordinates for the caller to rasterise, and it is also a small, easy dependency graph for something you might embed in a build pipeline.

Separately, the original Go IconVG package at golang.org/x/exp/shiny/iconvg implements a decoder and an encoder, also for the older, obsolete, version of the file format. The encoder is worth noting even so, because the format is documented as presentation only, and an encoder for an older version existed in the ecosystem.

The practical takeaway is that if you are choosing a decoder today, the C implementation in this repository is the one that matches the current specification.

## Not pixel exact, and that is a deliberate boundary

The second half of the readme deals with fidelity, and it is unusually candid.

It is not a pixel-exact format. Different implementations may produce slightly different renderings, due to implementation-specific rounding errors in the mathematical computations when rasterizing vector paths to pixels. Artifacts may appear when scaling up to extreme sizes, say 1 million by 1 million pixels. Nonetheless, at typical scales, for example up to 4096 by 4096, such differences are not expected to be perceptible to the naked eye.

The distinction being drawn is between a format that specifies a single correct rendering and a format that specifies a geometry. IconVG stores the geometry, and the rasterisation happens in your implementation, so the last pixel can differ between two correct decoders. That is the same trade every compact binary format makes, and stating the boundary at 4096 by 4096 tells you where the practical limit is for the intended use.

For an icon set, this is harmless. Nobody can tell the difference between two renderings of a 24 by 24 chevron. For anything where a pixel difference would matter, such as a design being signed off, or a rendering that is diffed against a reference, it is a genuine constraint rather than a rounding footnote.

Combined with the format being experimental and subject to incompatible changes, the picture is of a format that is deliberately small and deliberately narrow, and that is exactly the right shape for its purpose and exactly the wrong shape for a general purpose vector format.

## Building and trying the examples

There is no installation section in the readme, because IconVG is a format and a set of decoders rather than an application, and the readme points at the specification and the example directories instead.

The build scripts at the root of the repository tell you how the example outputs are produced. build-example-with-cairo.sh and build-example-with-skia.sh are the two paths, which is a useful hint in itself, since Cairo and Skia are the two rasterisation backends an implementation would typically reach for, and the fact that there are two scripts suggests the project wanted to show the output is not identical between rasterisers.

The example directory contains two projects, iconvg-to-png and iconvg-viewer. The first is the one you want for a quick check, since it converts an IconVG file into a PNG, which is what an application that displays an icon effectively does. The second is a viewer, which suggests the more interesting question of what a vector icon looks like at a given size rather than after a fixed rasterisation.

The cmd directory at the root of the tree holds the command line entry points, and the script directory holds the build helpers, while the release directory contains the C decoder that the readme describes as the current one.

So a first use of the format looks like this. Take an SVG you already have, export it to IconVG with the tooling for your authoring application, then decode it with the C implementation or with the Go low-level decoder, and compare the output against the SVG rendering. The comparison is the actual evaluation, because the format's value is a claim about size that you want to check against your own assets rather than take on trust.

## The repository moved, and the project disclaims Google

Two administrative facts in the readme matter for anyone planning to depend on this.

The first is the move. The canonical repository's location moved on February 2026, from github.com/google/iconvg to github.com/nigeltao/iconvg, and the readme has been updated accordingly, with a note at the bottom saying it was updated in February 2026. The project is now maintained under the name of the author who wrote it, not under the Google organisation, even though the code and the licence history remain Google's.

That is a meaningful change for a dependency. The go module path in this repository is still github.com/google/iconvg, and the original Go package lives at golang.org/x/exp/shiny/iconvg, so the naming across the ecosystem is genuinely split, and a project that hard codes one path will need to check which one it means.

The second fact is the disclaimer. This is not an official Google product, it is just code that happens to be owned by Google.

Combined with the experimental warning, the picture is of a format specification that was incubated inside Google, published under the Apache-2.0 licence, and has been handed to a single maintainer outside the company. That is a normal trajectory for a format that was useful to one organisation and not obviously to everyone, and it is also a reason to look carefully at the current repository before building on it.

The last push to this repository was on 2026-09-02, and there are no GitHub releases, so the version tracking for a consumer is the commit history and the spec file rather than a release feed.

## Conclusion

Adopt IconVG if you ship icons to a client over a slow link or embed many of them, since the size reduction is the whole point of the format and the trade of features away is exactly what an icon set does not need. Skip it if you need an authoring format, since IconVG is explicitly not one and cannot be converted back to SVG, and skip it if you need a stable format, because the specification warns of incompatible changes. Verify first which repository you are using, since the canonical location moved from github.com/google/iconvg to github.com/nigeltao/iconvg in February 2026, and check that the decoder you pick supports the file format version you are shipping.

## FAQ

### What is IconVG and what is it designed for?

IconVG is a compact, binary format for simple vector graphics: icons, logos, glyphs and emoji. It is similar in concept to SVG but much simpler, with no features for text, multimedia, interactivity, linking, scripting, animation, XSLT or DOM.

### How much smaller is an IconVG file than the equivalent SVG?

The readme example measures a cowbell asset: the PNG is 18555 bytes at 256 by 256 pixels, the SVG is 4506 bytes, and the IconVG is 1012 bytes. The format is intended for efficient presentation rather than authoring.

### Which decoders does the IconVG repository contain?

A decoder written in C, a decoder written in Dart that is for an older, obsolete, version of the file format, and a low-level decoder written in Go that outputs vector coordinates rather than pixels. The original Go package at golang.org/x/exp/shiny/iconvg also implements a decoder and an encoder for that older format version.

### Is IconVG a pixel exact format?

No. Different implementations may produce slightly different renderings because of implementation-specific rounding errors when rasterizing vector paths, and artifacts may appear at extreme sizes such as 1 million by 1 million pixels. At typical scales up to 4096 by 4096 the differences are not expected to be perceptible.

### Where is the canonical IconVG repository now?

It moved in February 2026 from github.com/google/iconvg to github.com/nigeltao/iconvg, though the Go module path in this repository is still github.com/google/iconvg. The readme also notes that this is not an official Google product, and that the format is experimental and subject to incompatible changes.

### What file extension and MIME type does IconVG use?

The suggested file extension is .iconvg and the suggested MIME type is image/x-iconvg. The magic number is 0x8A 0x49 0x56 0x47, which is the string 8aIVG, and the specification is at spec/iconvg-spec.md.

## Sources

- [google/iconvg on GitHub](https://github.com/google/iconvg)
- [Issues](https://github.com/google/iconvg/issues)
- [License: Apache-2.0](https://github.com/google/iconvg/blob/main/LICENSE)
- [README](https://github.com/google/iconvg/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/google-iconvg
