Runs 100% in your browser — nothing uploaded

Protobuf Decoder — Wire Format Viewer

Paste a serialized protocol-buffers message as hex or base64 and see it decoded into a tree of field numbers, wire types and values — no .proto schema required. Nested messages are unpacked recursively. Binary payloads are often proprietary, so decoding stays entirely on your device.

protobuf (hex / base64)input
decoded treefield → wire type → value
Paste a protobuf message (hex or base64). Everything runs on this device.

How to decode a protobuf message

Paste the serialized message into the input pane as a hex string (for example 089601120774657374696e67) or as base64; the tool auto-detects which, or you can force a format. It walks the bytes and prints a tree: every field's number, its wire type, and the decoded value, with nested messages indented underneath their parent. Copy the tree with one click. There is no schema to upload and nothing is sent anywhere — the decode happens in your browser.

What the protobuf wire format encodes

Protocol buffers serialize each field as a tag followed by a value. The tag is a varint holding the field number shifted left by three bits, with the low three bits naming the wire type. Four wire types matter in practice: type 0 (varint) for variable-length integers — int32/64, uint, bool and enum; type 1 (64-bit) for fixed64, sfixed64 and double; type 2 (length-delimited) for strings, bytes and embedded messages, prefixed by a varint length; and type 5 (32-bit) for fixed32, sfixed32 and float. Because the field names are not on the wire, a schema-free decoder can recover the complete structure and every value but not the human-readable names.

This viewer interprets each type usefully. A varint is shown as its unsigned value plus the signed (two's-complement int64) and zigzag (sint) readings, because the same bytes mean different things depending on the declared field type. Fixed-width fields are shown both as raw integers and as the IEEE-754 float or double they may represent. All multi-byte integers follow protobuf's little-endian convention.

Strings, bytes or a nested message?

Length-delimited fields are the interesting case: on the wire there is no way to tell a string from a packed array from an embedded message — they are all just a length and that many bytes. The decoder resolves this with a heuristic. It first tries to parse the bytes as a nested protobuf message; if every byte is consumed and the field numbers look valid, it shows the decoded sub-tree. If that fails but the bytes are valid printable UTF-8, it shows them as a string. Otherwise it falls back to a hex byte dump. This matches how interactive protobuf inspectors work, and it means deeply nested messages unfold automatically — while genuinely ambiguous fields are still shown so you can judge for yourself.

Why decode protobuf without a schema?

You reach for a schema-free decoder exactly when you do not have the .proto — reverse-engineering a mobile app's gRPC traffic, debugging a webhook whose payload arrived as opaque bytes, inspecting a cached binary response, or checking what a client actually sent versus what you expected. Pasting hex into a chatbot to "decode this protobuf" does not work reliably: varint parsing is bit-level and a model will guess. A deterministic parser reads the bytes exactly as the protobuf runtime would, so the structure it shows is the structure that is really there.

Why a local protobuf decoder matters

The binary payloads you decode are some of the least shareable data a developer touches: a captured gRPC frame can carry user records, auth material, internal identifiers or unreleased API fields. Uploading that to an online decoder hands proprietary traffic to a third party that may log or cache it. The safe approach is to never let the bytes leave your machine.

This decoder is plain JavaScript that runs inside your own browser tab — the varint reader, the recursive descent and the type heuristics all execute in memory on your device, with no network request, no account and no logging. Close the tab and the payload is gone. That is the gitime.dev approach throughout: deterministic, dependency-light developer tools that keep your data where it belongs.

Frequently asked questions

Do I need a .proto schema to decode?
No. The wire format is read directly, recovering field numbers, wire types and values. Field names live only in the .proto and cannot be recovered.
Is my protobuf payload uploaded anywhere?
No. Decoding runs in your browser. The bytes you paste never leave your device.
How are length-delimited fields interpreted?
The tool tries a nested-message parse first, then valid UTF-8 as a string, then a hex byte dump.
What do varint and fixed32/64 mean?
Varint is a variable-length integer (shown unsigned, signed and zigzag); fixed64/fixed32 are 8- and 4-byte little-endian values, also shown as double/float.

Related tools