Skip to content

Protobuf Decoder

Decodes a protobuf payload without the .proto file, inferring field numbers, wire types and nesting.

Decodes a protobuf payload without the `.proto` file. It reads the wire format — field numbers, wire types, nesting — and shows every valid reading of each value side by side, because without the schema there is genuinely more than one.

🔒 Runs entirely in your browserprotobufdecodebinarygrpc

Payload

Drop a binary payload

Decoded in this tab. Nothing is uploaded.

Fields

Top-level fields

3

Total size

17 byte

  • #1VARINT@0, 3 Buint 150 · zigzag 75
  • #2LEN@3, 9 B"testing"
  • #3LEN@12, 5 Bmessage (1 field)
    • #1VARINT@0, 3 Buint 150 · zigzag 75

As JSON (field numbers for names)

Without the .proto file there are no field names and one payload can have several valid readings — a varint is shown as unsigned, signed and zigzag at once, and a length-delimited field as message, text or bytes. The nesting shown is the reading where every byte parses exactly; the alternatives are printed beside it, not hidden.

How to use it

  1. Paste the bytes or drop the file

    Hex with or without spaces, or Base64. A binary file up to 32 MB can be dropped instead.

  2. Read the field list

    Each row gives the field number, the wire type, the byte offset and length, and the readings. Nested messages are indented under their parent.

  3. Take the JSON projection

    The same tree as JSON, with field numbers standing in for names. Useful for diffing two payloads, or for pasting into an issue.

Common questions

Why are there no field names?

Because protobuf does not put them on the wire. The encoded message carries field *numbers* only — the names live in the `.proto` file, which is exactly what makes the format compact and exactly why a schema-less decode can only show you numbers.

Why is one value shown three different ways?

Because a varint on the wire is just bits: the same bytes are a valid `uint64`, a valid `int64` and a valid zigzag `sint64`, and only the schema says which. Showing one and hiding the others would be a guess presented as a fact.

How does it decide a field is a nested message?

A length-delimited field could be a message, a string or raw bytes. It is shown as a message when its contents parse completely — every byte consumed, no leftovers — and the string reading is printed alongside when the bytes are also printable text. Occasionally a short string parses as a message by coincidence; both readings are there so you can tell.

Can it decode gRPC traffic?

The message body, yes, once you strip the five-byte gRPC frame header — one compression flag and a four-byte big-endian length — from the front. Feed the bytes after that and it decodes normally.

Feed it from

Next

These accept what this tool produces, so the result can go straight in.