Data types
This article defines the data types used in the protocol. All data sent over the network (except for VarInt and VarLong) is bigendian, that is the bytes are sent from most significant byte to least significant byte. The majority of everyday computers are littleendian, therefore it may be necessary to change the endianness before sending data over the network.
Definitions
Name  Size (bytes)  Encodes  Notes 

Boolean  1  Either false or true  True is encoded as 0x01 , false as 0x00 .

Byte  1  An integer between 128 and 127  Signed 8bit integer, two's complement 
Unsigned Byte  1  An integer between 0 and 255  Unsigned 8bit integer 
Short  2  An integer between 32768 and 32767  Signed 16bit integer, two's complement 
Unsigned Short  2  An integer between 0 and 65535  Unsigned 16bit integer 
Int  4  An integer between 2147483648 and 2147483647  Signed 32bit integer, two's complement 
Long  8  An integer between 9223372036854775808 and 9223372036854775807  Signed 64bit integer, two's complement (Actually a C Long Long) 
Float  4  A singleprecision 32bit IEEE 754 floating point number  
Double  8  A doubleprecision 64bit IEEE 754 floating point number  
String (n)  ≥ 1 ≤ (n×4) + 3 
A sequence of Unicode scalar values  UTF8 string prefixed with its size in bytes as a VarInt. Maximum length of n characters, which varies by context; up to n × 4 bytes can be used to encode n characters and both of those limits are checked. Maximum n value is 32767. The + 3 is due to the max size of a valid length VarInt.

Chat  ≥ 1 ≤ (32767×4) + 3 
See Chat  Encoded as a String with max length of 32767. 
VarInt  ≥ 1 ≤ 5 
An integer between 2147483648 and 2147483647  Variablelength data encoding a two's complement signed 32bit integer; more info in their section 
VarLong  ≥ 1 ≤ 10 
An integer between 9223372036854775808 and 9223372036854775807  Variablelength data encoding a two's complement signed 64bit integer; more info in their section 
Chunk Section  Varies  A 16×16×16 chunk of blocks  See SMP Map Format 
Entity Metadata  Varies  Miscellaneous information about an entity  See Entities#Entity Metadata Format 
Slot  Varies  An item stack in an inventory or container  See Slot Data 
NBT Tag  Varies  Depends on context  See NBT 
Position  8  An integer/block position: x (33554432 to 33554431), y (2048 to 2047), z (33554432 to 33554431)  x as a 26bit integer, followed by y as a 12bit integer, followed by z as a 26bit integer (all signed, two's complement). See also the section below. 
Angle  1  A rotation angle in steps of 1/256 of a full turn  Whether or not this is signed does not matter, since the resulting angles are the same. 
UUID  16  A UUID  Encoded as an unsigned 128bit integer (or two unsigned 64bit integers: the most significant 64 bits and then the least significant 64 bits) 
Optional X  0 or size of X  A field of type X, or nothing  Whether or not the field is present must be known from the context. 
Array of X  count times size of X  Zero or more fields of type X  The count must be known from the context. 
X Enum  size of X  A specific value from a given list  The list of possible values and how each is encoded as an X must be known from the context. An invalid value sent by either side will usually result in the client being disconnected with an error or even crashing. 
Byte Array  Varies  Depends on context  This is just a sequence of zero or more bytes, its meaning should be explained somewhere else, e.g. in the packet description. The length must also be known from the context. 
VarInt and VarLong
Variablelength format such that smaller numbers use fewer bytes. These are very similar to Protocol Buffer Varints: the 7 least significant bits are used to encode the value and the most significant bit indicates whether there's another byte after it for the next part of the number. The least significant group is written first, followed by each of the more significant groups; thus, VarInts are effectively little endian (however, groups are 7 bits, not 8).
VarInts are never longer than 5 bytes, and VarLongs are never longer than 10 bytes.
Pseudocode to read and write VarInts and VarLongs:
public static int readVarInt() {
int numRead = 0;
int result = 0;
byte read;
do {
read = readByte();
int value = (read & 0b01111111);
result = (value << (7 * numRead));
numRead++;
if (numRead > 5) {
throw new RuntimeException("VarInt is too big");
}
} while ((read & 0b10000000) != 0);
return result;
}
public static long readVarLong() {
int numRead = 0;
long result = 0;
byte read;
do {
read = readByte();
int value = (read & 0b01111111);
result = (value << (7 * numRead));
numRead++;
if (numRead > 10) {
throw new RuntimeException("VarLong is too big");
}
} while ((read & 0b10000000) != 0);
return result;
}
public static void writeVarInt(int value) {
do {
byte temp = (byte)(value & 0b01111111);
// Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
value >>>= 7;
if (value != 0) {
temp = 0b10000000;
}
writeByte(temp);
} while (value != 0);
}
public static void writeVarLong(long value) {
do {
byte temp = (byte)(value & 0b01111111);
// Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone
value >>>= 7;
if (value != 0) {
temp = 0b10000000;
}
writeByte(temp);
} while (value != 0);
}
Note that Minecraft's VarInts are not encoded using Protocol Buffers; it's just similar. If you try to use Protocol Buffers Varints with Minecraft's VarInts, you'll get incorrect results in some cases. The major differences:
 Minecraft's VarInts are all signed, but do not use the ZigZag encoding. Protocol buffers have 3 types of Varints:
uint32
(normal encoding, unsigned),sint32
(ZigZag encoding, signed), andint32
(normal encoding, signed). Minecraft's are theint32
variety. Because Minecraft uses the normal encoding instead of ZigZag encoding, negative values always use the maximum number of bytes.  Minecraft's VarInts are never be longer than 5 bytes and its VarLongs will never be longer than 10 bytes, while Protocol Buffer Varints will always use 10 bytes when encoding negative numbers, even if it's an
int32
.
Sample VarInts:
Value  Hex 

0  0x00 
1  0x01 
2  0x02 
127  0x7f 
128  0x80 0x01 
255  0xff 0x01 
2147483647  0xff 0xff 0xff 0xff 0x07 
1  0xff 0xff 0xff 0xff 0x0f 
2147483648  0x80 0x80 0x80 0x80 0x08 
Sample VarLongs:
Value  Hex 

0  0x00 
1  0x01 
2  0x02 
127  0x7f 
128  0x80 0x01 
255  0xff 0x01 
2147483647  0xff 0xff 0xff 0xff 0x07 
9223372036854775807  0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x7f 
1  0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x01 
2147483648  0x80 0x80 0x80 0x80 0xf8 0xff 0xff 0xff 0xff 0x01 
9223372036854775808  0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x01 
Position
64bit value split in to three parts
 x: 26 MSBs
 z: 26 LSBs
 y: 12 bits between them
Encoded as followed:
((x & 0x3FFFFFF) << 38)  ((y & 0xFFF) << 26)  (z & 0x3FFFFFF)
And decoded as:
val = read_unsigned_long(); x = val >> 38; y = (val >> 26) & 0xFFF; z = val << 38 >> 38;
Note: The details of bit shifting are rather language dependent; the above may work in Java but probably won't in other languages without some tweaking. In particular, you will usually receive positive numbers even if the actual coordinates are negative. This can be fixed by adding something like the following:
if x >= 2^25 { x = 2^26 } if y >= 2^11 { y = 2^12 } if z >= 2^25 { z = 2^26 }
Fixedpoint numbers
Some fields may be stored as fixedpoint numbers, where a certain number of bits represents the signed integer part (number to the left of the decimal point) and the rest represents the fractional part (to the right). Floating points (float and double), in contrast, keep the number itself (mantissa) in one chunk, while the location of the decimal point (exponent) is stored beside it.
Essentially, while fixedpoint numbers have lower range than floating points, their fractional precision is greater for higher values. This makes them ideal for representing global coordinates of an entity in Minecraft, as it's more important to store the integer part accurately than position them more precisely within a single block (or meter).
Coordinates are often represented as a 32bit integer, where 5 of the leastsignificant bits are dedicated to the fractional part, and the rest store the integer part.
Java lacks support for fractional integers directly, but you can represent them as integers. To convert from a double to this integer representation, use the following formulas:
abs_int = (int)double * 32;
And back again:
double = (double)abs_int / 32;