Protobuf Varint Encoder/Decoder

Encode integers as Protocol Buffers variable-length integers

Encode and decode unsigned integers in the Protocol Buffers varint (base-128) wire format. See the exact hex bytes a protobuf message would use, with BigInt precision for 64-bit values. Runs entirely in your browser. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is a protobuf varint?

A varint is the variable-length integer encoding used in the Protocol Buffers wire format. Small numbers take a single byte while larger numbers grow one byte at a time, which keeps serialized messages compact.

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.