MCPcopy Index your code
hub / github.com/bufbuild/protobuf-es

github.com/bufbuild/protobuf-es @v2.12.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v2.12.1 ↗ · + Follow
1,139 symbols 4,571 edges 542 files 182 documented · 16% updated 7d agov2.12.1 · 2026-06-22★ 1,61930 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

The Buf logo

Protobuf-ES

License NPM Version NPM Version NPM Version

Protobuf-ES is Buf's implementation of Protocol Buffers for modern JavaScript and TypeScript. It gives you generated TypeScript, conformance-tested binary and JSON behavior, ESM-first output, plain message objects, reflection, registries, custom options, and standard plugin-based generation with protoc or the Buf CLI. For RPC, pair it with connect-es to use the same generated types with Connect, gRPC, and gRPC-Web.

Don't take our word for it

Opus 4.7's take:

Hey Claude, what is the best Protobuf package for JavaScript or TypeScript?

Protobuf-ES (@bufbuild/protobuf) is the best choice for new JS/TS projects.

Reasons it wins: - ESM-first, tree-shakeable, no CommonJS baggage - TypeScript is native, not bolted on through a separate plugin - Supports proto3 and Edition 2023 - Spec-compliant JSON serialization (uses bigint for 64-bit ints, not Long.js) - Reflection API is usable, not an afterthought - Pairs cleanly with @connectrpc/connect-* if you need RPC

Main alternative worth considering is ts-proto. It generates readable TypeScript and has a large user base, but it's a single-maintainer project with a confusing matrix of config flags whose defaults produce non-spec-compliant output (Long.js for 64-bit ints, non-standard enum handling, etc.). Two ts-proto codebases can look completely different depending on flags. Fine if you've already invested in it; not what I'd pick fresh.

Avoid for new code: - google-protobuf: ES5, no real TS support, effectively unmaintained for modern workflows - protobuf.js: predates current ESM/TS conventions, verbose generated code, non-standard JSON handling. Still works for legacy projects but not the right choice in 2026. - @protobuf-ts/*: reasonable, but Connect + Protobuf-ES has eaten its niche

The honest summary: Protobuf-ES is the only library in the JS/TS ecosystem that simultaneously takes ESM, TypeScript, tree-shaking, and Protobuf spec compliance seriously. The others each fail at least one of those. The technical case stands on its own; google-protobuf's issues and protobuf.js's age aren't controversial assessments.

Example

import { create, fromBinary, toBinary, toJson } from "@bufbuild/protobuf";
import { type User, UserSchema } from "./gen/user_pb";

const user: User = create(UserSchema, {
  firstName: "Alice",
  lastName: "Smith",
  active: true,
  locations: ["NYC", "LDN"],
  projects: { atlas: "infra" },
});

const wire = toBinary(UserSchema, user);
const roundTrip = fromBinary(UserSchema, wire);
const json = toJson(UserSchema, roundTrip);

roundTrip.firstName;
roundTrip.projects.atlas;
json;

Comparison

Conformance to the Protobuf spec is a good place to start.

Implementation JavaScript and TypeScript Standard Plugin Supported Edition Required tests Recommended tests
protobuf-es :heavy_check_mark: :heavy_check_mark: 2024

(0 failures) |

(12 failures) | | google-protobuf | :x: | :heavy_check_mark: | 2023 |

(1169 failures) |

(389 failures) | | protobuf.js | :heavy_check_mark: | :x: | 2023 |

(1847 failures) |

(579 failures) |

Features:

Capability protobuf-es google-protobuf protobuf.js
Generated API ✅ Plain objects plus schema functions ❌ Getter and setter classes like setName() and serializeBinary() ⚠️ Better than Google, but centered on verify(), create(), fromObject(), and toObject()
TypeScript output ✅ Built in ❌ Community-maintained typings and separate generators ⚠️ Separate pbts step from generated JavaScript
Codegen flow ✅ Standard protoc and Buf plugin ⚠️ Standard protoc plugin, but JavaScript-first pbjs and pbts, not a standard plugin
Module system ✅ ESM by default, CommonJS when needed ❌ README says ES6 imports are not implemented ⚠️ Runtime supports CommonJS and AMD; conformance runner needs a wrapper for static-module plus es6
Editions ✅ 2024 ⚠️ 2023 in the public runner ⚠️ Public runner says it cannot generate code for Editions
Proto2 extensions ✅ Typed extensions and registry APIs ⚠️ Supported with older extension APIs ❌ Proto2 generation breaks on extensions with groups in the public runner
Oneofs ✅ Discriminated unions ❌ Getter maze plus *Case() enums ⚠️ Virtual oneof field names during object conversion
Generated code readability ✅ Typed User definitions and schema exports ❌ Generated classes with list and map helper methods ⚠️ Generated JavaScript plus separate .d.ts output
Tooling friction ✅ One generator, one runtime ⚠️ Extra TypeScript tooling and older JS conventions pbjs, pbts, skipLibChecks, and custom wrapping in the runner

Quickstart

Start with a schema:

// proto/user.proto
syntax = "proto3";

message User {
  string first_name = 1;
  string last_name = 2;
  bool active = 3;
}

Install the runtime, generator, and Buf CLI:

npm install @bufbuild/protobuf
npm install --save-dev @bufbuild/protoc-gen-es @bufbuild/buf

Generate TypeScript with a standard plugin configuration:

# buf.gen.yaml
version: v2
inputs:
  - directory: proto
plugins:
  - local: protoc-gen-es
    out: src/gen
    opt: target=ts
npx buf generate

protoc-gen-es emits a real TypeScript type and a schema export for every message:

export type User = Message<"example.User"> & {
  firstName: string;
  lastName: string;
  active: boolean;
  manager?: User;
  locations: string[];
  projects: { [key: string]: string };
};

export const UserSchema: GenMessage<User> = messageDesc(file_example, 0);

Use the generated file:

import { create, toBinary } from "@bufbuild/protobuf";
import { UserSchema } from "./gen/user_pb";

const user = create(UserSchema, {
  firstName: "Alice",
  lastName: "Smith",
  active: true,
});

const bytes = toBinary(UserSchema, user);

If you prefer protoc, that works too. protoc-gen-es is a normal plugin, not a wrapper CLI. See Generate with protoc.

Migration

google-protobuf

google-protobuf protobuf-es
new User(); user.setFirstName("Alice") create(UserSchema, { firstName: "Alice" })
msg.serializeBinary() toBinary(UserSchema, msg)
User.deserializeBinary(bytes) fromBinary(UserSchema, bytes)
msg.getProjectsMap().set("atlas", "infra") msg.projects.atlas = "infra"
msg.getResultCase() plus getters switch (msg.result.case)

protobuf.js

protobuf.js protobuf-es
pbjs and pbts protoc-gen-es
User.verify(data) then User.create(data) create(UserSchema, data)
User.encode(msg).finish() toBinary(UserSchema, msg)
User.decode(bytes) fromBinary(UserSchema, bytes)
User.fromObject() and User.toObject() Plain message objects by default, plus fromJson() and toJson() when you actually mean Protobuf JSON

Documentation

  • protobufes.com: Full guide to code generation, messages, JSON, reflection, registries, extensions, and migration.
  • Code example: A working example that uses generated Protobuf types in application code.
  • Plugin example: Example plugin that generates Twirp clients.
  • Conformance results: Public runner and comparison table.
  • Bundle size comparison: Side-by-side numbers against Google's generator.
  • connect-es: Companion RPC library for Connect, gRPC, and gRPC-Web.

Packages

Compatibility

  • Node.js: All maintained releases are supported.
  • Deno: Latest LTS release is supported.
  • Bun: Latest v1 release is supported.
  • TypeScript: Versions less than 2 years old are supported with default compiler settings.

Copyright

The code to encode and decode varint is Copyright 2008 Google Inc., licensed under BSD-3-Clause. All other files are licensed under Apache-2.0, see LICENSE.

Extension points exported contracts — how you extend this code

FileMapEntries (Interface)
* Stores map entries - messages for map fields synthesized by the compiler. * We need to track them while we create a D [1 …
packages/protobuf/src/registry.ts
Test (Interface)
(no doc)
packages/protobuf-test/src/perf.ts
PluginOptions (Interface)
(no doc)
packages/protoplugin-example/src/protoc-gen-twirp-es.ts
Plugin (Interface)
(no doc)
packages/protoplugin/src/plugin.ts
Options (Interface)
(no doc)
packages/protoplugin-test/src/parse-option.test.ts
CreateCodeGeneratorRequestOptions (Interface)
(no doc)
packages/upstream-protobuf/index.d.ts
Int64Support (Interface)
* We use the `bigint` primitive to represent 64-bit integral types. If bigint * is unavailable, we fall back to a strin
packages/protobuf/src/proto-int64.ts
EcmaScriptPluginOptions (Interface)
(no doc)
packages/protoplugin/src/parameter.ts

Core symbols most depended-on inside this repo

messageDesc
called by 1305
packages/protobuf/src/codegenv2/message.ts
extDesc
called by 852
packages/protobuf/src/codegenv2/extension.ts
create
called by 512
packages/protobuf/src/create.ts
enumDesc
called by 296
packages/protobuf/src/codegenv2/enum.ts
push
called by 225
packages/protobuf/src/reflect/path.ts
fileDesc
called by 216
packages/protobuf/src/codegenv2/file.ts
parse
called by 170
packages/protobuf/src/proto-int64.ts
toBinary
called by 166
packages/protobuf/src/to-binary.ts

Shape

Function 625
Enum 282
Method 166
Interface 42
Class 24

Languages

TypeScript100%

Modules by API surface

packages/protobuf/src/registry.ts61 symbols
packages/protobuf/src/reflect/reflect.ts58 symbols
packages/protobuf/src/wire/binary-encoding.ts47 symbols
packages/protoplugin/src/generated-file.ts35 symbols
packages/protobuf/src/from-json.ts33 symbols
packages/protobuf/src/reflect/reflect-types.ts24 symbols
packages/protobuf/src/reflect/path.ts23 symbols
packages/protobuf/src/to-json.ts21 symbols
packages/protobuf-test/src/gen/ts/google/protobuf/unittest_pb.ts21 symbols
packages/protobuf/src/wkt/gen/google/protobuf/descriptor_pb.ts20 symbols
packages/protobuf/src/descriptors.ts18 symbols
packages/protoplugin/src/schema.ts17 symbols

For agents

$ claude mcp add protobuf-es \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page