What’s new here
pbf splits decoding and encoding into PbfReader and PbfWriter classes so bundlers can tree-shake whichever half you do not use. The compiled output from a .proto file is plain JavaScript you can read and edit, not an opaque runtime. Lazy decoding is first-class: save pbf.pos, skip fields, come back later.
What it does
pbf reads and writes protocol buffers in JavaScript. Give it a Buffer or Uint8Array and a field-dispatch loop, and it walks the binary message one field at a time. It also ships a CLI that compiles a .proto schema into a JavaScript module with typed read and write functions.
The benchmark in the README decodes 439 Mapbox vector tiles (37.5 MB) in 195ms at 192 MB/s and encodes them in 146ms at 257 MB/s. protobuf.js is slightly faster but ships at 33.9KB minzipped versus pbf’s 2.6KB. The same data in JSON is 136 MB; pbf decodes roughly twice as fast and produces output about a quarter the size.
The API is low-level by design. You write the field-dispatch yourself, or you generate it from a schema. Either way, the code you end up with is readable and straightforward to customize.
Who it’s for
JavaScript developers who need to read or write protobuf binary data in the browser or in Node, and where bundle size matters. Mapbox uses it in vector-tile-js to parse map tiles. If bundle size does not matter, protobuf.js is a larger alternative at 33.9KB minzipped that benchmarks slightly faster.
Try it
npm install pbfCompile a schema:
npm install -g pbf
pbf example.proto > example.jsThen read and write:
import {PbfReader, PbfWriter} from 'pbf';
import {readExample, writeExample} from './example.js';
const obj = readExample(new PbfReader(buffer));
const pbf = new PbfWriter();
writeExample(obj, pbf);
const buffer = pbf.finish();Or use directly in the browser without a build step:
<script type="module">
import {PbfReader, PbfWriter} from 'https://cdn.jsdelivr.net/npm/pbf/+esm';
</script>How mature is it
884 stars, 113 forks, 22 contributors, 8 releases. Latest release is v5.1.2 from July 9, 2026. One commit in the last 90 days; the last push was September 2, 2026. 13 open issues and pull requests. Created January 2014. License: BSD-3-Clause. Active but stable.