Open-source project
mapbox/geobuf avatar
mapbox/geobuf

Geobuf: GeoJSON in a protocol buffer, six to eight times smaller

A compact binary encoding for geographic data.

1,033 stars86 forksJavaScriptISC

At a glance

What is it?
Geobuf is a compact binary encoding for geographic data that packs GeoJSON into protocol buffers, keeping properties and geometry structure rather than flattening them. It usually makes GeoJSON six to eight times smaller, and its schema is explicitly not stable yet, which is the one thing to weigh before committing to it.
Who is it for?
Geobuf suits a team shipping large GeoJSON payloads over a network, storing them where size matters, or converting legacy Shapefiles to something modern, and who can accept a schema that is documented as not yet stable. It is the wrong choice if you need vector tiles, since Geobuf explicitly does without tiling or projecting, and a poor fit if you need exact coordinates, because the near lossless encoding keeps six decimal places, which is about ten centimetres.
Can I use it commercially?
Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 116 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Geobuf is: GeoJSON in a protocol buffer, kept intact

Geobuf is described as a compact binary encoding for geographic data, providing nearly lossless compression of GeoJSON data into protocol buffers. The word nearly is doing specific work, and the README defines it precisely: coordinates are encoded with precision of 6 digits after the decimal point, which is about 10cm. So the geometry is preserved to within a hand's width rather than exactly, and the properties and structure are preserved. The stated advantages over GeoJSON alone are that it is very compact, typically making GeoJSON six to eight times smaller, that it is two to two and a half times smaller even when comparing gzipped sizes, and that encoding and decoding is very fast, even faster than native JSON parse and stringify. The comparison against gzipped sizes is the interesting one, because it isolates the format's own efficiency from what gzip happens to do.

The measured sizes, on two real datasets

The README includes a sample compression table with two datasets, and quoting the numbers is more useful than paraphrasing them. For US zip codes, JSON is 101.85 MB, JSON gzipped is 26.67 MB, Geobuf is 12.24 MB and Geobuf gzipped is 10.48 MB. For Idaho counties, JSON is 10.92 MB, JSON gzipped is 2.57 MB, Geobuf is 1.37 MB and Geobuf gzipped is 1.17 MB. Read the first row carefully, because it makes the point that a binary format can beat gzip on already compressible data. Gzip takes the zip code JSON down to about a quarter of its size, and Geobuf without gzip gets to about an eighth, and Geobuf with gzip only improves on the plain Geobuf by a small margin, because the format has already removed the redundancy gzip was exploiting. The second row shows the same pattern at a smaller scale, with the gzipped Geobuf at about 1.17 MB against 2.57 MB for gzipped JSON, so roughly half rather than a quarter.

The design ambition: a Shapefile successor that keeps what Shapefile throws away

The README frames the project as an attempt to design a simple, modern Shapefile successor that works seamlessly with GeoJSON, and then draws the contrast with Mapbox Vector Tiles explicitly. Geobuf aims for nearly lossless compression of datasets without tiling, projecting coordinates, flattening geometries or stripping properties, and that list is exactly where it parts ways with Mapbox Vector Tiles. A client that receives Geobuf can recover the original geometry, the original coordinate system and the full property set, which is the trade the tiling-free design makes. The See Also section places it among twkb, which is a geospatial binary encoding that does not support topology and does not encode any non-geographic properties besides id, and TopoJSON, which is a GeoJSON extension that does support topology, so the position in that family is fairly clear.

The schema is explicitly unstable, and the format is defined in a .proto file

The README says plainly that the encoding schema is not stable yet, and that it may still change as the project gets community feedback and new ways to improve it are discovered. That is the single most important line for anyone considering the format for long-lived data. The schema itself lives in geobuf.proto in the repository, which is the artifact to read if you want to know what the encoding actually looks like, and the package files list includes geobuf.proto so it ships with the module. The reason a protocol buffer schema is the right home for it is that protocol buffers are designed to be forward compatible, so a reader can skip fields it does not understand, and that property matters here because the schema is expected to move. The trade is that you get a format designed to change under you in exchange for a format designed to be read by many implementations.

The API is two functions, and the Pbf object is the seam

The API section lists two operations. To encode, you call geobuf.encode with a GeoJSON object and a Pbf object to write to, and it returns a Geobuf as a UInt8Array of bytes, and in Node 4.5.0 or later you can use Buffer.from to convert back to a buffer. To decode, you call geobuf.decode with a Pbf object holding Geobuf data and get a GeoJSON object back. The Pbf library is the seam, and it is a dependency rather than part of the package, so a caller who wants to work with the bytes directly can do so. There is one browser detail worth knowing, that when loading Geobuf data over XMLHttpRequest you need to set responseType to arraybuffer, since the response arrives as a buffer and not as text. The whole API surface is small enough to read in a minute, which is the sign of a format that is meant to be used from many languages rather than only from JavaScript.

js
const buffer = geobuf.encode(geojson, new Pbf());
js
const geojson = geobuf.decode(new Pbf(data));

Three command line binaries, and a documented performance trap

Installing the package globally installs three binaries. geobuf2json turns Geobuf from stdin or a specified file into GeoJSON on stdout, json2geobuf does the reverse, and shp2geobuf takes a Shapefile filename and writes Geobuf to stdout, so a Shapefile to GeoJSON pipeline is two commands. The README then explains a performance problem in a way that is unusually useful, because the instinct is to blame the decoder. For big files, geobuf2json can be pretty slow, but the bottleneck is not the decoding, it is the native JSON.stringify on the decoded object to pipe it as a string to stdout. On some files this step may take forty times more time than the actual decoding. So the format is fast and the tool is slow, and the reason is a string conversion at the end of the pipeline. That is a fact worth having before you benchmark the CLI and conclude the encoding is slow.

bash
npm install -g geobuf

json2geobuf data.json > data.pbf
shp2geobuf myshapefile > data.pbf
geobuf2json data.pbf > data.json

What incremental parsing and partial reads would give you

The README says the encoding format also potentially allows easy incremental parsing, getting features out as you read them without needing to build an in-memory representation of the whole data, and partial reads, reading only the parts you actually need and skipping the rest. The word potentially is doing the work, since these are properties the format is designed to permit rather than features the library currently exposes. This is the case where the choice of protocol buffer matters. A length-delimited record stream lets a consumer read the first feature and stop, and a reader that understands the schema can walk past a record it does not need. For a large dataset served to a client that only wants a subset, that is the difference between a full transfer and a partial one. But the API as documented is encode and decode of a whole object, so the incremental path is something a consumer would build on top of the format rather than something the package hands you.

Upkeep, packaging and the licence

The version in the package manifest is 4.0.0, the sole listed release is v4.0.0 from 2026-04-28, and the last push to the repository was on 2026-06-29, with the repository not archived. The licence is ISC, as stated in the manifest and in the LICENSE file, which is a short permissive licence with no copyleft obligation. The package is an ES module with a type of module, and the build has moved to rolldown with a rolldown.config.js, the test script is node --test, and the pretest step runs eslint over the source, the tests and the bin directory. The dev dependencies are small and telling: the geojson-fixtures package for test data, benchmark for the performance claims, and eslint with the mourner config. The runtime dependencies are just pbf and shapefile, the latter being what makes the shp2geobuf binary possible. The published files list includes the proto schema alongside the code, so a consumer can read the format without fetching the repository.

Editorial conclusion

Geobuf suits a team shipping large GeoJSON payloads over a network, storing them where size matters, or converting legacy Shapefiles to something modern, and who can accept a schema that is documented as not yet stable. It is the wrong choice if you need vector tiles, since Geobuf explicitly does without tiling or projecting, and a poor fit if you need exact coordinates, because the near lossless encoding keeps six decimal places, which is about ten centimetres. Before adopting it, read geobuf.proto in the repository and treat the encoding as a moving target, since the README says it may still change as the project gets community feedback, and note that the command line conversion is documented as slow on large files for a reason worth understanding.

Frequently asked questions

What is Geobuf and how does it compare to GeoJSON?

Geobuf is a compact binary encoding for geographic data that provides nearly lossless compression of GeoJSON into protocol buffers. It typically makes GeoJSON six to eight times smaller, and two to two and a half times smaller even when comparing gzipped sizes, with encoding and decoding that are very fast.

What does nearly lossless mean in Geobuf?

Coordinates are encoded with precision of 6 digits after the decimal point, which is about 10cm. Properties and structure are preserved; the loss is in the coordinate precision only.

How do I encode and decode with Geobuf?

Call geobuf.encode with a GeoJSON object and a Pbf object to write to, which returns the Geobuf as a UInt8Array, and geobuf.decode with a Pbf object holding Geobuf data to get a GeoJSON object back. When loading over XMLHttpRequest you need to set responseType to arraybuffer.

Is the Geobuf encoding schema stable?

No. The README states that the encoding schema is not stable yet and may still change as the project gets community feedback and discovers new ways to improve it. The schema is defined in geobuf.proto, which ships with the package.

How do I convert a Shapefile to Geobuf?

Install the package globally with npm install -g geobuf, which provides the geobuf2json, json2geobuf and shp2geobuf binaries, then run shp2geobuf myshapefile > data.pbf. The README notes that geobuf2json can be slow on big files because the bottleneck is JSON.stringify at the end rather than the decoding.

Official sources

  1. Issues
  2. License: ISC
  3. mapbox/geobuf on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mapbox-geobuf.svg)](https://hysenlabs.com/projects/mapbox-geobuf)