Protobuf Varint & ZigZag Calculator
Use this Protobuf Varint & ZigZag Calculator to encode unsigned integers into Protocol Buffers varint bytes, decode protobuf varint hex back to decimal, and convert signed sint32 or sint64 values using ZigZag encoding.
uint32 or uint64 use the unsigned value directly.
Fields declared as sint32 or sint64 first apply
ZigZag encoding and then encode the resulting unsigned integer as a varint.
| Byte | Hex | Binary | Continuation | 7 Data Bits | Bit Shift |
|---|
-
-
What Is a Protobuf Varint?
A protobuf varint is a variable-length integer representation used by Protocol Buffers for several integer-like field types. Instead of always storing an integer in four or eight bytes, a varint stores seven value bits in each byte and uses the high bit as a continuation flag.
Small non-negative values therefore require very little space. Values from 0 through 127 fit in one byte, while progressively larger values require additional bytes.
How Protobuf Varint Encoding Works
Each varint byte contains:
bit 7:
continuation flag
bits 6..0:
seven value bits
If another varint byte follows, the most significant bit is set to one. The final byte has a zero continuation bit.
Protobuf Varint Example: 150
The decimal value 150 is represented in binary as:
150 decimal
= 10010110₂
Split the value into groups of seven bits beginning with the least significant bits:
150
→ 0000001 0010110
The low seven bits are transmitted first. Because another group follows, the continuation bit is set:
0010110
+ continuation 1
= 10010110
= 0x96
0000001
+ continuation 0
= 00000001
= 0x01
Result:
96 01
Varint Byte Ranges
| Varint Bytes | Unsigned Range |
|---|---|
| 1 byte | 0 – 127 |
| 2 bytes | 128 – 16,383 |
| 3 bytes | 16,384 – 2,097,151 |
| 4 bytes | 2,097,152 – 268,435,455 |
| 5 bytes | 268,435,456 – 34,359,738,367 |
| Up to 10 | Required for the full uint64 range |
What Is ZigZag Encoding?
ZigZag encoding maps signed integers onto unsigned integers so values near zero remain small before varint encoding.
Signed ZigZag
0 → 0
-1 → 1
1 → 2
-2 → 3
2 → 4
-3 → 5
The mapping interleaves negative and positive values instead of allowing small negative values to turn into very large unsigned representations.
ZigZag Encoding Formula
Conceptually, ZigZag can be expressed without relying on a specific programming language’s signed shift behavior:
if n ≥ 0:
ZigZag(n) = 2 × n
if n < 0:
ZigZag(n) = -2 × n - 1
For example:
n = -75
ZigZag =
-2 × (-75) - 1
= 150 - 1
= 149
ZigZag Decode Formula
To convert the unsigned ZigZag value back to the original signed integer:
signed =
(unsigned >> 1)
XOR
-(unsigned & 1)
An equivalent conceptual rule is:
even ZigZag value:
n = value / 2
odd ZigZag value:
n = -(value + 1) / 2
Example: Encode −75 as Protobuf sint64
First ZigZag encode the signed value:
-75
→ ZigZag 149
Then encode unsigned 149 as a protobuf varint:
149
→ 95 01
Therefore:
sint64 -75
ZigZag:
149
Varint:
95 01
Protobuf uint vs sint
uint32 / uint64
The non-negative integer value is encoded directly as a protobuf varint.
sint32 / sint64
The signed value is ZigZag encoded first, then the resulting unsigned number is encoded as a varint.
Why ZigZag Helps Negative Values
Standard two’s-complement signed integer encodings do not naturally make small negative numbers small when interpreted as unsigned values. ZigZag rearranges the mapping so values close to zero remain close to zero regardless of sign.
That makes sint32 and sint64 efficient when both
small negative and small positive values occur frequently.
Protobuf int32 vs sint32
These protobuf field types are not interchangeable at the wire-value level.
An int32 uses the normal signed integer varint behavior, while
sint32 applies ZigZag encoding first.
Canonical Protobuf Varints
A value has a shortest possible varint representation. For example, zero should normally be represented as:
00
not a longer continuation sequence that eventually resolves to the same numeric value.
The calculator re-encodes decoded values and reports whether the supplied byte sequence matches the shortest canonical varint representation.
64-Bit Protobuf Integer Precision
JavaScript’s ordinary Number type cannot exactly represent every 64-bit integer. This calculator therefore performs integer arithmetic with BigInt.
That allows exact conversion of values throughout the uint64, sint64, uint32 and sint32 ranges supported by this tool.
Protobuf Integer Ranges
| Type | Minimum | Maximum |
|---|---|---|
| uint32 | 0 | 4,294,967,295 |
| uint64 | 0 | 18,446,744,073,709,551,615 |
| sint32 | −2,147,483,648 | 2,147,483,647 |
| sint64 | −9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
How to Decode Protobuf Varint Hex
To decode a varint, remove the continuation bit from each byte and place each seven-bit group at increasing powers of 128.
96 01
0x96 & 0x7F
= 0x16
= 22
0x01 & 0x7F
= 1
Value =
22
+ (1 << 7)
= 22 + 128
= 150
Varint Continuation Bit
The highest bit of every varint byte indicates whether another byte follows.
MSB = 1
→ another varint byte follows
MSB = 0
→ this is the final byte
A stream ending with a byte whose continuation bit remains set is truncated and cannot be decoded as a complete varint.
Common Uses for This Calculator
Protocol Debugging
Check integer bytes copied from protobuf network traffic or diagnostic logs.
Serializer Verification
Compare expected decimal values with generated protobuf byte output.
Embedded Development
Verify lightweight protobuf implementations on microcontrollers.
Reverse Engineering
Inspect wire-level integer values when investigating protobuf data you are authorized to analyze.
Common Protobuf Varint Mistakes
Reading Bytes as Big-Endian
Varint seven-bit groups are arranged least-significant group first.
Forgetting the Continuation Bit
The high bit is control information and is not part of the seven payload bits.
Applying ZigZag to uint Fields
Unsigned protobuf fields use their value directly.
Skipping ZigZag for sint Fields
sint32 and sint64 require ZigZag before varint encoding.
Using JavaScript Number for uint64
Values above the exact integer range of Number can silently lose precision.
Accepting a Truncated Varint
A final byte with its continuation bit still set means more bytes are required.
Protobuf Varint & ZigZag Calculator FAQs
What is a protobuf varint?
How is 150 encoded as a protobuf varint?
What does protobuf varint 96 01 decode to?
How is 300 encoded as a protobuf varint?
What is ZigZag encoding?
What does ZigZag encode −1 to?
What does ZigZag encode 1 to?
What does ZigZag value 1 decode to?
What is the ZigZag value for −75?
How is protobuf sint −75 encoded?
Does uint32 use ZigZag?
Does sint32 use ZigZag?
Does sint64 use ZigZag?
How many bytes can a uint64 protobuf varint require?
What is a protobuf continuation bit?
What is a canonical varint?
Why does this calculator use BigInt?
Is ZigZag the same as two’s complement?
Encode and Decode Protobuf Varints and ZigZag Integers
Enter a decimal integer or protobuf hexadecimal varint to inspect exact unsigned values, ZigZag mappings, byte groups, continuation bits and encoded length for 32-bit or 64-bit Protocol Buffers integer fields.