Wiki 9Minecraft Wiki 9Minecraft

Entity Trading Behavior and Trade Tables

How to add custom trading menus, trade tiers, and economy tables to entities in Bedrock Edition.

5Sections
3Code examples
3Known errors

Trading behavior in Minecraft Bedrock allows players to interact with an entity to exchange items through a dedicated interface. This system is split into two distinct parts: the behavior component attached to the entity file, and the JSON trade table that defines the actual offers, prices, and tiers. You will reach for this system whenever you are creating custom merchants, quest givers, or overriding vanilla villager professions.

The Two Trade Components

Before writing a trade table, the entity itself needs a component that enables the trading UI and links to the table file. Bedrock provides two different components for this purpose: minecraft:trade_table and minecraft:economy_trade_table.

The basic minecraft:trade_table component is the legacy implementation, commonly used on the wandering trader or simple custom NPCs. It opens a flat trade screen without an experience bar at the top, and it does not support dynamic price changes from curing or hero of the village effects. The newer minecraft:economy_trade_table component is what vanilla villagers use. It enables visible profession tiers, experience progression, supply exhaustion, and price multipliers.

For most custom merchants that do not need to restock at a workstation block, the standard minecraft:economy_trade_table is still preferred because it lets you show or hide unlocked tiers cleanly. You place this component inside the components or component_groups block of your entity behavior file.

FieldWhat it doesNotes
display_nameSets the title text at the top of the trade window.Accepts a raw string or a localization key from your .lang file.
tablePath to the trade table JSON relative to the behavior pack root.Always starts with trading/ and includes the .json extension.
new_screenSwitches from the classic Pocket UI to the modern sidebar trade menu.Only exists on economy_trade_table. Set to true for modern villagers.
persist_tradesKeeps the rolled trades saved to the entity NBT after the first interaction.If false, trades may reroll when the entity reloads.
convert_trades_economyConverts old trade data if upgrading an existing entity.Optional boolean on economy_trade_table.
BP/entities/goblin_merchant.json
{
  "format_version": "1.20.80",
  "minecraft:entity": {
    "description": {
      "identifier": "custom:goblin_merchant",
      "is_spawnable": true,
      "is_summonable": true
    },
    "components": {
      "minecraft:economy_trade_table": {
        "display_name": "entity.custom:goblin_merchant.name",
        "table": "trading/custom/goblin_trades.json",
        "new_screen": true,
        "persist_trades": true,
        "show_trade_screen": true
      }
    }
  }
}

Trade Table Structure and Tiers

Trade tables live in the BP/trading/ folder of your behavior pack. Unlike loot tables or entity files, trade tables do not require a format_version key at the top. The root object simply contains a single array called tiers.

Each object inside the tiers array represents one progression level (such as Novice, Apprentice, or Journeyman). When an entity spawns with a trade table, it unlocks the first tier automatically. To unlock subsequent tiers, the player must complete trades to earn experience for the merchant, matching the total_exp_required value defined on the next tier.

Inside each tier, you can place either a direct trades array or a groups array. If you put trades directly in the tier, every single trade in that list will become available when the tier unlocks. If you want the game to pick only a random subset of trades from a larger pool—just like vanilla villagers do—you wrap your trades inside a groups array and specify num_to_select.

BP/trading/custom/goblin_trades.json
{
  "tiers": [
    {
      "total_exp_required": 0,
      "groups": [
        {
          "num_to_select": 2,
          "trades": [
            {
              "wants": [
                {
                  "item": "minecraft:gold_ingot",
                  "quantity": {
                    "min": 2,
                    "max": 5
                  },
                  "price_multiplier": 0.05
                }
              ],
              "gives": [
                {
                  "item": "minecraft:amethyst_shard",
                  "quantity": 4
                }
              ],
              "trader_exp": 2,
              "max_uses": 12,
              "reward_exp": true
            },
            {
              "wants": [
                {
                  "item": "minecraft:copper_ingot",
                  "quantity": 10
                },
                {
                  "item": "minecraft:coal",
                  "quantity": 5
                }
              ],
              "gives": [
                {
                  "item": "minecraft:iron_pickaxe",
                  "quantity": 1
                }
              ],
              "trader_exp": 5,
              "max_uses": 3,
              "reward_exp": true
            }
          ]
        }
      ]
    },
    {
      "total_exp_required": 10,
      "trades": [
        {
          "wants": [
            {
              "item": "minecraft:diamond",
              "quantity": 1
            }
          ],
          "gives": [
            {
              "item": "minecraft:lava_bucket",
              "quantity": 1
            }
          ],
          "trader_exp": 10,
          "max_uses": 6,
          "reward_exp": true
        }
      ]
    }
  ]
}

Defining Wants and Gives

Every individual trade entry requires a wants array and a gives array. The wants array can hold either one or two item objects, corresponding to the two input slots in the trading interface. If you put more than two items in wants, the extra entries are ignored. The gives array only ever uses its first item entry, because the output slot of the trading UI can only dispense a single item stack per transaction.

Item identifiers accept a trailing colon and integer to set the data value or auxiliary metadata (for example, minecraft:potion:5), though modern Bedrock items generally have flattened identifiers. The quantity field accepts either a fixed integer or an object with min and max integers, which the game rolls once when the trade is first generated.

For entities using minecraft:economy_trade_table, you can also control how supply and demand affect prices. Setting max_uses determines how many times a player can execute the trade before a red X appears over the arrow. Setting price_multiplier on an item inside wants determines how steep the price increase is when the player buys out the stock repeatedly, or how big the discount is when the player has reputation bonuses.

FieldWhat it doesNotes
wantsArray of 1 or 2 items required from the player.Supports item, quantity, and price_multiplier.
givesArray containing the 1 item awarded to the player.Supports item, quantity, and loot table functions.
max_usesNumber of times the trade can be used before locking.Set to a very high number if your entity cannot restock.
trader_expExperience points added to the merchant's tier bar.Only applies when using economy_trade_table.
reward_expWhether green XP orbs drop for the player upon trading.Boolean value (true or false).

Applying Loot Functions to Output Items

Plain items are often not enough for higher-tier trades. You can modify the item inside the gives array using a functions block, which borrows many of the same item functions used in Bedrock loot tables. This is how vanilla villagers sell enchanted books, named items, dyed leather armor, and woodland explorer maps.

The functions array goes directly inside the item object in the gives list. While you cannot use every loot function inside a trade table, standard item modifiers like enchant_with_levels, enchant_book_for_trading, set_name, set_lore, and set_data work reliably. Note that functions are only evaluated on the output item in gives; putting functions inside the wants array to demand custom named items or specific enchantments from the player is not supported by the trading system.

BP/trading/custom/enchanted_trade_snippet.json
{
  "tiers": [
    {
      "total_exp_required": 0,
      "trades": [
        {
          "wants": [
            {
              "item": "minecraft:emerald",
              "quantity": 15
            }
          ],
          "gives": [
            {
              "item": "minecraft:diamond_sword",
              "quantity": 1,
              "functions": [
                {
                  "function": "enchant_with_levels",
                  "treasure": true,
                  "levels": {
                    "min": 20,
                    "max": 35
                  }
                },
                {
                  "function": "set_name",
                  "name": "Goblin Blade"
                }
              ]
            }
          ],
          "trader_exp": 15,
          "max_uses": 1,
          "reward_exp": true
        }
      ]
    }
  ]
}

Controlling Restocking and Profession Behaviors

When a trade reaches its max_uses limit, it becomes locked. On a custom entity that only has minecraft:economy_trade_table, locked trades will stay locked forever unless you also configure the entity to restock or use high max_uses values (such as 9999) so the stock never runs out in normal play.

If you want your custom merchant to restock like a vanilla villager, the entity requires additional AI goal components and properties. Specifically, vanilla villagers rely on minecraft:trade_resupply along with a valid workstation block defined in minecraft:dweller and pathfinding goals like minecraft:behavior.work. Without the dweller and work behavior loop, adding minecraft:trade_resupply by itself will not trigger restocking because the entity has no assigned job site to walk to.

Finally, make sure your entity has minecraft:behavior.trade_with_player and minecraft:behavior.look_at_trading_player in its AI goals. Without these two behavior components, the player can still open the trade menu, but the entity will walk away while the player is browsing, immediately closing the UI when it moves out of range.

Which versions this applies to

Applies to Minecraft Bedrock 1.16.0 through 1.21+. Both minecraft:trade_table and minecraft:economy_trade_table are stable vanilla features and do not require any experimental toggles.

When it does not work

What you seeWhyThe fix
The Trade button appears on the entity, or right-clicking works, but the trade UI flashes open for a split second and immediately closes (or never opens at all).The path in the table property of the entity component does not match the actual file location in BP/trading/, or the trade table JSON has a syntax error.Verify the path starts with "trading/" (not "BP/trading/") and check the Content Log for JSON parse errors in your trade table file.
The entity walks away while the player has the trade window open, forcing the menu to close after a few seconds.The entity is missing the AI behavior goal that pauses its movement during a transaction.Add "minecraft:behavior.trade_with_player": { "priority": 1 } to the entity's components so it stands still while a player is trading with it.
A custom item in the wants array accepts any item, or shows a missing texture icon in the trade slot.The item identifier in wants or gives is misspelled, or you attempted to put loot functions (like set_name) inside the wants block.Double-check the exact identifier of your custom item, and remove any functions blocks from the wants array; functions only work inside gives.

Reference, straight from the game files

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