FormatterHQ

Protobuf Formatter

Format Protocol Buffers definitions: messages, nested types, enums, oneofs, maps and gRPC services are laid out consistently with clang-format.

Input PROTOBUF
Output PROTOBUF
Ready.

How to use the Protobuf Formatter

  1. Paste your .proto source code into the Input editor, or use Sample, Upload file or Load URL.
  2. Pick a Style preset (default: Google), keep Indent on Style default or override it, and set the Column limit (0 means no limit).
  3. Press Format; with Auto update on, the output refreshes as you edit.
  4. Use Copy or Download above the output panel to take the formatted file with you.

A protobuf formatter for .proto files

Protocol Buffers schemas define the messages and gRPC services that other code is generated from, so they are read often and changed carefully. This protobuf formatter uses clang-format's Protocol Buffers mode to indent messages, enums and services, put one field per line, and space field assignments and options consistently. It works for proto2, proto3 and editions syntax because it formats tokens rather than validating semantics.

Example

syntax="proto3";package shop.v1;import "google/protobuf/timestamp.proto";option go_package="example.com/shop/v1;shopv1";enum Status{STATUS_UNSPECIFIED=0;STATUS_PAID=1;}message Order{string id=1;repeated LineItem items=2;google.protobuf.Timestamp created_at=3;map<string,string> labels=4;oneof payment{string card_token=5;string voucher=6;}}service Orders{rpc Get(GetOrderRequest)returns(Order);rpc Watch(WatchRequest)returns(stream Order);}
syntax = "proto3";
package shop.v1;
import "google/protobuf/timestamp.proto";
option go_package = "example.com/shop/v1;shopv1";
enum Status {
  STATUS_UNSPECIFIED = 0;
  STATUS_PAID = 1;
}
message Order {
  string id = 1;
  repeated LineItem items = 2;
  google.protobuf.Timestamp created_at = 3;
  map<string, string> labels = 4;
  oneof payment {
    string card_token = 5;
    string voucher = 6;
  }
}
service Orders {
  rpc Get(GetOrderRequest) returns (Order);
  rpc Watch(WatchRequest) returns (stream Order);
}

Every field and enum value gets its own line, = is spaced, the map<string, string> type gets a space after the comma, and returns (stream Order) is spaced as in the official examples.

Protobuf style guide essentials

The official Protocol Buffers style guide covers naming as well as layout. A formatter only handles layout, so it is worth checking the rest by eye:

  • Indentation: 2 spaces (the Google preset's default) and lines up to 80 characters.
  • Messages, enums and services in PascalCase; fields in lower_snake_case; enum values in UPPER_SNAKE_CASE prefixed with the enum name.
  • Zero value: the first enum value should be _UNSPECIFIED = 0, because proto3 uses zero as the default.
  • Repeated fields get plural names (items, not item).
  • Packages are lowercase and often versioned (shop.v1).

What the formatter will not do

  • Renumbering fields: field numbers are part of the wire format and are never changed. Reusing or changing a number breaks compatibility with existing data.
  • Reordering: declarations stay in the order you wrote them.
  • Validation: duplicate field numbers, unknown types or missing imports are not reported. Use protoc or buf lint for that.

Comments become documentation

Comments placed directly above a message, field, enum value or RPC are copied by protoc into the generated code for most languages, where they show up as doc comments in IDEs. The formatter keeps them attached to the declaration below, so it is worth writing them in full sentences and keeping them next to the element they describe.

Options

Style defaults to Google, which matches the protobuf style guide's 2-space indentation. Indent can be set to 4 spaces if your repository uses it. Column limit controls when long option lists or comments wrap; the style guide recommends 80, while this tool starts at 100. Short messages may be collapsed onto one line by some presets (for example LLVM prints message A { int32 x = 1; }), so stay with Google if you always want one field per line.

Common syntax mistakes

  • Missing semicolons after fields or syntax = "proto3" lead to broken indentation in the output.
  • Field names with hyphens are invalid; use underscores.
  • required does not exist in proto3; optional is allowed again since protobuf 3.15.

Working with the JSON representation of your messages? Format it with the JSON Formatter, or derive a JSON Schema from a sample using JSON to JSON Schema. Formatting runs in your browser.

Frequently asked questions

Does the protobuf formatter change field numbers?
Never. Field numbers identify fields on the wire, so the formatter only changes whitespace and layout around them.
Does it support proto2 and proto3?
Yes. Both syntaxes, including extensions, options, oneofs, maps and gRPC service definitions, are formatted. Editions syntax formats the same way.
Can it find errors in my .proto file?
No. clang-format does not compile schemas. Use protoc or buf lint to find duplicate numbers, unknown types and style violations.
Why did a short message end up on one line?
Some presets allow short blocks on a single line. The Google preset keeps one field per line, which is what the protobuf style guide shows.
Is buf format the same as this tool?
buf format is a separate formatter with its own fixed style. Both produce similar layouts, but spacing and wrapping details differ slightly.

Last updated September 26, 2026

Related tools