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.
{
"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 Key | What it does | Notes |
|---|---|---|
| tag:minecraft:is_pickaxe_item_destructible | Marks the block as mineable by pickaxes. | Vanilla pickaxes apply their mining speed multiplier and Efficiency bonus. |
| tag:minecraft:is_axe_item_destructible | Marks the block as mineable by axes. | Vanilla axes mine this block faster. |
| tag:minecraft:is_shovel_item_destructible | Marks the block as mineable by shovels. | Vanilla shovels mine this block faster. |
| tag:minecraft:is_hoe_item_destructible | Marks the block as mineable by hoes. | Vanilla hoes mine this block faster. |
| tag:minecraft:is_sword_item_destructible | Marks the block as mineable by swords. | Used for blocks like cobwebs or bamboo that swords cut through quickly. |
| tag:minecraft:stone_tier_destructible | Identifies 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_destructible | Identifies the block as requiring at least an iron-tier tool. | Pair with a tool tag like is_pickaxe_item_destructible. |
| tag:minecraft:diamond_tier_destructible | Identifies 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.
{
"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.
{
"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.
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 see | Why | The fix |
|---|---|---|
| Content Log Error: [Block][error] my_pack:tin_ore | tag:my_pack:ore - Tag components must be an empty object | You 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.
