NBT Format Reference

Supports Minecraft Bedrock Edition and Java Edition — and every server core for both, popular or obscure: Vanilla, Paper, Spigot, Purpur, Folia, Fabric, Forge, NeoForge, Mohist, Sponge, Bedrock Dedicated Server, PocketMine-MP, Nukkit, PowerNukkitX, Cloudburst, Dragonfly, Endstone, LeviLamina and the rest. Full list.

NBT (Named Binary Tag) is Minecraft's binary tree format: a tag is a one-byte type, a length-prefixed name and a payload, and compounds nest until a TAG_End byte closes them. There are 13 tag types and five encodings in circulation across Java and Bedrock. This page documents all of them, and the editor above lets you check any claim against a real file.

13 tag typesBig-endianLittle-endianVarintgzipzlibSNBT

Drop any NBT file to inspect here

level.dat · .nbt · .mcstructure · .schem · .schematic · .dat · chunk dumps

The 13 tag types

IdTagPayloadSNBT
0TAG_EndNone — closes a compound—
1TAG_Byte1 byte, signed −128…1271b
2TAG_Short2 bytes, signed1s
3TAG_Int4 bytes, signed1
4TAG_Long8 bytes, signed1L
5TAG_Float4 bytes, IEEE 7541.0f
6TAG_Double8 bytes, IEEE 7541.0d
7TAG_Byte_Arrayint length, then that many bytes[B;1b,2b]
8TAG_Stringunsigned short length, then UTF-8 bytes"text"
9TAG_Listelement type byte, int length, then payloads with no names[1,2]
10TAG_Compoundtype + name + payload repeated until TAG_End{a:1}
11TAG_Int_Arrayint length, then that many 4-byte ints[I;1,2]
12TAG_Long_Arrayint length, then that many 8-byte longs[L;1L,2L]

A file is a single root TAG_Compound: one type byte 0x0A, a name, then the compound's contents. Named tags appear only inside compounds — list elements carry payloads only, which is why a list is homogeneous.

Five encodings in the wild

EncodingIntegersString lengthRootUsed by
Java (classic)Big-endian fixed width2-byte big-endianNamedJava worlds, structures, schematics
Java network (1.20.2+)Big-endian fixed width2-byte big-endianNamelessJava protocol
BedrockLittle-endian fixed width2-byte little-endianNamedBedrock worlds, .mcstructure, LevelDB values
Bedrock level.datLittle-endian fixed width2-byte little-endianNamed, after an 8-byte headerBedrock world metadata
Bedrock networkZigzag varint for int and longUnsigned varintNamedBedrock protocol

In the varint encoding, TAG_Short, TAG_Float and TAG_Double stay fixed-width little-endian; only TAG_Int and TAG_Long become zigzag varints, and array and list lengths follow whatever TAG_Int does. String lengths are unsigned varints, which also lifts the 65535-byte ceiling that the fixed encodings impose.

Strings: modified UTF-8 versus UTF-8

Java serialises strings with DataOutputStream.writeUTF, which is modified UTF-8: a NUL character is written as C0 80 rather than 00, and characters outside the Basic Multilingual Plane are written as two three-byte surrogate halves (CESU-8) instead of one four-byte sequence. Bedrock uses standard UTF-8. A tool that assumes one encoding for both will corrupt emoji and some CJK text on save — this editor encodes per format, which is why a world named with an emoji survives a round trip here.

Compression

NBT itself is not compressed; the container decides. Java files are usually gzip (magic 1F 8B), chunk payloads inside region files are zlib (magic 78 01, 78 9C or 78 DA), and Bedrock stores level.dat and structure files uncompressed. Detection is by magic bytes, so the same parser handles all three — and a file saved with the wrong compression is the single most common reason a hand-edited world will not load.

A minimal file, byte by byte

The canonical hello_world.nbt: a root compound named hello world holding one string tag name with the value Bananrama. In Java's big-endian encoding:

0A                          TAG_Compound
00 0B 68 65 6C 6C 6F 20 77 6F 72 6C 64   name length 11, "hello world"
   08                       TAG_String
   00 04 6E 61 6D 65        name length 4, "name"
   00 09 42 61 6E 61 6E 72 61 6D 61      value length 9, "Bananrama"
00                          TAG_End

The same document in Bedrock's little-endian encoding differs only in the byte order of the two length fields: 0B 00 instead of 00 0B. In Bedrock network NBT the lengths become single varint bytes, 0B and 04, with no padding at all. Drop any of the three into the editor above and it will tell you which one it received.

SNBT

SNBT is NBT written as text, and it is what commands consume: /data merge entity @s {Invulnerable:1b}. Type suffixes are what keep it lossless — b byte, s short, L long, f float, d double, none for int — and typed array literals are written [B;…], [I;…], [L;…]. The editor exports SNBT from any loaded file, which makes two versions of a world diffable in a normal text diff.

Frequently Asked Questions

Is there an official NBT specification?

No formal spec from Mojang. The format was documented by Notch in 2010 and has been maintained by the community since; the tag ids and layout on this page match what the game reads and writes today.

Why does Bedrock use little-endian?

Bedrock's engine is C++ and targets little-endian hardware, so it stores values in native order. Java's serialisation is big-endian because that is what the Java DataOutput contract specifies.

What is zigzag varint encoding?

A way of writing integers in as few bytes as possible while keeping negatives short: the sign is folded into the low bit, so −1 encodes as 1 and 1 encodes as 2. Bedrock's protocol uses it for ints and longs.

Can a TAG_List hold mixed types?

No. A list declares one element type and every entry has to match it. Mixed data needs a list of compounds.

What is the maximum string length?

65535 bytes in the fixed encodings, because the length field is an unsigned short. The varint network encoding has no practical limit.

Related tools