Named Binary Tags (NBT)

Read and write the tag data Bedrock stores on items.

NBT (Named Binary Tag) is the key/value format Bedrock uses to store structured data - on items, blocks, and entities. Endstone exposes it through endstone.nbt as Python-friendly tag objects, so you read and edit it without touching the binary format.

Tag types

Every value is a typed tag. Scalars hold a single .value; the container tags nest other tags:

TagHolds
ByteTag, ShortTag, IntTag, LongTagan integer
FloatTag, DoubleTaga float
StringTaga string
ByteArrayTag, IntArrayTagan array of integers
ListTaga sequence of tags (all the same type) - list-like
CompoundTaga map of named tags - dict-like

Read an item's NBT

ItemStack.nbt returns a CompoundTag, which behaves like a dict - index it, check membership, iterate items():

# `player` is an endstone.Player
item = player.inventory.item_in_main_hand
if item is None:
    return

tag = item.nbt  # a CompoundTag
for key, value in tag.items():
    player.send_message(f"{key} = {value}")

Reading a scalar back out means going through .value:

if "my_plugin:level" in tag:
    level = tag["my_plugin:level"].value  # an int

Write NBT

Reading nbt gives you a tag to edit; assign it back to nbt to apply the change. Wrap raw values in the matching tag type:

from endstone.nbt import IntTag, StringTag

tag = item.nbt
tag["my_plugin:level"] = IntTag(5)
tag["my_plugin:owner"] = StringTag("Steve")
item.nbt = tag

Namespace your keys (my_plugin:level, not level) so they can't collide with the vanilla data Bedrock keeps on the same item.

Build nested structures

CompoundTag and ListTag nest, so you can build whatever shape you need. Both also construct from plain Python - a dict or an iterable of tags:

from endstone.nbt import CompoundTag, ListTag, IntTag, StringTag

stats = CompoundTag()
stats["kills"] = IntTag(10)

lore = ListTag()
lore.append(StringTag("Forged in fire"))
stats["lore"] = lore

CompoundTag.to_dict() and ListTag.to_list() go the other way, unwrapping a tag tree into plain Python values.

Serialize and load

To persist NBT or move it between systems, dump() writes the binary form and load() reads it back. Bedrock uses little-endian byte order, which is the default:

from endstone.nbt import load

data = tag.dump()              # bytes, little-endian
restored, root_name = load(data)

Pass byte_order="big" for Java-style NBT, or network=True for Bedrock's network varint encoding.

On this page