Protobuf decoder

Paste protobuf bytes as base64 or hex and see every field: its number, its wire type and its value, with nested messages opened up. No .proto is needed, as with protoc --decode_raw. A gRPC frame's 5-byte header is recognised and skipped. It runs in this page; nothing is uploaded.

Updated

Worked example

A user record, as base64:

CCoSDEFkYSBMb3ZlbGFjZRoTCg9hZGFAZXhhbXBsZS5jb20QASIDAQIDKPn//////////wExH4XrUbgeCUA=

decodes to:

1 (varint): 42 · sint 21
2 (len 12, string): "Ada Lovelace"
3 (len 19, message) {
  1 (len 15, string): "ada@example.com"
  2 (varint): 1 · sint -1 · bool true
}
4 (len 3, bytes): 01 02 03 · packed [1, 2, 3]
5 (varint): 18446744073709551609 · int64 -7
6 (fixed64): 4614253070214989087 · double 3.14
  • Field 1 is a varint: 42 if it is an int32, 21 if it is a sint32.
  • Field 3 is a nested message with an email and a bool.
  • Field 4 is three bytes that read as a packed repeated int32: 1, 2 and 3.
  • Field 5 takes ten bytes because it is a negative int64, −7.
  • Field 6 is 8 fixed bytes; as a double it is 3.14.

Reading the wire types

Wire typeUsed forShown as
0 varintint32, int64, uint32, uint64, sint32, sint64, bool, enumsunsigned; negative int64; zigzag for sint
1 fixed64fixed64, sfixed64, doubleunsigned, signed and double
2 lenstring, bytes, nested messages, packed repeated numberstext, a nested message, or hex with a packed reading
3, 4 groupproto2 groups (deprecated)a nested block
5 fixed32fixed32, sfixed32, floatunsigned, signed and float

Each field starts with a tag, (field number << 3) | wire type, as a varint. The wire format does not record names or declared types, so the decoder shows each reading that fits; the .proto decides which one is meant.

istek decodes every response against its schema, so you read field names and values instead of numbers. See istek.

istek, $29 once

macOS 14.0+ · Apple Silicon · no account, no telemetry

Buy istek · $29