File Location and Structure
Every spawn rule lives in the BP/spawn_rules/ directory of your behavior pack. While the file name itself does not strictly have to match the entity identifier, naming it after your mob (such as custom_boar.json) keeps your project maintainable. If you want to override a vanilla mob's spawning behavior, use the exact file name and identifier from the base game.
A spawn rule file is wrapped in the minecraft:spawn_rules object and requires a format_version. Inside, it splits into two sections: a description block that links the rule to an entity and a population cap, and a conditions array that lists every valid scenario where the mob is allowed to appear.
{
"format_version": "1.8.0",
"minecraft:spawn_rules": {
"description": {
"identifier": "my_pack:forest_boar",
"population_control": "animal"
},
"conditions": [
{
"minecraft:spawns_on_surface": {},
"minecraft:brightness_filter": {
"min": 7,
"max": 15,
"adjust_for_weather": false
},
"minecraft:weight": {
"default": 10
},
"minecraft:herd": {
"min_size": 2,
"max_size": 4
},
"minecraft:biome_filter": {
"test": "has_biome_tag",
"operator": "==",
"value": "forest"
}
}
]
}
}Population Control Pools
The population_control field in the description block prevents your entity from flooding the world and causing severe lag. Bedrock Edition divides natural spawns into distinct mob caps. Before the game attempts to run your conditions, it checks if the chosen pool currently has room for more entities in the active spawning area around the player.
Choosing the wrong pool is a common reason custom mobs appear too rarely or too often. Passive creatures that stay in the world permanently usually belong in the animal pool, while hostile threats that despawn when the player walks away belong in the monster pool.
| Pool Name | Typical Usage | Behavior Notes |
|---|---|---|
| animal | Sheep, pigs, cows, passive custom mobs | Small cap, slower spawn cycle. Mobs here usually have persistence and do not despawn naturally. |
| monster | Zombies, skeletons, hostile custom mobs | High cap, checks every tick. Mobs in this pool should be configured to despawn when far from players. |
| water_animal | Fish, dolphins, squid | Dedicated cap for aquatic life so oceans do not block land animals from spawning. |
| ambient | Bats | Very small cap meant for purely decorative mobs that have no gameplay impact. |
Core Spawn Conditions
Each object inside the conditions array represents a separate spawning rule. If an entity can spawn in two wildly different ways—such as on the surface in swamps and deep underground in lush caves—you create two separate objects in the conditions array. For a single condition object to succeed, every component inside that specific object must pass its check simultaneously.
Vanilla spawn rules rely on a core set of condition components to check the environment, light level, difficulty, and group sizes.
| Component | What it does | Notes |
|---|---|---|
| minecraft:spawns_on_surface | Allows spawning on the highest solid block open to the sky. | Can be paired with minecraft:spawns_underground in the same condition to allow spawning at any depth. |
| minecraft:spawns_underground | Allows spawning in caves or under a roof. | Used by most standard hostile monsters and cave-dwelling creatures. |
| minecraft:spawns_underwater | Requires the spawn block to be liquid water. | Essential for fish, squid, drowned, and custom aquatic entities. |
| minecraft:spawns_on_block_filter | Restricts spawning to specific block identifiers. | Accepts a single block string or an array of block names like minecraft:grass_block. |
| minecraft:spawns_on_block_prevented_filter | Blocks spawning on specific block identifiers. | Useful when a biome filter is broad, but you want to exclude specific surfaces. |
| minecraft:brightness_filter | Checks the light level at the target coordinate. | Takes min and max (0 to 15), plus a boolean adjust_for_weather which lowers light during storms. |
| minecraft:difficulty_filter | Restricts spawns by world difficulty setting. | Takes min and max strings: peaceful, easy, normal, or hard. |
| minecraft:height_filter | Restricts the Y-coordinate range for valid spawns. | Takes min and max integers. Useful for deep cave monsters or high mountain goats. |
| minecraft:weight | Determines how often this mob is picked compared to others in the same biome and pool. | Higher default integer values mean more frequent spawns. A weight of 80 is very common (like zombies); 5 is rare (like endermen). |
| minecraft:herd | Controls how many mobs appear together in one successful spawn attempt. | Uses min_size and max_size. Can also define an event string to fire on a specific number of spawned mobs, such as making them babies. |
| minecraft:density_limit | Caps how many of this specific entity can exist nearby. | Takes surface and underground integer limits to prevent one high-weight mob from taking over an entire area. |
Filtering Biomes with Tags
The minecraft:biome_filter component is the primary way vanilla rules keep polar bears in frozen areas and husks in deserts. Rather than checking for exact biome names, vanilla Bedrock rules almost always test against biome tags using the has_biome_tag filter test. This makes your custom mob automatically compatible with new vanilla biomes or even custom biomes from other add-ons that use standard tags.
You can combine multiple filter tests using all_of, any_of, and none_of logic groups. This is standard practice in vanilla files: a common hostile monster will require the monster biome tag while excluding mushroom islands and the deep dark.
{
"format_version": "1.8.0",
"minecraft:spawn_rules": {
"description": {
"identifier": "my_pack:cursed_skeleton",
"population_control": "monster"
},
"conditions": [
{
"minecraft:spawns_on_surface": {},
"minecraft:spawns_underground": {},
"minecraft:brightness_filter": {
"min": 0,
"max": 7,
"adjust_for_weather": true
},
"minecraft:difficulty_filter": {
"min": "easy",
"max": "hard"
},
"minecraft:weight": {
"default": 40
},
"minecraft:herd": {
"min_size": 1,
"max_size": 2
},
"minecraft:biome_filter": {
"all_of": [
{
"test": "has_biome_tag",
"operator": "==",
"value": "monster"
},
{
"test": "has_biome_tag",
"operator": "!=",
"value": "mooshroom_island"
},
{
"test": "has_biome_tag",
"operator": "!=",
"value": "deep_dark"
}
]
}
}
]
}
}Vanilla Patterns to Copy
When designing a custom entity's spawn behavior, the safest workflow is to copy the pattern of the closest vanilla equivalent. For a standard overworld animal (like cows or sheep), use the animal population pool, set minecraft:spawns_on_surface, restrict the brightness_filter from 7 to 15, add a minecraft:spawns_on_block_filter for minecraft:grass_block, and filter for the animal biome tag with a weight between 8 and 12.
For aquatic entities, combine minecraft:spawns_underwater with the water_animal pool and test for the ocean or river biome tags. If your mob spawns in the Nether, remember that ambient light in the Nether is higher than in overworld caves; vanilla Nether mobs like piglins and magma cubes either raise their maximum brightness_filter or omit the brightness filter entirely depending on their design.
Which versions this applies to
Format version 1.8.0 is the standard used across almost all vanilla spawn rules in current Bedrock releases (1.20 and 1.21+) and requires no experimental toggles. Newer format versions up to 1.11.0 also exist in some vanilla files and are stable.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Custom mob works with /summon and spawn eggs, but never spawns naturally in the world. | In the entity's behavior file (BP/entities/), the description block has is_spawnable set to false, or the spawn rule JSON omits one of the placement components (minecraft:spawns_on_surface, minecraft:spawns_underground, or minecraft:spawns_underwater). | Ensure at least one placement component is inside each condition block in your spawn rule, and verify that the identifier in the spawn rule exactly matches the entity's behavior identifier. |
| Content Log shows: [Scripting][error]-Failed to parse spawn rules file | There is a JSON syntax error, or minecraft:biome_filter is formatted with an invalid test name or missing operator. | Validate your JSON for missing commas or brackets, and verify that every filter test inside minecraft:biome_filter includes "test", "operator", and "value" keys. |
| Hostile custom mob spawns during the day or in lit bases. | The minecraft:brightness_filter component is missing, or its max value is set above 7. | Add minecraft:brightness_filter to the condition object with "min": 0 and "max": 7 (or 0 if matching newer strict darkness rules for specific cave mobs). |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
