The Protocol Buffers wire format stores integers as varints — variable-length sequences where small numbers cost a single byte and larger numbers grow gradually. This tool turns any non-negative integer into its exact varint bytes and decodes byte sequences back into numbers, so you can inspect or hand-build a protobuf payload.
How it works
A varint splits the integer into 7-bit groups, least significant group first.
Each group is written into one byte’s low 7 bits, and the top bit (0x80)
is set as a continuation flag on every byte except the final one:
300 (binary 100101100)
low 7 bits 0101100 -> 0xAC (continuation set)
next bits 10 -> 0x02 (last byte)
varint = AC 02
Decoding reverses this: read bytes until one has its continuation bit cleared, shift each group left by 7 times its position, and OR them together. The tool uses BigInt throughout so 64-bit values stay exact.
Tips and notes
Varint is defined only for unsigned (non-negative) integers; signed protobuf
fields are normally pre-processed with ZigZag encoding first, so use the ZigZag
tool before this one for negative numbers. When decoding, separate bytes with
spaces or commas and write them in hex (AC, 0xAC) or decimal (172). The
final byte must clear its continuation bit or the input is reported as an
incomplete varint.
Where varints appear in real protobuf messages
When you open a binary protobuf message in a hex editor, the first few bytes are almost always varints — the field tag (field number shifted left by 3, OR-ed with wire type 0 for varint) followed by the value. Wire type 0 means the next bytes are a varint, so the decoder reads until it finds a byte without the continuation bit set. This is why protobuf messages are so compact: a field with a small integer value like 1 or 42 takes only two bytes total (tag + one-byte value), whereas a fixed-32 encoding would always cost 4 bytes.
Signed integers and ZigZag
Standard varints only encode non-negative numbers efficiently. A small negative
number like −1, treated as a two’s-complement 64-bit integer, becomes a very
large unsigned value (all bits set) and expands to 10 bytes. Protobuf’s solution
is ZigZag encoding, which maps −1 to 1, −2 to 3, 1 to 2, and so on, making
small negatives compact. The general formula is (n << 1) ^ (n >> 63) for 64-bit
integers. Use the ZigZag encoder first for negative numbers, then encode the
result as a varint.
Practical uses for this encoder
Beyond debugging protobuf wire formats, varint encoding appears in MessagePack, CBOR, Cap’n Proto, FlatBuffers, LEB128, and various binary file formats. If you are hand-building a protobuf payload for testing, this tool gives you the exact bytes to inject. If you are writing a custom binary protocol and want compact integer storage, varint is the standard off-the-shelf solution for integers that skew small. Paste the output bytes directly into a hex editor, a raw socket write, or a unit test fixture.