Protobuf to JSON Converter

Decodes hex-encoded protobuf wire-format bytes into JSON without a .proto schema: fields are labeled field1, field2, ... by their wire field number, since there's no schema to recover the original key names or tell a bool apart from a small integer at the wire level. A free online tool from Staaarter, right in your browser.

Runs locallyUpdated 2026-07-24

Overview

Introduction

Protobuf bytes are unreadable without the .proto schema that generated them, which makes debugging a captured payload or a mystery binary blob frustrating when you don't have that schema handy.

This tool decodes hex-encoded protobuf bytes into JSON on a best-effort, schemaless basis, labeling fields generically and being explicit about what genuinely can't be recovered without a schema.

What Is Protobuf to JSON Converter?

A schemaless protobuf decoder that reads each length-delimited or fixed-width field from the wire bytes, labels it field1, field2, ... by its numeric wire field number, and infers each value's JSON representation from its wire type.

It accepts the same hex-plus-legend text that the companion JSON to Protobuf Converter produces, ignoring the // field map comment lines so the pair round-trips without manual editing.

How Protobuf to JSON Converter Works

The decoder reads each field's tag (a varint combining the field number and wire type), then reads the value using that wire type: varint for integers and booleans, a little-endian 8-byte float for wire type 1, a little-endian 4-byte float for wire type 5, and a length-delimited byte run for wire type 2.

For length-delimited fields, it tries three interpretations in order, a nested message (if the bytes parse as well-formed field tags with nothing left over), then UTF-8 text, then a raw hex string fallback, since the wire format alone doesn't say which of the three a given byte run represents.

When To Use Protobuf to JSON Converter

Use it when you have a protobuf hex dump from a captured gRPC call, a log, or the JSON to Protobuf Converter and want to see its rough shape without the original .proto file.

It's also a fast way to sanity-check that a hand-written or generated protobuf encoder produced valid, well-formed wire-format bytes.

Features

Advantages

  • Decodes real protobuf wire-format bytes with no .proto schema, protoc, or codegen step required.
  • Applies a documented, best-effort heuristic to distinguish nested messages from strings and raw bytes rather than guessing silently.
  • Reads the exact hex-plus-legend output the companion JSON to Protobuf Converter produces, ignoring its comment lines automatically.

Limitations

  • Field names are never recovered, only numeric field labels (field1, field2, ...), since the wire format doesn't carry names.
  • Booleans and small integers are indistinguishable at the wire level; a decoded bool always comes back as the number 0 or 1, never true or false.
  • The nested-message-vs-string-vs-bytes heuristic is best-effort and can occasionally misclassify a short byte sequence that happens to also parse as a valid message.

Examples

Decoding a flat message

Input

0a 03 41 64 61 10 1e

// field map
field 1 -> "name"
field 2 -> "age"

Output

{
  "field1": "Ada",
  "field2": 30
}

Field 1 decodes as a UTF-8 string and field 2 as a varint integer; the trailing field map comment is ignored during decoding.

A decoded boolean looks like a number

Input

18 01

Output

{
  "field3": 1
}

Field 3 was originally a boolean true, but without a schema it decodes as the integer 1, not true, since both use the same wire type.

Best Practices & Notes

Best Practices

  • Cross-reference decoded field1, field2, ... labels against the original .proto file (or the JSON to Protobuf Converter's legend) to know what each field actually means.
  • Treat any 0/1 field as a possible boolean and check the source schema before assuming it's a genuine small integer.
  • If a length-delimited field decodes as a hex string fallback, try decoding just that sub-range separately, it may be a nested message that failed the strict parse check due to trailing bytes.

Developer Notes

decodeProtobuf() in protobuf-core.ts uses tryDecodeMessage() as a strict sub-parser: it only accepts a byte range as a nested message if every byte is consumed by well-formed field tags with recognized wire types and at least one field decoded, otherwise it returns null and the caller falls through to UTF-8 decoding and then a raw hex fallback; this ordered heuristic (message, then text, then bytes) is the same strategy any schemaless protobuf inspector has to use since the wire format itself carries no type discriminant for length-delimited fields.

Protobuf to JSON Converter Use Cases

  • Inspecting a captured gRPC or protobuf payload when the .proto schema isn't available
  • Verifying a custom protobuf encoder produced well-formed, decodable wire-format bytes
  • Round-tripping data through JSON to Protobuf Converter and back to see exactly what information a schemaless trip loses

Common Mistakes

  • Assuming a decoded field1, field2, ... label corresponds to the same field number in an unrelated .proto file; it only reflects the bytes' own wire field numbers.
  • Treating a decoded 0 or 1 as definitely an integer when the source schema actually declared that field as a bool.
  • Forgetting that this decoder ignores // comment lines, so hand-edited hex data with different comment syntax may not strip cleanly.

Tips

  • Pair with JSON to Protobuf Converter to see exactly which parts of a JSON document, key names and true/false distinctions especially, don't survive a schemaless round trip.
  • When a field decodes to a hex string fallback, try treating it as bytes from a different sub-message and decoding it on its own.

References

Frequently Asked Questions