Add custom NBT tags to Items/Tiles/Entities without NMS! Modify NBT and store it Files, other NBT or as String in yaml/json/SQL/Redis.
Server Owner/Developer Wiki
Import the API using Maven, then check out the basic usage or code examples like working with Skulls.
Unsupported
Required
Terms for using, modifying and redistributing this product.
06.04.2026 · Modrinth
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.15.6...2.15.7
Screenshots and images from the original Modrinth page.

Published versions and original Modrinth files.
06.04.2026 · 37 600 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.15.6...2.15.7
28.03.2026 · 2 945 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.15.5...2.15.6
09.12.2025 · 26 637 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.15.4...2.15.5
09.12.2025 · 257 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.15.3...2.15.4
11.10.2025 · 12 958 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.15.2...2.15.3
26.08.2025 · 8 562 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.15.1...2.15.2
01.07.2025 · 12 806 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.15.0...2.15.1
17.04.2025 · 23 011 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.14.1...2.15.0
16.12.2024 · 35 275 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.14.0...2.14.1
02.11.2024 · 11 938 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.13.2...2.14.0
10.08.2024 · 14 318 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.13.1...2.13.2
20.06.2024 · 25 411 downloads
@Nullable flag to resolveCompoundIf you have questions about how to migrate your code away from NBTItem or how to support 1.20.5+ with the new ItemStack logic, check out the updated wiki! SoSeDiK did an amazing job updating the wiki, including many updated examples. Also, feel free to PR your plugin to the Plugin list on the wiki.
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.13.0...2.13.1
13.06.2024 · 2 702 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.12.4...2.13.0
30.04.2024 · 10 222 downloads
NBT.itemStackFromNBT and the related methods (it will assume the NBT is 1.20.4 data, otherwise upgrade the NBT before yourself with the Datafixer)Due to Mojang changes to how ItemStacks work at runtime, vanilla NBT won't be visible on loaded ItemStacks in 1.20.5+ anymore. So modifying vanilla data will not work anymore in the same way as for 1.8-1.20.4, and all plugins need to be updated to be aware of that. If in doubt, feel free to ask on Discord.
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.12.3...2.12.4
24.03.2024 · 7 546 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.12.2...2.12.3
10.12.2023 · 23 413 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.12.1...2.12.2
04.11.2023 · 7 088 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.12.0...2.12.1
21.09.2023 · 7 135 downloads
Hello everyone, this is the by far biggest NBTAPI update so far. This release contains 100 commits of the total 580 total commits(17% of all commits of the past 7 years?!?), so strap in for the changes.
(Also small reminder that supporting the dev behind this project would be really nice, especially when you use this API to make paid Plugins 😅)
. separated strings to keys like tag.othertag.key (see below for examples){} tagset(String key, T value, NBTHandler<T> handler) method to set your custom data with the provided handlerget(String key, NBTHandler<T> handler) method to get your custom data with the provided handlerThis release has a lot of performance optimizations under the hood, mainly for the NBT.get and NBT.modify methods for ItemStacks/Entities/BlockEntities. I highly encourage everyone to start updating their NBTItem/NBTEntity/NBTTileEntity code to use these new methods.
All benchmarks are done on Paper-171 on my local PC with 2.11.3 vs 2.12.0-RC1. The numbers are how often the test case was able to run in one second(the JVM did have some warmup time before on these methods). But since it's just one run there is probably a +-5% margin of error on these values, they are just there to get a rough idea.
Link to the code that runs. The legacy tests use new NBTItem, while the others use the NBT class. Both tests get/set the same data, just changing between the old and new syntax!
NMS-Backed Itemstacks:
* LegacyGet: 880.620 -> 909.369 = ~3% faster
* NBT.get: 884.326 -> 4.214.210 = ~376% faster
* LegacySet: 762.453 -> 804.732 = ~5% faster
* NBT.modify: 298.238 -> 1.781.667 = ~497% faster
Bukkit-only Itemstacks:
* LegacyGet: 215.992 -> 202.413 = ~6% slower
* NBT.get: 223.998 -> 649.626 = ~190% faster
* LegacySet: 229.485 -> 239.910 = ~4% faster
* NBT.modify: 166.048 -> 567.107 = 241% faster
Basically, switch to the new NBT.get/NBT.modify method and get at least 200% more performance compared to before.
To get a better idea on the performance of using the NBTAPI to store data on items vs Spigots Persistent Data Container API I checked and compared these too. Again, Paper-171 on 2.12.0-RC1. On NMS-Backed Itemstacks normal PDC is about the same speed as NBT.get. Only when caching the NamespacedKey in a final class field PDC pulls ahead. Writing data, especially on Bukkit-only items is a lot slower, but still easily 500.000+ times per second, so doubt that it's much of an issue(especially for gaining a way more flexible API and pre-1.14 support).
To simplify working with deeply nested NBT, resolve methods now allow directly getting or working with these tags.
Compounds are separated by .. In case you need a . inside a key, it can be escaped with a \.
Examples:
// sets foo/bar/baz/test to 42
nbt.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
// gets the value we just set or 0
nbt.resolveOrDefault("foo.bar.baz.test", 0);
// gets the value we just set or null
nbt.resolveOrNull("foo.bar.baz.test", int.class);
// example of a key with a . in it. Sets the key foo/some.key/baz/other
nbt.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123)
// get a tag or null when it's not there
nbt.resolveCompound("some.nested.key");
This is a preview feature contained in this release, and the API might change depending on feedback/development. It allows defining an Interface with normal methods/default methods, and the NBTAPI wraps the NBT with an automatically generated implementation of this Interface.
Methods starting with has/get/set will be interpreted as their respective calls:
public boolean hasKills(); runs return nbt.hasTag("kills");
public void setKills(int amount); runs nbt.setInteger("kills", amount);
public int getKills(); runs return nbt.getInteger("kills");
Default methods like
public default void addKill() {
setKills(getKills() + 1);
}
inside the interface are supported. Also having a getter return another Interface that also extends NBTProxy is supported.
To support other datatypes like ItemStacks, the init method can be overwritten with a default method, using the registerHandler method to add handlers. For example:
@Override
default void init() {
registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
}
To now use your interface, just call NBT.modify or NBT.readNbt like this:
NBT.modify(item, TestInterface.class, ti -> {
ti.addKill();
//or any other method from your interface
});
// This instance can only run read-only methods. Calling any setter will cause an exception
TestInterface yourInterface = NBT.readNbt(item, TestInterface.class);
yourInterface .getKills();
For the complete example check the built-in startup test or the WIP NBT-ItemMeta proxy. Also feel free to ask on Discord.
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.11.3...2.12.0-RC1
10.09.2023 · 675 downloads
Hello everyone, this is the by far biggest NBTAPI update so far, that's why I decided to have a Minecraft-style Release Candidate before the full 2.12.0 release(best-case without any changes). This release contains 84 commits of the total 563 total commits(nearly 15% of all commits of the past 6-7 years?!?), so strap in for the changes.
(Also small reminder that supporting the dev behind this project would be really nice, especially when you use this API to make paid Plugins 😅)
. separated strings to keys like tag.othertag.key (see below for examples){} tagset(String key, T value, NBTHandler<T> handler) method to set your custom data with the provided handlerget(String key, NBTHandler<T> handler) method to get your custom data with the provided handlerThis release has a lot of performance optimizations under the hood, mainly for the NBT.get and NBT.modify methods for ItemStacks/Entities/BlockEntities. I highly encourage everyone to start updating their NBTItem/NBTEntity/NBTTileEntity code to use these new methods.
All benchmarks are done on Paper-171 on my local PC with 2.11.3 vs 2.12.0-RC1. The numbers are how often the test case was able to run in one second(the JVM did have some warmup time before on these methods). But since it's just one run there is probably a +-5% margin of error on these values, they are just there to get a rough idea.
Link to the code that runs. The legacy tests use new NBTItem, while the others use the NBT class. Both tests get/set the same data, just changing between the old and new syntax!
NMS-Backed Itemstacks:
* LegacyGet: 880.620 -> 909.369 = ~3% faster
* NBT.get: 884.326 -> 4.214.210 = ~376% faster
* LegacySet: 762.453 -> 804.732 = ~5% faster
* NBT.modify: 298.238 -> 1.781.667 = ~497% faster
Bukkit-only Itemstacks:
* LegacyGet: 215.992 -> 202.413 = ~6% slower
* NBT.get: 223.998 -> 649.626 = ~190% faster
* LegacySet: 229.485 -> 239.910 = ~4% faster
* NBT.modify: 166.048 -> 567.107 = 241% faster
Basically, switch to the new NBT.get/NBT.modify method and get at least 200% more performance compared to before.
To get a better idea on the performance of using the NBTAPI to store data on items vs Spigots Persistent Data Container API I checked and compared these too. Again, Paper-171 on 2.12.0-RC1. On NMS-Backed Itemstacks normal PDC is about the same speed as NBT.get. Only when caching the NamespacedKey in a final class field PDC pulls ahead. Writing data, especially on Bukkit-only items is a lot slower, but still easily 500.000+ times per second, so doubt that it's much of an issue(especially for gaining a way more flexible API and pre-1.14 support).
To simplify working with deeply nested NBT, resolve methods now allow directly getting or working with these tags.
Compounds are separated by .. In case you need a . inside a key, it can be escaped with a \.
Examples:
// sets foo/bar/baz/test to 42
nbt.resolveOrCreateCompound("foo.bar.baz").setInteger("test", 42);
// gets the value we just set or 0
nbt.resolveOrDefault("foo.bar.baz.test", 0);
// gets the value we just set or null
nbt.resolveOrNull("foo.bar.baz.test", int.class);
// example of a key with a . in it. Sets the key foo/some.key/baz/other
nbt.resolveOrCreateCompound("foo.some\\.key.baz").setInteger("other", 123)
// get a tag or null when it's not there
nbt.resolveCompound("some.nested.key");
This is a preview feature contained in this release, and the API might change depending on feedback/development. It allows defining an Interface with normal methods/default methods, and the NBTAPI wraps the NBT with an automatically generated implementation of this Interface.
Methods starting with has/get/set will be interpreted as their respective calls:
public boolean hasKills(); runs return nbt.hasTag("kills");
public void setKills(int amount); runs nbt.setInteger("kills", amount);
public int getKills(); runs return nbt.getInteger("kills");
Default methods like
public default void addKill() {
setKills(getKills() + 1);
}
inside the interface are supported. Also having a getter return another Interface that also extends NBTProxy is supported.
To support other datatypes like ItemStacks, the init method can be overwritten with a default method, using the registerHandler method to add handlers. For example:
@Override
default void init() {
registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
}
To now use your interface, just call NBT.modify or NBT.readNbt like this:
NBT.modify(item, TestInterface.class, ti -> {
ti.addKill();
//or any other method from your interface
});
// This instance can only run read-only methods. Calling any setter will cause an exception
TestInterface yourInterface = NBT.readNbt(item, TestInterface.class);
yourInterface .getKills();
For the complete example check the built-in startup test or the WIP NBT-ItemMeta proxy. Also feel free to ask on Discord.
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.11.3...2.12.0-RC1
07.06.2023 · 14 401 downloads
More features like Mojang mapped jars/Folia support and a cleaner way to access data using interfaces are on the way. You should consider joining the discord to join the discussion.
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.11.2...2.11.3
16.03.2023 · 10 450 downloads
14.12.2022 · 13 414 downloads
Full Changelog: https://github.com/tr7zw/Item-NBT-API/compare/2.11.0...2.11.1
11.12.2022 · 955 downloads
New major NBTAPI release, adding 1.19.3 support and a new way to interact with the API.
Changes:
- 1.19.3 support
- Added interfaces to most nbt logic, including read-only versions
- Added a new utility class NBT, which provides clean lambda access to read and write NBT. https://github.com/tr7zw/Item-NBT-API/wiki/Using-the-NBT-API has updated examples on how to use this class.
- Utility readFrom/saveTo methods to NBTFile
- hasTag as alternative for hasKey, returning boolean instead of Boolean
- Added getOrDefault method
- Added getOrNull method
- Deprecated setObject/getObject, please do the serialization yourself using your preferred lib/settings
- getUUID/setUUID now will handle pre-1.16 and post-1.16 formats correctly on their own
- getItemStack will now return null if the tag is not found
- getKeys is now a copy of the Set, and no longer linked to NMS internal objects
- Added setItemStackArray/getItemStackArray methods
- Added modifyMeta methods to ItemStacks. Do not modify the NBT while inside the modifyMeta scope
- The wiki is now inside the Github repository, so anyone can make pull requests to add examples, clarifications etc.
- NBTItem now will correctly reject ItemStacks of size 0
- Updated a lot of Javadoc
- The full API Javadoc is now available under https://tr7zw.github.io/Item-NBT-API/v2-api/
- Pulling the NBTAPI plugin via Maven/Gradle will now also correctly contain the API Javadoc(only had the plugin Javadoc before)
- Fixed small NPE error during error reporting(ironic)
- NBTCompoundList now extend NBTList<ReadWriteNBT> instead of NBTList<NBTListCompound>. This is a compile-time breaking change, and code needs to be updated accordingly. Already published plugins should not be affected by this.
21.08.2022 · 1 300 downloads
Added:
1.19 support
1.7.10 Crucible support(use the latest build). Thanks, EverNife