NBT

The Named Binary Tag (NBT) file format is an extremely simple, albeit annoying (did we really need yet another format?)[See Discussion] structured binary format used by the Minecraft game for a variety of things. Due to this, several third-party utilities now also utilize the format. You may find example files at the bottom of this article.

Unless you have specific goals or licence requirements, it is extremely recommended to go with one of the existing libraries.

Utilities

Almost every 3rd-party Minecraft application uses NBT on some level. There also exist several dedicated NBT editors, which will likely be useful to you if you are developing an NBT library of your own. These include:

Specification

The NBT file format is extremely simple, and writing a library capable of reading/writing it is a simple affair. There are 11 datatypes supported by this format, and one type used to close compound tags. It is strongly advised to read this entire section or you may run into issues.

Type ID

Type Name

Payload Size (Bytes)

Description

0

TAG_End

0

Signifies the end of a TAG_Compound. It is only ever used inside a TAG_Compound, and is not named despite being in a TAG_Compound

A length-prefixed array of signed bytes. The prefix is a signed integer (thus 4 bytes)

8

TAG_String

...

A length-prefixed UTF-8 string. The prefix is an unsigned short (thus 2 bytes) signifying the length of the string in bytes

9

TAG_List

...

A list of nameless tags, all of the same type. The list is prefixed with the Type ID of the items it contains (thus 1 byte), and the length of the list as a signed integer (a further 4 bytes). If the length of the list is 0 or negative, the type may be 0 (TAG_End) but otherwise it must be any other type. (The notchian implementation uses TAG_End in that situation, but another reference implementation by Mojang uses 1 instead; parsers should accept any type if the length is <= 0).

10

TAG_Compound

...

Effectively a list of a named tags. Order is not guaranteed.

11

TAG_Int_Array

...

A length-prefixed array of signed integers. The prefix is a signed integer (thus 4 bytes) and indicates the number of 4 byte integers.

12

TAG_Long_Array

...

A length-prefixed array of signed longs. The prefix is a signed integer (thus 4 bytes) and indicates the number of 8 byte longs.

There are a couple of simple things to remember:

The datatypes representing numbers are in big-endian in the PC version, but Pocket Version is in little-endian. Unless you're using Java, you will most likely have to swap it to little-endian. See the Wikipedia article on Endianness.

Every NBT file will always implicitly be inside a tag compound, and also begin with a TAG_Compound

The structure of a NBT file is defined by the TAG_List and TAG_Compound types, as such a tag itself will only contain the payload, but depending on what the tag is contained within may contain additional headers. I.e. if it's inside a Compound, then each tag will begin with the TAG_id, and then a string (the tag's name), and finally the payload. While in a list it will be only the payload, as there is no name and the tag type is given in the beginning of the list.

For example, here's the example layout of a TAG_Short on disk:

Type ID

Length of Name

Name

Payload

Decoded

2

9

shortTest

32767

On Disk (in hex)

02

00 09

73 68 6F 72 74 54 65 73 74

7F FF

If this TAG_Short had been in a TAG_List, it would have been nothing more than the payload, since the type is implied and tags within the first level of a list are nameless.

Examples

There are two defacto example files used for testing your implementation (test.nbt & bigtest.nbt), originally provided by Markus. The example output provided below was generated using PyNBT's debug-nbt tool.

test.nbt

This first example is an uncompressed "Hello World" NBT example. Should you parse it correctly, you will get a structure similar to the following:

bigtest.nbt

This second example is a gzip compressed test of every available tag. If your program can successfully parse this file, then you've done well. Note that the tags under TAG_List do not have a name, as mentioned above.

servers.dat

The servers.dat file contains a list of multiplayer servers you've added to the game. To mix things up a bit, this file will always be uncompressed. Below is an example of the structure seen in servers.dat.