Wiki 9Minecraft Wiki 9Minecraft

Comparing and Retrieving Scoreboard Values in Commands and Scripts

Read, display, and branch logic using scoreboard values across functions, UI, and Script API.

6Sections
6Code examples
4Known errors

Scoreboards are the primary numerical storage system in Minecraft Bedrock Edition for tracking player states, timers, and game logic. Retrieving and comparing these values allows your add-on to trigger events when thresholds are met, compare two entities against each other, or render dynamic stats on the screen. You will use these patterns whenever you build shops, cooldown systems, round timers, or custom HUD elements.

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.

SyntaxWhat it matchesNotes
scores={obj=5}Entities with an exact score of 5Does not match untracked entities even if you test for 0.
scores={obj=5..}Entities with a score of 5 or greaterInclusive of 5; goes up to the 32-bit integer limit.
scores={obj=..5}Entities with a score of 5 or lessIncludes negative numbers down to -2,147,483,648.
scores={obj=1..10}Entities with a score between 1 and 10Inclusive of both 1 and 10.
scores={obj=!5}Entities with any tracked score except 5Still 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 rangeMatches 0 or lower, and 11 or higher.
BP/functions/shop/buy_sword.mcfunction
# 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 50

Comparing 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 PatternWhat it doesNotes
if score <A> <objA> = <B> <objB>Runs if A's score equals B's scoreSingle equals sign (=), not double.
if score <A> <objA> < <B> <objB>Runs if A's score is strictly less than B'sAlso supports <=, >, and >=.
if score <A> <objA> matches <range>Runs if A's score falls within the rangeEssential for checking fake player scores against constants.
unless score ...Inverts any of the above checksAlso passes if either target has no tracked score on the objective.
BP/functions/arena/check_highscore.mcfunction
# 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_round

Displaying 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.

BP/functions/ui/update_hud.mcfunction
# 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.

BP/functions/arena/find_leader.mcfunction
# 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 leader

Reading 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.

BP/entities/custom_turret.json
{
  "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.

BP/scripts/score_utils.js
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 seeWhyThe 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.