Tiny, liberally-licensed NBT library. NBT is the datafile format used in Minecraft and Voxel.
Switch branches/tags
Clone or download
Pull request Compare This branch is 1 commit ahead, 8 commits behind TkTech:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



PyNBT is a tiny, liberally licenced (MIT) NBT library. It supports reading and writing big endian or little endian NBT files.

Using the Library

Using the library in your own programs is simple and is capable of reading, modifying, and saving NBT files.


NOTE: Beginning with version 1.1.0, names are optional for TAG_*'s that are added to a TAG_Compound, as they will be given the same name as their key. If you do specify a name, it will be used instead. This breaks compatibility with old code, as the position of the name and value parameter have now swapped.

from pynbt import NBTFile, TAG_Long, TAG_List, TAG_String

value = {
    'long_test': TAG_Long(104005),
    'list_test': TAG_List(TAG_String, [

nbt = NBTFile(value=value)
with open('out.nbt', 'wb') as io:


Reading is simple, and will accept any file-like object providing read(). Simply pretty-printing the file created from the example under writing:

from pynbt import NBTFile

with open('out.nbt', 'rb') as io:
  nbt = NBTFile(io)

This produces the output:

TAG_Compound(''): 2 entries
  TAG_Long('long_test'): 104005
  TAG_List('list_test'): 3 entries
    TAG_String(None): 'Timmy'
    TAG_String(None): 'Billy'
    TAG_String(None): 'Sally'

Every tag exposes a minimum of two fields, .name and .value. Every tag's value maps to a plain Python type, such as a dict() for TAG_Compound and a list() for TAG_List. Every tag also provides complete __repr__ methods for printing. This makes traversal very simple and familiar to existing Python developers.

with open('out.nbt', 'rb') as io:
  nbt = NBTFile(io)
  # Iterate over every TAG in the root compound as you would any other dict
  for name, tag in nbt.items():
      print(name, tag)

  # Print every tag in a list
  for tag in nbt['list_test']:


These changelogs are summaries only and not comprehensive. See the commit history between tags for full changes.


  • Added support for TAG_Long_Array


  • Removed pocket detection helpers and RegionFile, leaving PyNBT to only handle NBT.
  • Added a simple unicode test.


  • Internal cleanups in nbt.py to ease some C work.
  • NBTFile.__init__() and NBTFile.save()'s arguments have changed. For most cases changing compressed=True to NBTFIle.Compression.GZIP will suffice.
  • NBTFile.__init__() and NBTFile.save() no longer accept paths, instead accepting only file-like objects implementing read() and write(), respectively.
  • name must now be provided at construction or before saving of an NBTFile() (defaults to None instead of '').


  • TAG_List's values no longer need to be TAG_* objects. They will be converted when the tag is saved. This allows much easier lists of native types.


  • Internal code cleanup. Breaks compatibility with pocket loading and saving (to be reimplemented as helpers).
  • Slight speed improvements.
  • TAG_List can now be treated as a plain python list (.value points to self)


  • Breaks compatibility with older code, but allows much more convenient creation of TAG_Compound. name and value have in most cases swapped spots.
  • name is now the last argument of every TAG_*, and optional for children of a TAG_Compound. Instead, they'll be given the key they're assigned to as a name.
  • TAG_Compounds can now be treated like dictionaries for convienience. .value simply maps to itself.


  • Small bugfixes.
  • Adds support for TAG_Int_Array.


  • First release.