Wiki 9Minecraft Wiki 9Minecraft

Block Tags in Bedrock Add-Ons

How to assign tags to custom blocks for tool interactions, Molang queries, and Script API filtering.

5Sections
4Code examples
4Known errors

Block tags are empty JSON keys prefixed with 'tag:' that you place inside a custom block's component list or permutation blocks. They have no inherent visual or mechanical behavior on their own, acting instead as labels that other systems—like vanilla tool items, Molang queries, and the Script API—check against. You reach for block tags whenever you want vanilla pickaxes to mine your custom ore at the proper speed, or when you need to group multiple blocks together so your scripts and entity behaviors can identify them without hardcoding dozens of individual block identifiers.

Declaring Tags in a Block Definition

Unlike standard components that take a value or an object of parameters, a block tag is declared inside the "components" object by writing a key that starts with "tag:" and setting its value to an empty JSON object `{}`. You can assign as many tags to a block as you need.

In modern Bedrock format versions (1.20.60 and later), you should namespace your custom tags inside the tag name itself, such as `tag:my_pack:custom_ore`, while using the `minecraft:` namespace when you want to hook into vanilla tool and gameplay tags. Older tutorials often show bare tag names like `tag:stone` or `tag:metal`. While bare tags still parse for backwards compatibility, explicit namespaces prevent collisions between different add-ons and are required for modern vanilla tool interactions.

BP/blocks/tin_ore.json
{
  "format_version": "1.20.80",
  "minecraft:block": {
    "description": {
      "identifier": "my_pack:tin_ore"
    },
    "components": {
      "minecraft:destructible_by_mining": {
        "seconds_to_destroy": 3.0
      },
      "tag:minecraft:is_pickaxe_item_destructible": {},
      "tag:minecraft:stone_tier_destructible": {},
      "tag:my_pack:ore": {}
    }
  }
}

Vanilla Tool and Mining Tier Tags

For years, making vanilla pickaxes, axes, or shovels speed up when mining a custom block required awkward workarounds or modifying vanilla player and item files. Starting in Bedrock 1.20.60, vanilla tools check for specific `minecraft:` tags on the block being mined to determine whether the tool is the right type for the job.

Keep in mind what these tags actually do and what they do not do. Adding `tag:minecraft:is_pickaxe_item_destructible` makes vanilla pickaxes apply their mining speed multiplier and respond to the Efficiency enchantment when breaking your block. However, tags do not automatically gate your block's loot table drops by tool tier. Even if you add `tag:minecraft:iron_tier_destructible`, a wooden pickaxe will still break the block and drop its default loot unless you handle tier checking yourself—either through custom item digger definitions or via the Script API during the block break event.

Tag KeyWhat it doesNotes
tag:minecraft:is_pickaxe_item_destructibleMarks the block as mineable by pickaxes.Vanilla pickaxes apply their mining speed multiplier and Efficiency bonus.
tag:minecraft:is_axe_item_destructibleMarks the block as mineable by axes.Vanilla axes mine this block faster.
tag:minecraft:is_shovel_item_destructibleMarks the block as mineable by shovels.Vanilla shovels mine this block faster.
tag:minecraft:is_hoe_item_destructibleMarks the block as mineable by hoes.Vanilla hoes mine this block faster.
tag:minecraft:is_sword_item_destructibleMarks the block as mineable by swords.Used for blocks like cobwebs or bamboo that swords cut through quickly.
tag:minecraft:stone_tier_destructibleIdentifies the block as requiring at least a stone-tier tool.Used alongside tool type tags; does not automatically suppress loot drops on its own.
tag:minecraft:iron_tier_destructibleIdentifies the block as requiring at least an iron-tier tool.Pair with a tool tag like is_pickaxe_item_destructible.
tag:minecraft:diamond_tier_destructibleIdentifies the block as requiring at least a diamond-tier tool.Pair with a tool tag like is_pickaxe_item_destructible.

State-Dependent Tags in Permutations

Because tags live inside the `components` object, they can also be placed inside the `components` block of any entry in the `permutations` array. When a block transitions into a state that matches a permutation's condition, any tags defined in that permutation are dynamically added to the block for as long as the condition holds true.

This is useful when a block changes its physical nature based on a block state—for example, a custom machine that is soft when unarmored, or a plant block that only counts as harvestable when its growth state reaches the maximum value. Do note that you cannot remove a base tag inside a permutation; if a tag should only exist in certain states, leave it out of the base `components` list and put it only in the relevant permutations.

BP/blocks/petrified_log.json
{
  "format_version": "1.20.80",
  "minecraft:block": {
    "description": {
      "identifier": "my_pack:petrified_log",
      "states": {
        "my_pack:petrified": [
          false,
          true
        ]
      }
    },
    "components": {
      "minecraft:destructible_by_mining": {
        "seconds_to_destroy": 2.0
      }
    },
    "permutations": [
      {
        "condition": "!q.block_state('my_pack:petrified')",
        "components": {
          "tag:minecraft:is_axe_item_destructible": {}
        }
      },
      {
        "condition": "q.block_state('my_pack:petrified')",
        "components": {
          "minecraft:destructible_by_mining": {
            "seconds_to_destroy": 5.0
          },
          "tag:minecraft:is_pickaxe_item_destructible": {}
        }
      }
    ]
  }
}

Matching Block Tags in Custom Tools

When you create a custom tool item using the `minecraft:digger` item component, you do not want to list every single custom and vanilla block identifier in its `destroy_speeds` array. Instead, you can pass a Molang expression inside the `block` object's `tags` field using the `q.any_tag()` or `q.all_tags()` query.

Notice the syntax difference when referencing tags outside of the block definition: you strip the leading `tag:` prefix. If your block has `"tag:my_pack:ore": {}` in its components, you query for `'my_pack:ore'` inside `q.any_tag()`. You can test for multiple tags at once by passing multiple string arguments to `q.any_tag()`, which returns true if the block has at least one of the listed tags.

BP/items/miner_drill.json
{
  "format_version": "1.20.80",
  "minecraft:item": {
    "description": {
      "identifier": "my_pack:miner_drill"
    },
    "components": {
      "minecraft:max_stack_size": 1,
      "minecraft:digger": {
        "use_efficiency": true,
        "destroy_speeds": [
          {
            "block": {
              "tags": "q.any_tag('minecraft:is_pickaxe_item_destructible', 'my_pack:ore')"
            },
            "speed": 8
          }
        ]
      }
    }
  }
}

Checking Block Tags in Molang and Script API

Both Molang and the `@minecraft/server` Script API provide methods to inspect block tags at runtime. In entity behaviors, animation controllers, or particles that evaluate against a block context, you can use `q.block_has_any_tag()` or `q.block_has_all_tags()` with world-relative coordinates, or `q.any_tag()` in contexts where the block is already the subject of the query.

In the Script API, both the `Block` class and the `BlockPermutation` class expose `hasTag(tag: string): boolean` and `getTags(): string[]`. Just like in `minecraft:digger`, you omit the `tag:` prefix when calling these methods in JavaScript or TypeScript. Calling `block.hasTag("my_pack:ore")` checks both the base components of the block and any active tags granted by its current permutation.

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

world.afterEvents.playerBreakBlock.subscribe((event) => {
  const { player, brokenBlockPermutation } = event;

  if (brokenBlockPermutation.hasTag("my_pack:ore")) {
    const allTags = brokenBlockPermutation.getTags();
    player.sendMessage(`You mined a tagged ore! Active tags: ${allTags.join(", ")}`);
  }
});

Which versions this applies to

Defining `tag:*` on custom blocks is stable in base Bedrock 1.16.100+ with no experimental toggles required. The vanilla tool destructible tags (such as `tag:minecraft:is_pickaxe_item_destructible`) require format_version 1.20.60 or higher to function with vanilla tools.

When it does not work

What you seeWhyThe fix
Content Log Error: [Block][error] my_pack:tin_ore | tag:my_pack:ore - Tag components must be an empty objectYou assigned a boolean, string, or number value to the tag key (for example, `"tag:my_pack:ore": true`) instead of an empty JSON object.Change the value of every `tag:` entry in your `components` list to `{}`.
`block.hasTag()` in Script API or `q.any_tag()` in an item's `minecraft:digger` component always evaluates to false.You included the `tag:` prefix inside the query string (writing `hasTag("tag:my_pack:ore")` instead of `hasTag("my_pack:ore")`).Remove `tag:` when reading or querying the tag. Only the block JSON definition uses the `tag:` prefix on the component key.
Vanilla pickaxes still mine the custom block at hand speed even though `tag:minecraft:is_pickaxe_item_destructible` is present.Either the block's `format_version` is older than `1.20.60`, or the block is missing `minecraft:destructible_by_mining` (or has it set to `0` seconds).Bump the block JSON `format_version` to at least `1.20.60` (such as `1.20.80`) and ensure `minecraft:destructible_by_mining` has a positive `seconds_to_destroy` value.
Block fails to load with a schema parsing error mentioning unexpected component `minecraft:is_pickaxe_item_destructible`.You forgot the `tag:` prefix before the `minecraft:` namespace, causing the game to look for a non-existent component named `minecraft:is_pickaxe_item_destructible`.Prefix the key with `tag:` so it reads `"tag:minecraft:is_pickaxe_item_destructible": {}`.

Reference, straight from the game files

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