Filtering Targets with the scores Selector Argument
The most direct way to compare a score against a fixed number is inside a target selector using the scores argument. This argument takes a brace-enclosed list of objective names and value ranges. Ranges use two dots (..) to denote minimum and maximum bounds. A single integer checks for an exact match, a number followed by two dots (such as 10..) checks for that value or higher, and two dots followed by a number (..10) checks for that value or lower. You can also negate an exact value or a range by placing an exclamation mark (!) immediately after the equals sign.
When you chain multiple objectives inside the same scores block, the selector applies AND logic—an entity must satisfy every listed condition to be selected. This is the standard method for building shop checks or cooldown gates inside .mcfunction files without needing command blocks or script overhead.
One critical limitation of the scores selector is how it handles uninitialized scores. In Bedrock Edition, an entity does not have a score of 0 by default; its score is simply null (untracked) until a command explicitly sets or adds to it. A selector looking for scores={mana=..5} will not match a newly spawned player who has never had their mana objective modified, even though conceptually you might think of their mana as zero. Always initialize player scores to 0 when they join or when your system starts.
| Syntax | What it matches | Notes |
|---|---|---|
| scores={obj=5} | Entities with an exact score of 5 | Does not match untracked entities even if you test for 0. |
| scores={obj=5..} | Entities with a score of 5 or greater | Inclusive of 5; goes up to the 32-bit integer limit. |
| scores={obj=..5} | Entities with a score of 5 or less | Includes negative numbers down to -2,147,483,648. |
| scores={obj=1..10} | Entities with a score between 1 and 10 | Inclusive of both 1 and 10. |
| scores={obj=!5} | Entities with any tracked score except 5 | Still requires the entity to have a tracked score on that objective. |
| scores={obj=!1..10} | Entities with a tracked score outside the 1 to 10 range | Matches 0 or lower, and 11 or higher. |
# Initialize coins to 0 for any player who does not have a tracked score yet
scoreboard players add @a coins 0
# Notify players who cannot afford the 50-coin cost (0 to 49 coins)
tellraw @s[scores={coins=..49}] {"rawtext":[{"text":"§cYou need at least 50 coins to buy an Iron Sword."}]}
# Give the item and deduct cost only if the player has 50 or more coins
give @s[scores={coins=50..}] iron_sword 1 0
scoreboard players remove @s[scores={coins=50..}] coins 50Comparing Two Dynamic Scores with execute if score
The target selector syntax only allows you to compare a score against hard-coded constants. When you need to compare one entity's score against another entity's score—or compare two different objectives on the same entity—you must use the execute if score (or execute unless score) subcommand. This was introduced with the updated execute syntax and replaces the older, clunky pattern of subtracting scores into a temporary objective.
The execute if score subcommand takes a target, their objective, a comparison operator (<, <=, =, >=, >), a second target, and the second target's objective. In addition to real entities, both the first and second targets can be fake player names (strings that do not correspond to an actual entity in the world, often prefixed with a hash like #global or .temp to prevent collision with real gamertags). The subcommand also supports the matches keyword, which lets you check a fake player's score against a constant range without needing a real entity selector.
When using entity selectors inside execute if score, each selector must resolve to a single entity unless you branch the execution context first with execute as. If a selector inside the score check matches multiple entities at once, the condition will fail to evaluate.
| Subcommand Pattern | What it does | Notes |
|---|---|---|
| if score <A> <objA> = <B> <objB> | Runs if A's score equals B's score | Single equals sign (=), not double. |
| if score <A> <objA> < <B> <objB> | Runs if A's score is strictly less than B's | Also supports <=, >, and >=. |
| if score <A> <objA> matches <range> | Runs if A's score falls within the range | Essential for checking fake player scores against constants. |
| unless score ... | Inverts any of the above checks | Also passes if either target has no tracked score on the objective. |
# Compare the executing player's current points against the global high score held by fake player #server
execute if score @s points > #server high_score run tellraw @a {"rawtext":[{"selector":"@s"},{"text":" just beat the server high score!"}]}
# Copy the player's score into the #server high_score if they beat it
execute if score @s points > #server high_score run scoreboard players operation #server high_score = @s points
# Check a fake player's score against a constant range using 'matches'
execute if score #server round_timer matches ..0 run function arena/end_roundDisplaying Retrieved Scores in UI Text
To retrieve a score and show it to players in chat, actionbars, or titles, you use the rawtext JSON format inside tellraw or titleraw commands. Instead of plain text objects, rawtext arrays accept a score object containing a name field and an objective field. When the game renders the JSON, it looks up the current integer value and substitutes it into the string.
The name field inside the score object can be a target selector (such as @s, @p, or @e[type=armor_stand,c=1]), an explicit player name, or an asterisk (*). The asterisk is a special shorthand that means 'the recipient of this message'. If you run titleraw @a actionbar with name set to *, every player on the server sees their own personal score for that objective, all from a single command execution.
If you use a selector like @s inside the rawtext score object, the command must be executed with an active entity context (for example, via execute as @a at @s run ...). If the entity has no tracked score on that objective, the score component renders as an empty string rather than 0.
# Display each player's own mana and the global wave number on their actionbar
titleraw @a actionbar {"rawtext":[{"text":"§bMana: "},{"score":{"name":"*","objective":"mana"}},{"text":" §7| §eWave: "},{"score":{"name":"#game","objective":"wave"}}]}
# Broadcast the winner's score to everyone in chat
execute as @p[tag=winner] run tellraw @a {"rawtext":[{"selector":"@s"},{"text":" won the match with "},{"score":{"name":"@s","objective":"kills"}},{"text":" kills!"}]}Copying and Math Retrieval with Scoreboard Operations
Commands cannot directly pass a retrieved score as an argument into another command (for instance, you cannot pass a scoreboard value into the amplifier argument of an effect command). However, you can retrieve a score into a temporary working objective to perform arithmetic on it using scoreboard players operation. Because operations modify the target's score in place, the standard recipe is to copy the value into a temporary objective first, then apply math to that copy.
The operation command supports assignment (=), addition (+=), subtraction (-=), multiplication (*=), integer division (/=), modulo (%=), swapping (><), minimum (<), and maximum (>). The minimum and maximum operators are particularly useful for clamping values or finding the highest-scoring player in a group without writing complex conditional chains.
To find the highest score among all online players, set a fake player's score to a very low number (or 0), and then run the > (maximum) operation against @a. The game compares the fake player's score against every matched entity one by one, keeping whichever value is larger after each step.
# Reset the tracker to 0 before scanning
scoreboard players set #max kills 0
# Compare #max against all players; #max keeps the highest value found
scoreboard players operation #max kills > @a kills
# Tag whichever player(s) match that highest value
execute as @a if score @s kills = #max kills run tag @s add leaderReading Scores into Molang Queries
While commands and functions handle server-side logic, resource packs and certain behavior pack filters can retrieve scoreboard values through Molang using query.scoreboard('objective_name'). This query returns the integer score of the entity being evaluated, or 0.0 if the entity has no score on that objective or the objective does not exist.
However, there is a major engine caveat regarding client-server synchronization. Scoreboard data lives on the server. The Bedrock client only knows about a scoreboard objective's values if that objective is currently assigned to one of the active display slots (sidebar, list, or belowname) via scoreboard objectives setdisplay. If an objective is hidden (not displayed in any UI slot), evaluating query.scoreboard on the client side—such as inside an animation controller, render controller, or particle emitter—will always return 0.
Because behaviour pack entity events, environment sensors, and target filters evaluate on the server, you can safely use query.scoreboard inside a behaviour pack's minecraft:entity_sensor or filters block without displaying the objective on screen. Reserve client-side query.scoreboard calls for objectives that you already intend to show on the sidebar or belowname slot.
{
"format_version": "1.20.80",
"minecraft:entity": {
"description": {
"identifier": "wiki:custom_turret",
"is_spawnable": true,
"is_summonable": true
},
"components": {
"minecraft:health": {
"value": 20,
"max": 20
},
"minecraft:environment_sensor": {
"triggers": [
{
"filters": {
"test": "actor_health",
"subject": "self",
"operator": ">",
"value": 0
},
"event": "wiki:check_ammo"
}
]
}
},
"events": {
"wiki:check_ammo": {
"sequence": [
{
"filters": {
"test": "int_property",
"domain": "wiki:ammo_state",
"value": 1
},
"run_command": {
"command": [
"execute if score @s ammo matches 1.. run function turret/fire",
"execute if score @s ammo matches ..0 run PlayAnimation @s animation.turret.empty"
]
}
}
]
}
}
}
}Retrieving and Comparing Scores in the Script API
When your add-on uses a JavaScript/TypeScript behavior pack with the @minecraft/server module, you can read and compare scores directly in code without running commands. You access the scoreboard system through world.scoreboard. From there, getObjective('name') returns a ScoreboardObjective object (or undefined if it has not been created yet).
Every entity and player that has a score tracked on at least one objective is assigned a ScoreboardIdentity, accessible via the entity's scoreboardIdentity property. If an entity has never been added to any scoreboard objective, entity.scoreboardIdentity will be undefined. When you call objective.getScore(entity) or objective.getScore(entity.scoreboardIdentity), the method returns a JavaScript number if the entity has a score on that specific objective, or undefined if they do not.
For fake players, you cannot pass an Entity object; instead, you can pass the string name directly into objective.getScore('fake_player_name') or iterate over objective.getParticipants() to inspectScoreboardIdentity objects whose type is ScoreboardIdentityType.FakePlayer. Using Script API is the only way to feed a scoreboard value directly into dynamic API parameters, such as setting an entity's health, applying knockback vectors, or formatting complex ActionFormData menus.
import { world } from "@minecraft/server";
/**
* Safely retrieves an entity's score on an objective, returning 0 if untracked.
*/
export function getEntityScore(entity, objectiveId) {
const objective = world.scoreboard.getObjective(objectiveId);
if (!objective) {
return 0;
}
if (!entity.scoreboardIdentity) {
return 0;
}
try {
const score = objective.getScore(entity.scoreboardIdentity);
return score ?? 0;
} catch (e) {
return 0;
}
}
/**
* Compares a player's gold score against an item cost and heals them.
*/
export function purchaseHeal(player, cost) {
const currentGold = getEntityScore(player, "gold");
if (currentGold >= cost) {
const objective = world.scoreboard.getObjective("gold");
objective.addScore(player, -cost);
const healthComp = player.getComponent("minecraft:health");
if (healthComp) {
healthComp.resetToMaxValue();
}
player.sendMessage(`§aPurchased heal! Remaining gold: ${currentGold - cost}`);
} else {
player.sendMessage(`§cNot enough gold. You have ${currentGold}, but need ${cost}.`);
}
}Which versions this applies to
Applies to Minecraft Bedrock Edition 1.19.50 and newer (where the new execute if score syntax became standard). Script API examples apply to @minecraft/server 1.8.0 and newer on stable APIs; no experimental toggles are required.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Selector @a[scores={coins=..10}] ignores newly joined players who have 0 coins. | Entities do not have a default score of 0 in Bedrock. Until a score is explicitly initialized on an objective for that entity, their score is null (untracked) and fails all scores={} range checks, including negative or zero-inclusive ranges. | Run 'scoreboard players add @a coins 0' before your check. Adding 0 leaves existing scores untouched while initializing untracked players to 0. |
| Command error: 'Failed to execute ... as multiple targets matched selector' when running execute if score. | The target selectors inside 'execute if score <targetA> <obj> = <targetB> <obj>' can only evaluate one entity on each side at a time. Using @a or @e without c=1 inside the score condition causes the check to fail whenever two or more entities match. | Branch execution first using 'execute as @a if score @s <obj> = ...' so that the score comparison runs individually for each entity via @s. |
| Script error in Content Log: 'TypeError: Cannot read properties of undefined' or native exception when calling objective.getScore(entity). | either the objective itself does not exist in the world yet (world.scoreboard.getObjective returned undefined), or the entity has never had any score set on any objective, meaning entity.scoreboardIdentity is undefined. | Always check that both the objective and entity.scoreboardIdentity are defined before calling getScore(), and use the nullish coalescing operator (score ?? 0) to fall back to 0 when the entity has no score on that specific objective. |
| query.scoreboard('mana') always evaluates to 0 inside a resource pack render controller or animation. | The server only syncs scoreboard values to the client for objectives that are actively displayed in the UI (sidebar, list, or belowname). Hidden objectives are unknown to the client renderer. | Either display the objective using '/scoreboard objectives setdisplay', or move the state to an entity property (defined in the behavior pack entity description with client_sync set to true) instead of using a scoreboard. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
