Display entities

Lightweight, non-interactive entities that render a block, an item, or text with fully controllable geometry and client-side interpolation for smooth animation.

Overview

Display entities were added in Java Edition 1.19.4 1.19.4+ (snapshot 23w06a, pack_format 12) for the express purpose of rendering a block, an item, or text with fully controllable geometry (position, rotation, scale) and rendering options, plus client-side interpolation for smooth animation. There are three entity IDs:

They have no AI, no collision, no gravity, and are not saved as mobs. They are the modern replacement for armor-stand / falling-block / invisible-marker hacks.

Shared NBT (all three types)

Every field below is common to block_display, item_display, and text_display. Fields marked interpolated are tweened smoothly on the client when changed (see Interpolation and animation).

FieldTypeMeaning / valuesDefault
transformationCompound or list of 16 floatsModel transform. Two accepted forms (see below). Interpolated.identity
interpolation_durationIntNumber of ticks over which an interpolated change is smoothed on the client.0
start_interpolationIntDelay (ticks) before interpolation begins. If 0, interpolation starts immediately (on the next client tick after the update).0
teleport_durationIntInterpolation duration in ticks for position/rotation teleports. Clamped 0–59 inclusive. Added 1.20.2 1.20.2+.0
billboardStringPivot-to-face-player mode: fixed, vertical, horizontal, center.fixed
brightnessCompoundOverrides render light. Sub-fields block (Int 0–15, required) and sky (Int 0–15, required). Omitted ⇒ uses world light.omitted
view_rangeFloatView-range multiplier (render distance).1.0
shadow_radiusFloatShadow radius; treated as 64 if >64; ≤0 ⇒ no shadow. Interpolated.0
shadow_strengthFloatShadow opacity vs. distance to the block below. Interpolated.1
widthFloatCulling box max width; 0 ⇒ no culling.0
heightFloatCulling box max height; 0 ⇒ no culling.0
glow_color_overrideIntOverrides the glow-outline color (packed RGB). -1 ⇒ use the entity's team color.-1
TagsList of StringStandard scoreboard/entity tags (for @e[tag=…] selection).[]
πŸ“Œ Note

Billboard is not glow. billboard only controls whether the entity rotates to face the viewer; it does not make anything glow. Glow (an outline, and for text_display a bright unshaded render) comes from the entity being glowing β€” set Glowing:1b on summon or apply the Glowing effect β€” and the outline color is taken from glow_color_override (or the team color when -1). See The display flags for the text-glow specifics.

The transformation field β€” two forms

transformation accepts either a decomposed compound or a flat affine matrix.

Decomposed form. Applied in this order: right_rotation → scale → left_rotation → translation.

transformation:{
  translation:[0f,0f,0f],          # list of 3 floats
  left_rotation:[0f,0f,0f,1f],     # quaternion [x,y,z,w]  (angle-axis also accepted)
  right_rotation:[0f,0f,0f,1f],    # quaternion [x,y,z,w]
  scale:[1f,1f,1f]                 # list of 3 floats
}

Matrix form. A single list of 16 floats describing a row-major affine transformation matrix:

transformation:[
  1f,0f,0f,0f,
  0f,1f,0f,0f,
  0f,0f,1f,0f,
  0f,0f,0f,1f
]

The two forms are interchangeable. The game stores the decomposed form internally, so reading transformation back via /data get returns the decomposed compound even if you set a matrix.

⚠ Version differences
  • Since 1.19.4 (23w06a): all three display entities introduced.
  • Before 1.19.4 (RC1): the early-snapshot field interpolation_start was replaced by start_interpolation (with a revised meaning as a start delay). If you see interpolation_start in old datapacks it is legacy and no longer valid.
  • Since 1.20.2 (23w31a): teleport_duration added β€” position/rotation teleports interpolate on the client while the server still updates immediately.

block_display specifics

FieldTypeNotes
block_stateCompoundName (block ID, e.g. "minecraft:oak_log") + optional Properties (string map of block-state values).

A rotated, half-scale oak log floating in place

summon block_display ~ ~1 ~ {block_state:{Name:"minecraft:oak_log",Properties:{axis:"y"}},transformation:{translation:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[0.5f,0.5f,0.5f]}}
πŸ“Œ Note

block_state requires string values in Properties (e.g. axis:"y", lit:"true"), matching the blockstate format β€” booleans and ints are written as strings.

item_display specifics

FieldTypeNotes
itemItem stack compound{id:"minecraft:diamond_sword", count:1, components:{…}}. Uses the data-component item format from 1.20.5+ (see version note).
item_displayStringModel transform context. One of: none, thirdperson_lefthand, thirdperson_righthand, firstperson_lefthand, firstperson_righthand, head, gui, ground, fixed. Default none.

A diamond sword shown in the "gui" transform (flat, upright icon look), 2x scale

summon item_display ~ ~1 ~ {item:{id:"minecraft:diamond_sword",count:1},item_display:"gui",transformation:{translation:[0f,0f,0f],left_rotation:[0f,0f,0f,1f],right_rotation:[0f,0f,0f,1f],scale:[2f,2f,2f]},billboard:"vertical"}
⚠ Version differences
  • Before 1.20.5 (≤1.20.4): the item was written with the legacy {id:"…", Count:1b, tag:{…}} NBT (capital Count, tag for custom data).
  • Since 1.20.5 (pack_format 41): items use data components β€” {id:"…", count:1, components:{"minecraft:custom_name":…, …}}. This is what lets an item_display carry a custom model, dyed color, enchant glint, etc. via components.
  • Since 1.21.5: the whole item value, like all NBT, is written in SNBT within commands; component values that are text components follow the flattened text format (see Text components).

text_display specifics

FieldTypeMeaningDefault
textText component (SNBT)The content to render.required
line_widthIntMax pixel width before wrapping.200
backgroundInt (ARGB)Background color packed as ARGB. Alpha below 26 (0x1A) renders fully transparent. Interpolated.1073741824 (0x40000000, ~25% black)
text_opacityByteText alpha 0–255; values 4–26 render transparent. -1 ⇒ 255 (opaque). Interpolated.-1
alignmentStringcenter, left, or right.center
shadowBooleanDraw a drop shadow behind the text.false
see_throughBooleanRender through blocks (X-ray visible).false
default_backgroundBooleanUse the chat-style default background instead of background.false

A left-aligned yellow hologram with a shadow, no culling

summon text_display ~ ~2 ~ {text:'{"text":"Welcome!","color":"yellow"}',alignment:"left",shadow:true,billboard:"center",text_opacity:255b}

The display flags β€” named fields, not a bitmask

Some references describe a "bitmask" (has_shadow, is_see_through, use_default_background, alignment bits). That refers to how the game stores these flags internally / on the network as a single metadata byte. The datapack-facing NBT interface does not expose a bitmask β€” you set the named boolean/string fields instead, and the game maps them to the internal flag names:

Named NBT field (what you write)Internal metadata flag
shadow: truehas_shadow
see_through: trueis_see_through
default_background: trueuse_default_background
alignment: "left" / "right" / "center"alignment flag bits
🚧 Workaround

In a datapack you never write a raw bitmask β€” use shadow, see_through, default_background, and alignment. The hex flag values are a protocol implementation detail, not part of the datapack API.

Glowing text. To make a text_display glow (unshaded bright text with an outline), make the entity glowing β€” Glowing:1b on summon, or apply the Glowing effect β€” and optionally set glow_color_override for the outline/text tint. billboard is unrelated to glow.

Glowing bold red text, billboarded to face the viewer

summon text_display ~ ~2 ~ {text:'{"text":"GLOWING","bold":true}',Glowing:1b,glow_color_override:16711680,billboard:"center"}

Interpolation and animation

Interpolation smoothly tweens the interpolated fields (transformation, shadow_radius, shadow_strength, and for text_display also background and text_opacity) from their current value to a newly set value, over interpolation_duration ticks, starting after start_interpolation ticks.

The correct sequence β€” all on one server tick, in this order:

  1. Set start_interpolation to 0 (begin immediately).
  2. Set interpolation_duration to N (tween length in ticks).
  3. Set the new transformation (or other interpolated field).

If you change interpolation_duration/start_interpolation and the target value on the same tick, the client tweens from the old rendered value to the new one over N ticks. If you forget to (re)set start_interpolation/interpolation_duration before each change, the entity snaps instead of tweening.

Worked animated example β€” spin + grow over 20 ticks. Assumes the text_display was summoned with tag spinner.

data/example/function/spin_start.mcfunction

execute as @e[type=text_display,tag=spinner] run data merge entity @s {start_interpolation:0,interpolation_duration:20,transformation:{translation:[0f,0f,0f],left_rotation:{angle:180f,axis:[0f,1f,0f]},right_rotation:[0f,0f,0f,1f],scale:[2f,2f,2f]}}

Twenty ticks (1 s) later, issue the next keyframe (e.g. from a repeating loop with a schedule/scoreboard timer):

data/example/function/spin_next.mcfunction

execute as @e[type=text_display,tag=spinner] run data merge entity @s {start_interpolation:0,interpolation_duration:20,transformation:{translation:[0f,1f,0f],left_rotation:{angle:360f,axis:[0f,1f,0f]},right_rotation:[0f,0f,0f,1f],scale:[1f,1f,1f]}}
πŸ’‘ Best practice

Always (re)set start_interpolation:0 and interpolation_duration:N on the same tick as the value change, or the display snaps.

πŸ“Œ Note

Position teleport interpolation is separate. To slide the whole entity to a new location smoothly, set teleport_duration (0–59) and then /tp (or /teleport) the entity β€” the client interpolates the move instead of snapping.

Tricks and best practices

🎩 Trick

Holograms. summon text_display with billboard:"center" (and see_through optional) is the standard replacement for armor-stand nameplate holograms β€” no gravity by nature. Do multi-line via \n in text together with line_width. For a clean floating-text look, unset the default translucent background: default_background:false,background:0.

🎩 Trick

Smooth animations. Chain transformation keyframes with interpolation_duration; use teleport_duration (≤59) + /tp for smooth position slides.

🎩 Trick

Nameplate hacks. Parent a text_display to a mob (ride or data-driven position) for custom always-facing nameplates with color/shadow control beyond CustomName.

🎩 Trick

Item icons as GUI. item_display with item_display:"gui" gives a flat, icon-style render useful for map markers or fake HUD elements.

πŸ’‘ Best practice

Set item stacks inside item_display using the 1.20.5+ data-component format; the pre-1.20.5 Count/tag form is invalid on the 1.21+ baseline.

Mannequin β€” the player-avatar entity

minecraft:mannequin 1.21.9+ is a summon-only "technical" entity added in snapshot 25w36a (1.21.9): a player avatar with no connected player β€” it renders a full player skin/model and, unlike display entities, it is a living entity (it has Health, attributes, effects, wears equipment, and takes damage). It has no AI and no pathfinding β€” it never moves on its own, which makes it a clean base for command-driven NPCs and custom boss models.

It can only be created with /summon (there is no item or spawn egg):

/summon minecraft:mannequin ~ ~ ~ {
  profile: {name: "Steve"},
  pose: "standing",
  main_hand: "right",
  immovable: false,
  hidden_layers: [],
  Health: 20f,
  description: {"text":"Nebkheperre","color":"gold"}
}

The floating label above the entity is the description text component β€” not CustomName. (Set CustomName too, with CustomNameVisible:0b, only if you want the death message to name the boss β€” see the JAR note below.)

Mannequin-specific fields

FieldTypeValues / meaningDefault
profileString or CompoundPlayer name as a bare string (resolves that account's skin), or a profile object {name?, id?:int[4], properties?:[{name,value,signature?}]}. For a custom skin not tied to a live account, use the properties form with a textures property (base64) β€” the same minecraft:profile component player heads use. Always saved as a compound; cannot be removed.β€”
poseStringstanding, crouching, swimming, fall_flying, sleeping.standing
main_handStringleft or right β€” dominant hand (affects held-item rendering).right
immovableBooleantrue = the mannequin cannot be pushed or knocked around by physics/knockback.false
hidden_layersList<String>Outer skin layers to hide: cape, jacket, left_sleeve, right_sleeve, left_pants_leg, right_pants_leg, hat.[]
descriptionText component (compound)The mannequin's visible floating label β€” pass a text component, e.g. {"text":"Nebkheperre","color":"gold"}. Note this is not what death messages read (that's the inherited CustomName β€” see the JAR note below).β€”
hide_descriptionBooleantrue = show no description/label at all. JAR-confirmed field name; if the byte form 1b doesn't hide it, try true (bool-coercion unverified).false

Because it is a living entity it also accepts the standard fields β€” Health, attribute modifiers, equipment slots (armor, main/off hand) and ActiveEffects. Per minecraft.wiki it does not support several mob-only tags, notably NoAI, PersistenceRequired, CanPickUpLoot, DeathLootTable, LeftHanded, or leash.

πŸ“Œ JAR-verified (26.1.2-0.19.2)

The seven mannequin fields profile, pose, main_hand, immovable, hidden_layers, description, hide_description (all lowercase) were confirmed from the Mannequin.class constant pool by sibling elkonia-wob (javap). Key consequences:

  • Two different "names." description (a text component) is the visible floating label the mannequin renders. CustomName is inherited from LivingEntity and is what getDisplayName() returns β€” so it drives death/combat messages ("slain by …") and name lookups, and it does not read description. The class overrides no getName/getDisplayName/getCustomName, so death text is CustomName-if-present else the type name "Mannequin". The mannequin doesn't render CustomName as its nameplate (that's description's job), which is why setting CustomName alone can surface as an unstyled tag.
  • Named boss recipe: set both β€” CustomName (text component) + CustomNameVisible:0b to drive the death message while hiding the raw tag, plus description for the visible label. Or deal the kill via /damage <player> <amt> <type> by <named_marker> for clean attribution.
  • hidden_layers rides the same player-model customisation bitmask as a real player's hat/jacket/sleeve toggles.

Still wiki-sourced (not JAR-confirmed): the pose value set (the Pose enum is a separate class).

🚧 Workaround

Making a mannequin move (pure vanilla). There is no native movement field β€” MovementSpeed exists as an attribute but nothing drives it (no AI). Move it from a tick function instead: rotate to face the target, then step with tp @s ^ ^ ^0.2 (local-forward), gated by a block/height check for collision + gravity. Note the interaction with immovable: it blocks physics knockback, but a forced /tp should still reposition the entity β€” so a damageable boss that must not be shoved off its mark can either keep immovable:false and teleport back each tick, or use immovable:true and drive all motion via /tp (confirmed live on 26.1.2: immovable:0b + tp @s ^ ^ ^ movement works).

Steering / facing (JAR-verified 26.1.2-0.19.2). The mannequin is not yaw-locked β€” Mannequin.class overrides no rotation method, so it inherits normal Avatar/LivingEntity rotation and does visually turn. The catch: a local-forward step tp @s ^ ^ ^<speed> moves the entity but does not write its stored yaw, so on its own it "moon-walks." Aim it by writing its rotation each tick β€” tp @s ~ ~ ~ facing entity @p eyes or data modify entity @s Rotation set value [<yaw>f,<pitch>f] β€” and the body (yBodyRot) follows the head with the normal few-tick lag. immovable / isImmobile() gates travel (position), not yaw, so an immovable mannequin can still be turned.

⚠ Version differences

Mannequins do not exist before 1.21.9 / 25w36a β€” this section is just past this Codex's primary 1.21 verification baseline. The field names/casing are JAR-verified on 26.1.2-0.19.2 (see the note above). Still wiki-sourced, not JAR-confirmed: the exact pose value set (standing/crouching/swimming/fall_flying/sleeping) and whether hide_description wants 1b vs true β€” verify both empirically or via a Pose-enum decompile before shipping.

Sources