Protocol inspection

Protobuf wire data: boundaries are not a schema

A raw Protobuf stream provides field numbers and wire types. It does not carry field names or enough information to recover the original declared types.

Content updated: · Maintainer and corrections

Follow tags and exclusive end offsets

A tag is (field_number << 3) | wire_type, itself stored as a varint. Wire 0 carries a varint, wire 1 carries eight little-endian bytes, wire 2 has a length varint followed by that many bytes, and wire 5 carries four little-endian bytes. Offsets are zero-based and ranges use [start, end), with end excluded.

For 08 96 01 12 03 66 6f 6f, field 1 starts at byte 0, has tag 8 and raw unsigned value 150, and ends before byte 3. Field 2 begins at byte 3, payload begins at byte 5, and three payload bytes end before byte 8. Field number zero is invalid; numbers 19000–19999 are marked as reserved schema numbers.

Keep raw evidence separate from interpretations

A varint can represent an int, uint, ZigZag signed value, bool or enum depending on the schema. This tool reports the raw unsigned integer exactly using BigInt. Fixed32 and fixed64 show unsigned and native floating-point interpretations separately; neither is claimed as the declared type.

Length-delimited bytes may be a string, byte array, nested message or packed values. A fatal UTF-8 decode is shown only as a possible text interpretation, including control characters, not a schema decision. Invalid UTF-8 leaves the raw Hex intact. The tool never recursively guesses nested messages or attempts to unwrap gRPC frames.

Fail atomically within explicit limits

Groups, wire types 3/4, are explicitly unsupported. Invalid tags, over-ten-byte or overflowing uint64 varints, noncanonical overlong varints, truncated fixed fields and declared lengths beyond the remaining input reject the entire report. This strict contract may reject nonminimal encodings tolerated by some Protobuf readers; it does not imply that all implementations share this policy.

Input is limited to 128 KiB decoded bytes and 1000 fields. The text limit is 524288 characters, with Base64 limited to 174764; Hex accepts only byte pairs and ASCII space, tab or newline. Length is checked before taking a payload slice. Pages show at most 50 fields, payload previews are labeled, and full JSON preserves every field and byte. Editing clears old output; no input is uploaded, stored or added to a URL.

Data provenance

Sources