Wiki 9Minecraft Wiki 9Minecraft

About NBT (Named Binary Tag)

How Bedrock Edition stores structured binary data for worlds, structures, and entities.

5Sections
2Code examples
3Known errors

Named Binary Tag (NBT) is the tree-based binary format Minecraft uses to serialize dynamic game data to disk. In Bedrock Edition add-on development, you rarely edit raw NBT by hand, because the game lacks direct NBT access in slash commands. However, you interact with NBT whenever you export structure files, configure world templates, or look for modern alternatives to persist custom state in a behaviour pack.

What NBT Is and How Bedrock Uses It

NBT is essentially a binary equivalent of JSON, designed to be compact and fast for the game engine to read and write. Every piece of data in an NBT tree is a tag consisting of a numeric type ID, a string name, and a payload. While JSON is used for static definitions inside your behaviour and resource packs, NBT is used by the engine to save the live state of a world.

Unlike Java Edition, which stores chunks in region files and uses Big-Endian byte ordering for its NBT, Bedrock Edition stores nearly all world, entity, and chunk NBT payloads inside a LevelDB key-value database using Little-Endian byte ordering. The only standalone NBT files you will regularly encounter on disk are level.dat (which holds global world settings and contains an 8-byte header before the binary payload begins) and exported .mcstructure files inside a behaviour pack.

NBT Tag Types

When inspecting a .mcstructure file or a world save in an external NBT editor, every node in the tree has a specific data type. Unlike JSON, which treats all numbers as generic values, NBT strictly separates integers by bit width and distinguishes floating-point precision.

Understanding these types matters if you use external tools to modify structure files—for example, changing a tag from a Byte to an Int will cause the game engine to ignore the value when it loads the file.

IDTag NamePayload Description
0TAG_EndMarks the end of a TAG_Compound; has no name or payload.
1TAG_ByteAn 8-bit signed integer (-128 to 127), also used for boolean flags (0 or 1).
2TAG_ShortA 16-bit signed integer.
3TAG_IntA 32-bit signed integer.
4TAG_LongA 64-bit signed integer, commonly used for unique entity IDs and timestamps.
5TAG_FloatA 32-bit single-precision floating-point number, used for rotations and health.
6TAG_DoubleA 64-bit double-precision floating-point number.
7TAG_Byte_ArrayA length-prefixed array of signed 8-bit bytes.
8TAG_StringA UTF-8 string prefixed by its byte length as an unsigned 16-bit integer.
9TAG_ListAn ordered list of unnamed tags that must all share the exact same Tag ID.
10TAG_CompoundA dictionary of named tags of any type, closed by a TAG_End.
11TAG_Int_ArrayA length-prefixed array of 32-bit signed integers.
12TAG_Long_ArrayA length-prefixed array of 64-bit signed integers.

Where Add-on Creators Encounter NBT

Inside a standard behaviour pack, the only raw NBT files are structure files located in the BP/structures/ folder. When you save a region of blocks and entities using a Structure Block in-game and export it to disk, Bedrock writes an uncompressed Little-Endian TAG_Compound with the .mcstructure extension.

A .mcstructure file contains the dimensions of the saved volume, a block palette mapping runtime indices to block names and their block states, a 3D positional grid of those indices, block entity data (such as chest inventories or sign text), and full entity snapshots. Add-on creators occasionally open these files in an NBT editor to strip out unwanted entities, clean up temporary structure_void blocks, or manually edit a loot table path inside a saved container.

Command JSON Equivalents to NBT

Creators coming from other platforms often try to pass raw NBT strings into commands like /give or /replaceitem to set item lore, enchantments, or custom names. Bedrock Edition does not parse raw NBT in commands. Instead, its command parser accepts a strict JSON object with a tiny set of supported item components.

Through commands, you can only assign minecraft:can_place_on, minecraft:can_destroy, minecraft:item_lock, and minecraft:keep_on_death. To apply custom names, lore, or enchantments without external NBT editors, you must use the Script API or define a loot table inside your behaviour pack.

BP/loot_tables/chests/custom_gear.json
{
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "item",
          "name": "minecraft:diamond_pickaxe",
          "functions": [
            {
              "function": "set_name",
              "name": "Excavator's Pick"
            },
            {
              "function": "set_lore",
              "lore": [
                "Can break deepslate",
                "Soulbound to owner"
              ]
            },
            {
              "function": "enchant_with_levels",
              "levels": {
                "min": 20,
                "max": 30
              },
              "treasure": true
            }
          ]
        }
      ]
    }
  ]
}

Storing Custom Data Without Direct NBT Access

Because you cannot read or write arbitrary NBT tags on entities, items, or worlds during gameplay, Bedrock provides two official systems to persist custom add-on state: Entity Properties (defined in the entity JSON and readable via Molang) and Dynamic Properties (read and written via the @minecraft/server Script API).

When you call setDynamicProperty in script, the Bedrock engine serializes your string, number, boolean, or Vector3 directly into the entity, item stack, or world NBT payload inside the LevelDB save. This gives you the permanence of NBT storage while keeping your data sandboxed to your behaviour pack's manifest UUID.

BP/scripts/main.js
import { world } from "@minecraft/server";

world.afterEvents.entityHitEntity.subscribe((event) => {
  const { damagingEntity, hitEntity } = event;
  if (damagingEntity.typeId !== "minecraft:player") return;

  const currentHits = hitEntity.getDynamicProperty("my_pack:hit_count") ?? 0;
  const nextHits = currentHits + 1;

  hitEntity.setDynamicProperty("my_pack:hit_count", nextHits);
  damagingEntity.sendMessage(`Target hit count saved to NBT: ${nextHits}`);
});

Which versions this applies to

Applies to all modern Bedrock Edition versions. Little-Endian NBT in .mcstructure files and LevelDB world saves is foundational to the engine. Script API Dynamic Properties (the supported way to write custom persistent data) are stable in @minecraft/server 1.7.0+ (Bedrock 1.20.50 and later) and do not require any experimental toggles.

When it does not work

What you seeWhyThe fix
Syntax error: Unexpected "{": at "diamond_sword 1 0 >>{<<display:{Name..." when running /give or /replaceitem.You attempted to use Java Edition raw NBT syntax in a Bedrock command. Bedrock commands only accept a small JSON object for item components like minecraft:can_place_on or minecraft:keep_on_death.Move item customization (custom names, lore, enchantments, durability) into a behaviour pack loot table and spawn the item using /loot, or manipulate the ItemStack via the Script API.
A .mcstructure file fails to load via the /structure command or crashes the world after being edited in an external NBT tool.Many NBT editors default to Java Edition's format (GZip-compressed, Big-Endian byte order). Bedrock .mcstructure files must be saved as uncompressed, Little-Endian NBT.Ensure your NBT editor is explicitly set to write uncompressed Little-Endian binary before saving changes to any .mcstructure file.
World refuses to open or resets its settings after manually editing level.dat.Bedrock's level.dat is not a pure NBT file; it begins with an 8-byte header consisting of a 32-bit storage version integer and a 32-bit payload byte-length integer.Only edit level.dat with an NBT editor that natively supports the Bedrock level.dat header and automatically recalculates the byte-length integer upon saving.

Reference, straight from the game files

Read out of the game itself, so the ids match the version you are building for.