Loot tables
Loot tables are data-driven JSON files that decide what item stacks a block, entity, chest, fishing rod or command produces — built from pools, weighted entries, item-modifying functions, gating conditions and number providers.
File location
Each loot table is one JSON file under the singular 1.21+ folder:
data/<namespace>/loot_table/<path>.json
data/mypack/loot_table/blocks/lucky_ore.json → referenced as mypack:blocks/lucky_ore
data/mypack/loot_table/entity/boss_drop.json → referenced as mypack:entity/boss_drop
The table ID is namespace:path (without the .json). Vanilla tables live in the minecraft namespace and can be overridden by placing a same-named file in your pack.
Top-level schema
data/<namespace>/loot_table/example.json
{
"type": "minecraft:block",
"random_sequence": "minecraft:blocks/diamond_ore",
"modifier": { /* table-wide item modifier applied to every dropped stack; an array is also accepted */ },
"pools": [ { /* pool */ } ]
}
| Field | Type | Meaning |
|---|---|---|
type | string (enum) | The loot context the table is invoked in (optional, default generic). Validates which context parameters functions/conditions may reference. See the enum below. |
pools | array | List of pools; each pool is rolled independently. |
functions | array | Table-level item modifiers applied in order to every stack the whole table produces (shorthand for repeating functions in each pool). |
random_sequence | resource location | Names a deterministic random sequence 1.20+ so per-table RNG is reproducible. Omit for fully random behaviour. |
Loot context type enum
The context determines which parameters (the killed entity, the mined block, the tool, the origin position, etc.) are available to functions and conditions.
type | Context / provided parameters |
|---|---|
empty | No parameters. |
generic | Supplies all parameters (most permissive). |
chest | Origin + opening entity. |
block | Block state, position, tool, explosion radius, (block entity, direct killer). |
entity | Dying entity, position, damage source, (attacker / direct attacker / attacking player). |
equipment | Spawned entity + position (mob equipment on spawn). |
fishing | Bobber position, fishing rod tool, hooked-in entity. |
archaeology | Suspicious block center, brushing player, brush tool. |
vault | Vault center; optional opener entity + key item. |
gift | Giver location + gifting mob (cat/villager gifts). |
barter | The piglin trading. |
shearing | Sheared entity, position, shears tool. |
advancement_reward | Player + location on advancement grant. |
advancement_entity | Entity + location (predicate/context use). |
advancement_location | Location context (predicate use). |
command | /loot and command-driven contexts. |
selector | Entity-selector-driven contexts (predicates/item modifiers). |
entity_interact / block_interact | Interaction target + tool. |
Not every value is a valid loot-table-invoking context. Several (command, selector, advancement_entity, advancement_location, the interact types) primarily scope predicates and item modifiers rather than tables that drop items.
Pool schema
One entry in the pools array
{
"rolls": 1,
"bonus_rolls": 0.0,
"condition": { /* ONE condition; the pool is skipped unless it passes. Combine with all_of */ },
"modifier": { /* applied to every stack from this pool; an array is also accepted */ },
"entries": [ /* one is chosen per roll (weighted) */ ]
}
| Field | Type | Meaning |
|---|---|---|
rolls | number provider | How many entries to pick from this pool. |
bonus_rolls | number provider | Extra rolls per level of luck (default 0.0). |
entries | array | Candidate entries; per roll one is selected by weight. |
conditions | array | All must pass or the whole pool is skipped (see conditions). |
functions | array | Item modifiers applied to every stack from this pool (see functions). |
Both rolls and bonus_rolls accept the full number-provider syntax — a plain number, a {min,max} uniform shorthand, or an explicit provider object (see below).
Entry types
This is a shape change, not a rename — the plural arrays became single
values, and the new modifier takes an item modifier rather
than a list of functions:
| Up to 26.2 | From 26.3 |
|---|---|
functions: array of functions | modifier: one item modifier |
conditions: array of conditions | condition: one predicate reference |
Both apply to pools and to entries. Singleton entries lose functions
outright. A related trap reported from production: at 26.3 an item modifier file
whose root is a bare list is rejected — a list is valid only
inside a modifier field — and the world fails to load.
Common entry fields: type, conditions, functions, plus for weighted (singleton) entries weight (default 1) and quality (default 0).
Effective weight = max(floor(weight + quality × luck), 0). A higher quality makes an entry more likely as the player's luck attribute rises.
type | Kind | Key fields |
|---|---|---|
minecraft:item | singleton | name (item ID), functions, weight, quality. |
minecraft:tag | singleton / expanding | name (item #tag), expand (bool). expand:true = one entry per item in the tag (each weighted); expand:false = drops the whole tag's items as one entry. |
minecraft:loot_table | singleton | value — a referenced table ID or an inline loot-table object (nested tables, 1.20.2+). |
minecraft:dynamic | singleton | name — context-supplied contents (minecraft:contents for block entities like shulker boxes; minecraft:sherds for decorated pots). |
minecraft:empty | singleton | Drops nothing (use for a weighted "chance of nothing"). |
minecraft:group | composite | children — evaluate all children as a unit. |
minecraft:alternatives | composite | children — first child whose conditions pass (logical OR). |
minecraft:sequence | composite | children — run children in order until one's conditions fail (logical AND-until-fail). |
Loot functions (full catalogue)
Every item-modifier object is {"type": "minecraft:<id>", ...params, "condition": {...}} — condition is optional on any modifier. At 26.3 the discriminator is type, not function, and the field holding them is modifier, not functions: vanilla’s own 1,447 loot tables use type 1,098 times and function never. This catalogue is identical to the standalone item modifier schema (an item-modifier file is just a reusable loot function or array of functions).
| Function | Fields |
|---|---|
set_count | count (number provider), add (bool, default false). |
set_damage | damage (number provider), add (bool, default false). |
set_components | components (component map). |
set_custom_data | tag (SNBT string or object) — writes the custom_data component. |
set_lore | lore (array of text components), mode (append/insert/replace_all/replace_section), entity (ctx, optional), offset (int), size (int). |
set_name | name (text component), entity (ctx, optional), target (custom_name/item_name, default custom_name). |
set_enchantments | enchantments (map ID→level, each a number provider), add (bool). |
enchant_randomly | options (array/#tag, optional), only_compatible (bool, default true). |
enchant_with_levels | levels (number provider), options (optional). |
enchanted_count_increase | enchantment (ID), count (number provider), limit (int, default 0). The looting_enchant replacement. |
apply_bonus | enchantment (ID), formula (uniform_bonus_count/ore_drops/binomial_with_bonus_count), parameters (extra/probability/bonusMultiplier). |
furnace_smelt | (none) — outputs the smelted form. |
explosion_decay | (none) — randomly removes items per explosion radius. |
limit_count | limit (int, or {min,max} clamp). |
set_attributes | modifiers (array of {attribute, id, amount(np), operation, slot}), replace (bool, default true). |
set_stew_effect | effects (array of {type, duration}). |
set_potion | id (potion ID). |
set_ominous_bottle_amplifier | amplifier (number provider). |
set_instrument | options (instrument #tag). |
set_book_cover | author, title (text component), generation (0–3) — all optional. |
set_written_book_pages / set_writable_book_pages | pages (array), mode, offset, size. |
set_banner_pattern | patterns (array), append (bool). |
set_firework_explosion | shape, colors (ints), fade_colors (ints), has_trail, has_twinkle. |
set_fireworks | explosions (list op: values/mode/offset/size), flight_duration (0–255). |
set_custom_model_data | floats/flags/strings/colors (each a list op) — structured CMD 1.21.4+. |
set_contents | entries (array), component (container/bundle_contents/charged_projectiles). |
modify_contents | component (container-like), modifier (item modifier(s) applied to contents). |
set_loot_table | name (table ID), type (block-entity type), seed (optional) — for container block items. |
set_item | item (ID) — replaces the stack's item type. |
copy_components | source (block_entity), include/exclude (arrays, optional). |
copy_custom_data | source (context/storage/block_entity), ops (array of {source, target, op}). |
copy_name | source (context: block_entity/entity). |
copy_state | block (ID), properties (array of state names) — copies mined block states into block_state. |
exploration_map | destination (structure tag — bare id up to 26.2, #tag from 26.3, and the field became required at 26.3; see below), decoration, zoom (int, def 2), search_radius (int, def 50), skip_existing_chunks (bool, def true). |
fill_player_head | entity (ctx ref) — writes the profile of a player from context. |
filtered | item_filter (item predicate), modifier (item modifier applied on match). |
toggle_tooltips | toggles (booleans: attribute_modifiers, can_break, can_place_on, dyed_color, enchantments, stored_enchantments, trim, unbreakable). |
set_random_dyes / set_random_potion | Randomised dye / potion helpers. |
reference | name (referenced item-modifier ID or array). |
sequence | functions (array run in order). |
exploration_map: destination changed shape at 26.3
destination names a structure tag, and how you write
that tag depends on the version. There is no single value that is correct on
both sides of 26.3, which makes this the rare field where a pack spanning the
two needs an overlay.
| Up to 26.2 (format ≤ 110) | From 26.3 (format ≥ 111) — current release since 2026-09-15 | |
|---|---|---|
| Required? | Optional — defaults to buried treasure. | Required. Omitting it is an error. |
| Tag reference | "minecraft:on_treasure_maps" — bare. A leading # is a parse error. | "#minecraft:on_treasure_maps" — prefixed. |
| Bare id means | the tag of that name. | a single structure of that name — not the tag. |
| List form | — | ["ns:structure", "…"] is also accepted. |
Measured, not inferred, and re-checked as 26.3 progressed. The same vanilla file — villager_trade/cartographer/2/emerald_and_compass_village_desert_map.json — reads minecraft:on_desert_village_maps at format 110 and #minecraft:on_desert_village_maps at format 111. Across shipped 26.2 all 10 distinct destination values are bare and none are prefixed. The change has since held through 26.3-pre-1 (format 119), where all 28 occurrences across 23 distinct values are prefixed and none are bare — so it shipped unchanged in the 26.3 release (format 121).
Up to 26.2 — bare, and the tag is implied
{
"function": "minecraft:exploration_map",
"destination": "minecraft:on_woodland_explorer_maps",
"decoration": "woodland_mansion"
}
From 26.3 — the tag is referenced explicitly, and the key is type
{
"type": "minecraft:exploration_map",
"destination": "#minecraft:on_woodland_mansion_maps",
"decoration": "woodland_mansion"
}
Using # on 26.2 or earlier does not merely disable the map — the
file fails to parse, because the # is read as part of the
namespace:
Couldn't parse data file 'example:cartographer/dungeon_map':
Not a valid resource location: #example:on_dungeon_maps
Non [a-z0-9_.-] character in namespace of identifier
A loot table that fails to parse is never registered, so every reference to it dangles at once — villager trades, chest pools and item tables pointing at it all go silently empty, with nothing in-game naming the file at fault.
The reverse is worse, because it is silent. A bare tag-style name
on 26.3 parses cleanly and then resolves to a structure of that name. For a
name like on_treasure_maps, where no structure shares the tag's name,
there is nothing to find and no error is raised. Packs whose tag and structure happen
to share a name keep working across the change by coincidence, not design.
Keep the bare form in the base pack and put the # form in a 26.3
overlay. Naming the structure and its tag identically
also survives the jump, but the meaning quietly changes from "any of these" to "this
one", so it is a workaround rather than a fix.
A bare array in a loot modifier field (or in an item-modifier file) behaves exactly like sequence — vanilla uses the array form in 374 places and a single object in 724.
Loot conditions (full list)
Every condition is {"type": "minecraft:<id>", ...}, and it sits in the singular condition field. This is the same system as standalone predicate files — the full field breakdown of each condition lives on that page.
| Condition | Purpose |
|---|---|
all_of | terms — passes if all terms pass (AND). |
any_of | terms — passes if any term passes (OR). |
inverted | term — negates a single condition. |
random_chance | chance (float 0–1; a number provider since 1.21). |
random_chance_with_enchanted_bonus | Level-scaled chance (1.21 rename of the old looting-based chance). |
killed_by_player | Requires attacking_player in context. |
entity_properties | entity (context ref) + predicate (entity sub-predicate). |
entity_scores | entity + scores (map objective → int range). |
block_state_property | block + properties (state map, exact or {min,max}). |
table_bonus | enchantment + chances (array indexed by level). |
survives_explosion | Passes with probability 1 / explosion_radius. |
match_tool | predicate (item sub-predicate) — the mining/relevant tool. |
weather_check | raining (bool), thundering (bool). |
time_check | value (range) + period (int modulo, optional). |
value_check | value (number provider) + range (int range). |
location_check | predicate (location sub-predicate) + optional offsetX/Y/Z. |
damage_source_properties | predicate (damage-source sub-predicate). |
enchantment_active_check | active (bool) — inside enchantment-provided effects. |
reference | name (resource location of another predicate file). |
Number providers & ranges
Number providers generate a value for rolls, bonus_rolls, set_count.count, set_damage.damage, enchant levels, value_check, random_chance, and more. The four core providers are universal:
| Provider | Fields | Notes |
|---|---|---|
constant | value (number) | Fixed value. |
uniform | min, max (each a number provider) | Inclusive random. |
binomial | n (trials, np), p (probability 0–1, np) | Binomial distribution. |
score | target ({type:"fixed", name} or {type:"context", target}), score (objective), scale (float, optional) | Reads a scoreboard value. |
Three further providers — storage (storage + path), enchantment_level (amount, a per-level value) and sum (summands array) — are documented but less common. The four above are the safe, universal set.
Shorthand forms
- A plain number (
"rolls": 3) is treated as aconstant. - An object
{ "min": x, "max": y }(notype) is treated asuniform. - Explicit:
{ "type": "minecraft:uniform", "min": 1, "max": 4 }.
Int / float ranges
Distinct from number providers: a range tests a value rather than generating one. Used by predicate comparisons (count, distance, time_check.value, entity_scores, effects.amplifier, …). A range is a single number (exact match) or an object with optional min and/or max:
"count": { "min": 2, "max": 5 } // 2..5 inclusive
"count": 3 // exactly 3
"level": { "min": 10 } // >= 10 (open upper bound)
"rolls": { "type": "minecraft:binomial", "n": 3, "p": 0.5 }
"count": { "type": "minecraft:score",
"target": { "type": "context", "target": "this" },
"score": "kills", "scale": 0.5 }
Examples
Block drop with a fortune bonus
data/mypack/loot_table/blocks/lucky_ore.json
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:diamond",
"modifier": [
{ "type": "minecraft:apply_bonus",
"enchantment": "minecraft:fortune",
"formula": "minecraft:ore_drops"
},
{ "type": "minecraft:explosion_decay" }
]
}
],
"condition": { "type": "minecraft:survives_explosion" }
}
]
}
Weighted entity drop, gated on a player kill
data/mypack/loot_table/entity/boss_drop.json
{
"type": "minecraft:entity",
"pools": [
{
"rolls": { "min": 1, "max": 3 },
"bonus_rolls": 0.5,
"condition": { "type": "minecraft:killed_by_player" },
"entries": [
{ "type": "minecraft:item", "name": "minecraft:diamond", "weight": 6,
"modifier": [
{ "type": "minecraft:set_count",
"count": { "type": "minecraft:uniform", "min": 1, "max": 4 } } ] },
{ "type": "minecraft:item", "name": "minecraft:netherite_scrap", "weight": 1, "quality": 2 },
{ "type": "minecraft:empty", "weight": 3 }
]
}
]
}
Chest / gift table (generic context)
data/mypack/loot_table/gameplay/enchanted_book_gift.json
{
"type": "minecraft:generic",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:enchanted_book",
"modifier": [
{ "type": "minecraft:enchant_with_levels", "levels": { "min": 20, "max": 39 } }
]
}
]
}
]
}
A "custom item" drop via components 1.20.5+
data/mypack/loot_table/entity/starblade_drop.json
{
"type": "minecraft:entity",
"pools": [
{
"rolls": 1,
"condition": { "type": "minecraft:killed_by_player" },
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:netherite_sword",
"modifier": [
{ "type": "minecraft:set_components",
"components": {
"minecraft:custom_name": { "text": "Starblade", "color": "gold" },
"minecraft:rarity": "epic"
} },
{ "type": "minecraft:set_custom_data", "tag": "{starblade:1b}" }
]
}
]
}
]
}
- Since 1.21.5 (data pack format 71) — text components are stored as objects in NBT. Write
{ "text": "Starblade", "color": "gold" }, as above. Many commands, including/tellraw, take SNBT rather than JSON from this version. - Before 1.21.5 — the same field took a string containing JSON:
"{\"text\":\"Starblade\"}". A pack targeting older clients still needs that form.
The stale string form is syntactically valid JSON, so a pack carrying it parses cleanly and passes static validation. Nothing complains until the item is generated at runtime and the name renders wrong or not at all. This is the shape that gets whole batches of loot shipped broken: the file is well formed, the schema is satisfied, and only the meaning is wrong.
Tricks & best practices
/loot turns any table into a parametric item generator: /loot give @s loot mypack:x, /loot spawn ..., /loot replace block ..., /loot insert .... Call it from functions to hand out randomised kits without hard-coding /give lines.
Use a weighted minecraft:empty entry for a "chance of nothing" inside a single roll, rather than a random_chance condition — it keeps the odds visible alongside the real drops.
random_sequence guarantees reproducible RNG (deterministic chest loot for map-makers). Omit it when you want fully random behaviour.
Dynamic drops: a minecraft:dynamic entry (contents, sherds) emits the block's stored contents — required so shulker boxes and decorated pots keep their data when mined. Nested/inline tables (a loot_table entry with an inline value) plus reference functions/conditions keep shared sub-tables DRY.
apply_bonus formulas: minecraft:uniform_bonus_count (param bonusMultiplier), minecraft:ore_drops (no params — the vanilla fortune ore curve), minecraft:binomial_with_bonus_count (params extra, probability).
Version differences
- Since 1.20.5 (pack_format 41): item NBT became data components. Loot items use component syntax and
set_nbtwas split intoset_custom_data(the direct successor — writes thecustom_datacomponent) and the generalset_components(sets any typed component). - Since 1.20.5:
copy_nbt→copy_custom_data. - Since 1.20.5:
looting_enchant→enchanted_count_increase(now takes an explicitenchantment, since looting is data-driven). - Since 1.21 (pack_format 48): the folder
loot_tableswas singularised toloot_table. - Since 1.21: loot-context entity refs renamed:
killer→attacker,direct_killer→direct_attacker,killer_player→attacking_player. - Since 1.21:
random_chance_with_enchanted_bonusreplaced the old looting-based random-chance condition, andrandom_chance'schancebecame a number provider.