Villager Trades
Villager trades are data-driven JSON files introduced in Minecraft Java Edition 26.1 that define what individual trades a villager can offer and how they are grouped into trade sets per profession level. This system fully replaces the old hardcoded trade lists and lets data packs control everything about villager economies - what items are bought and sold, at what quantities, for how many uses, with what item modifier functions applied to the output, and under what conditions.
Overview
The trade system uses two file types that work together:
villager_trade- a single trade offer: inputs the villager wants, the output it gives, limits, and rewards.trade_set- a pool ofvillager_tradereferences that Minecraft samples from when a villager gains a level.
A villager profession's trade list is built from a stack of trade sets, one per level. Each time a villager levels up, Minecraft draws amount trades at random from the appropriate trade set.
File Structure
For the full JSON specification see:
Villager Trade
Creating a Trade
Use villagerTrade on your DataPack. Call wants and gives inside the block to set the required items - both accept an ItemArgument, an optional count, and an optional component builder.
Item Slots
wants, gives, and additionalWants all follow the same shape: an item id, an optional stack size, and an optional block to set data components on the item. gives is an item stack with a fixed count:
Two-input trades use additionalWants for the second slot:
Trade Costs
wants and additionalWants are trade costs (TradeCost), written as { "id": ..., "count": ..., "components": ... }:
| Field | Type | Description |
|---|---|---|
components |
Components? |
Components the traded item must match exactly, any item of that type matches when unset. |
count |
ContextIntProvider? |
Number of items requested, 1 when unset. Rolled each time the trade is offered. |
id |
ItemArgument |
Item requested. |
count takes a fixed number or an int provider, including the ID of a context provider file through reference(...):
The component block restricts the cost to items carrying exactly those component values, here an undamaged sword:
In game: the three trades above in a merchant's offer list, click one to select it
VillagerTrade Fields
All fields are optional except wants and gives, which must be set before the data pack is generated.
| Field | Type | Description |
|---|---|---|
additionalWants |
TradeCost? |
Second item the villager requests alongside wants. |
doubleTradePriceEnchantments |
InlinableList<EnchantmentOrTagArgument>? |
Enchantments on the player's item that double the trade cost. |
givenItemModifier |
InlinableItemModifier? |
Item modifier applied to the output item before delivery. |
gives |
ItemStack? |
Item the villager offers in return. Required. |
maxUses |
ContextIntProvider? |
Maximum uses before the trade locks. Unlocks when the villager restocks. |
merchantPredicate |
PredicateCondition? |
Condition checked against the merchant entity; trade only appears when it passes. |
reputationDiscount |
ContextFloatProvider? |
Price multiplier applied based on the player's village reputation. |
wants |
TradeCost |
Primary item the villager requests. Required. |
xp |
ContextIntProvider? |
XP points awarded to the villager when the trade completes. |
maxUses and xp take int providers (maxUses(12), xp(uniform(1, 5))), or a range drawn uniformly (maxUses(8..12), xp(1..5)), reputationDiscount a float provider (reputationDiscount(0.05f)) or a float range (reputationDiscount(0.05f..0.1f)). Each one also takes the ID of a context provider file through reference(...):
Applying Item Modifiers to the Output
Use givenItemModifier to run an item modifier on the item the villager gives. This is how you add random enchantments, custom lore, or any other post-processing:
One function is written as an object, several functions as a list. An item modifier file is applied by its ID with reference:
See Item Modifiers for all available functions.
Gating a Trade with a Predicate
merchantPredicate is a condition evaluated against the villager entity. The trade only appears in the merchant's offer list when the condition passes - useful for biome-locked or NBT-gated trades.
See Predicates for all available condition types.
Double-Price Enchantments
doubleTradePriceEnchantments lists enchantments that, when present on the player's traded-in item, cause the villager to charge twice as much. Vanilla uses this for the Curse of Binding and similar effects.
Trade Set
Creating a Trade Set
A TradeSet groups references to villager_trade files and controls how many are rolled per level. Everything is set inside the block: trades takes the references returned by villagerTrade (or trade tags), and amount takes the number of trades rolled out of the pool.
A file name holding slashes lands in subfolders, the way vanilla groups its sets per profession and level, so tradeSet("farmer/level_1") writes data/<namespace>/trade_set/farmer/level_1.json.
Sampling with Tags
Individual trade references and tag references mix in the same pool, and trade appends a single one to what is already there:
A pool holding a single entry serializes as a plain string rather than an array, matching vanilla.
Reproducible Rolls
randomSequence seeds the rolls from a named random sequence, so the same set always produces the same trades for a given world seed:
TradeSet Fields
| Field | Type | Description |
|---|---|---|
allowDuplicates |
Boolean? |
Whether the same trade can be rolled more than once. Defaults to false. |
amount |
ContextIntProvider |
How many trades are rolled out of the set. Defaults to 1. |
randomSequence |
RandomSequenceArgument? |
Named random sequence the rolls are seeded from, non-deterministic when unset. |
trades |
InlinableList<VillagerTradeOrTagArgument> |
Trade references or tags rolled from. |
TradeSet Builders
| Builder | Description |
|---|---|
amount(value) |
Rolls exactly value trades. |
amount(min, max) |
Rolls between min and max trades, both included, like amount(min..max). |
amount(range) |
The same from a range, amount(1..3). Equal ends roll exactly that many, and an inverted range such as 3..1 throws. |
amount(provider) |
Any int provider (binomial(4, 0.5f)), or a reference(id) to a provider file. |
randomSequence(name, ns) |
Seeds the rolls from a named random sequence. |
trade(trade) |
Appends one trade or tag to the pool. |
trades(vararg / list) |
Sets the pool, replacing the entries already there. |
Full Example: Custom Farmer Profession Level 1
See Also
- Item Modifiers - Apply functions to the item a villager gives
- Predicates - Gate trade availability via
merchantPredicate - Enchantments -
doubleTradePriceEnchantmentsand enchanting trade outputs - Tags - Group trades into reusable
villager_tradetags for trade sets - Loot Tables - Related data-driven item generation system
External Resources
- Minecraft Wiki: Villager trade definition
- Minecraft Wiki: Trade set
- Minecraft Wiki: Trading - How the vanilla trading system works
- Minecraft Wiki: Villager - Villager behavior, professions, and leveling
