What the Protobuf Schema Viewer does
This viewer reads Protocol Buffers .proto files in your browser and lays out their messages, nested types, enums, oneofs, maps and gRPC services - with the field numbers that decide wire compatibility checked against the rules in the official language guide.
In Protocol Buffers the field number, not the name, is what goes on the wire. Reusing a deleted field's number, colliding with a reserved range or picking a number the implementation keeps for itself produces data that old and new code silently misread. Those mistakes are easy to make in review and are exactly what this page looks for.
How to use it
- Paste a
.protofile, or drop several. When pasting more than one, start each with a line such as// file: shop/common/money.protoso imports between them resolve. - Choose Read schema.
- Start with Findings: problems break compilation or compatibility, warnings are risky, notes are style-guide suggestions.
- Browse Messages for each type's fields sorted by number, with its reserved numbers and names, and Services for every RPC and its streaming mode.
- Use Dependencies to see which types a change would ripple into, and download the field map as JSON to diff it between releases.
Reading the results
Problems are rule violations: duplicate field numbers or names, numbers outside 1 to 536,870,911 or inside 19000-19999, use of a reserved number or name, required or custom defaults in proto3, a proto3 enum whose first value is not zero, invalid map keys, and duplicate enum numbers without allow_alias. protoc rejects most of these; the rest corrupt data between versions.
Warnings mostly mean a referenced type was not found in what you pasted - often because it lives in an import you did not include. Google's well-known types, such as google.protobuf.Timestamp, are known without pasting them.
The Dependencies tab lists, for each type, the types its fields use and the types that use it. Changing a message shared by many others, like a Money type, affects every message and RPC in its Used by column.
Worked example: an Orders service split across two files
The example has orders/v1/orders.proto (package shop.orders.v1) and shop/common/money.proto (package shop.common), with 8 messages, 31 fields, one enum and an OrderService with 4 RPCs: two unary, one server-streaming (WatchOrder) and one client-streaming (ImportOrders).
Four problems are reported. coupon_code = 12 reuses a reserved name; gift_note = 10 falls inside reserved 9 to 11; internal_ref = 19050 sits in the 19000-19999 block the implementation reserves; and inside LineItem, legacy_qty = 2 duplicates quantity = 2. A note also reminds you to reserve legacy_qty's number when the deprecated field is finally removed.
shop.common.Money resolves across the two files, and google.protobuf.Timestamp resolves as a well-known type, so there are no unresolved-type warnings.
The field-number rules, briefly
Numbers 1 to 15 take one byte to encode with their wire type, so use them for the most frequent fields. Every number must be unique within its message, including fields inside a oneof. The largest is 536,870,911, and 19000 to 19999 belong to the Protocol Buffers implementation.
When you delete a field, add its number - and ideally its name - to reserved. Otherwise someone will reuse the number for a new field, and old clients will read the new data as the old field. Changing a field's type is also a wire change unless the types are compatible, such as int32 and int64.
proto3 and proto2 differences checked here
proto3 has no required, no custom default values and no groups, and the first enum value must be zero because zero is the default. proto2 allows all three, and this page only warns about required and groups there, because the proto2 guide itself advises against them. A file with no syntax line is proto2 to protoc, which is flagged because it is rarely intended.
Limitations: what the result does not prove
- It reads and checks
.prototext; it is not protoc. Option values, custom options andextendblocks are read but not validated, and code-generation options are not interpreted. - Imports are not fetched. Types from files you did not paste are reported as unresolved, apart from Google's well-known types.
- Compatibility between two versions of a schema needs both versions: compare the downloaded field maps, or use a dedicated breaking-change checker in CI.
- Edition files (
edition = "2023") are parsed with proto3-like rules; feature settings that change field presence or enum behaviour are not modelled.
Privacy: where your data goes
Everything you paste, type or drop is processed in this browser tab. It is not uploaded, logged, stored or sent to analytics. Session recording and tag-manager scripts are switched off on this page.
Standards and sources
- Protocol Buffers language guide (proto3) - checked 19 Sep 2026
- Protocol Buffers language guide (proto2)
- Protocol Buffers style guide
- Protocol Buffers encoding
- gRPC core concepts - RPC life cycle and streaming
Frequently asked questions
Why can't Protocol Buffers field numbers be reused?
Serialized messages carry only field numbers and wire types, not names. If a new field takes a deleted field's number, old code reading new data - or new code reading stored old data - interprets the bytes as the wrong field. Reserving the number prevents that for good.
What are field numbers 19000 to 19999 reserved for?
The Protocol Buffers implementation keeps that block for its own use, and protoc refuses to compile a field that uses one. The viewer flags any field in the range so you can renumber it before it reaches a build.
Can I paste several .proto files that import each other?
Yes. Start each file with a line such as // file: shop/common/money.proto, or drop the files together. Types are then resolved across files using their packages, the same inside-out scoping protoc uses.
What is the difference between reserved numbers and reserved names?
Reserved numbers stop a number from being reused on the wire. Reserved names stop a name from being reused, which matters for JSON encoding and generated code, where the name is what appears. Removing a field safely usually means reserving both.
Which map key types are allowed in proto3?
Any integer type, bool or string. Floating-point types, bytes, enums and messages cannot be keys, while values can be any type except another map. Map fields also cannot be repeated or placed inside a oneof.
Does it show gRPC streaming methods?
Yes. The Services tab labels every RPC as unary, client streaming, server streaming or bidirectional, from the stream keyword on its request and response, and flags request or response types that are not messages.
Last reviewed by the A2Z.Tools team against the sources listed above.