Skip to content

Every field in a Protobuf message starts with a tag. That tag is the only reason the decoder knows which field it's looking at and how to read the bytes that follow.

Tag Composition

A tag is a single Varint that combines two pieces of information:

  • Field Number (bits 3 through N)
  • Wire Type (the bottom 3 bits)

The formula for the tag value is (field_number << 3) | wire_type. Small field numbers fit in a single byte. Larger ones, 16 and above, spill into additional bytes under the same continuation rule varints always follow.

Tag structure

A tag packs two facts into a single number, the field number and the wire type. The lowest three bits hold the wire type. Everything above them holds the field number.

One number, two parts

(1 << 3) | 2 = 10
0
0
0
0
1
Field number = 1
0
1
0
Wire type = 2 (LEN)

Encoded as a varint

10 → 1 Byte(s)
Byte 00x0A
0
0
0
0
1
0
1
0
MSB7-Bit Value Chunk

Further Reading

Next

Wire Types

The Protobuf wire types: VARINT, I64, LEN, and I32, what each one carries, and how length-delimited encoding wraps strings, bytes, and sub-messages.