Skip to content

character.getProperty()

Read a value from the character behind the token — the sheet, not the token's copy of it.

Part of the Action API · Function reference

Available on character, which is null when the token is not linked to a character. Check before using it:

if (!character) return 'This token has no character sheet.';

Signature

character.getProperty(propertyName: string): unknown

Synchronous. Read-only — there is no character.setProperty().

Parameters

Parameter Type Description
propertyName string An attribute name, a metadata key, or one of the exposed top-level fields. Case-insensitive.

Returns

The value, or undefined when the name matches nothing or names something the character API does not expose.

What it can see

Three places are searched, in order, and the first match wins:

  1. Attributes — the character's own attributes, returned as the computed value: the number shown on the sheet, with every component and floor already applied. This is the main reason to use character rather than token.
  2. Metadata — the character's metadata map, matched case-insensitively.
  3. A short list of top-level fields — name, level, systemId, classes, and origins. Nothing else.

Everything else on a character is deliberately out of reach: skills, feats, attacks, notes, raw artwork records, ids, and the rest all return undefined. The character API is a small, stable window onto the sheet, not a view of its internals.

character versus token

They answer different questions, and the difference matters:

token.getProperty() character.getProperty()
Reads The token's own stored values The character sheet
Attributes Whatever was projected onto the token The computed value, live from the sheet
Writable Yes, via setProperty() No
Available Always Only when the token is linked to a character

A token's values can drift from its character's — that is what makes a temporarily buffed minion possible. Read token for the state of this figure on the map, and character for what the sheet says.

Examples

Guard, then read

if (!character) return `${token.name} has no character sheet.`;
const str = character.getProperty('Strength');
sendMessage(`${character.getProperty('name')} — Strength ${str}`);

Scale an effect by level

const level = Number(character.getProperty('level') ?? 1);
const damage = roll(`${Math.ceil(level / 2)}d6`, { label: 'Searing Smite' });
target?.applyDamage(damage, 'radiant');

Fall back to the token

const wis = character?.getProperty('Wisdom') ?? token.getProperty('wis') ?? 10;

Compare sheet against token

const sheet = character?.getProperty('Dexterity');
const onMap = token.getProperty('dex');
if (sheet !== undefined && sheet !== onMap) {
  sendMessage(`<i>${token.name} is running on modified Dexterity (${onMap} vs ${sheet}).</i>`);
}

Notes and gotchas

  • character is often null. Monsters, scenery, and hand-placed tokens have no sheet. Every use needs a guard or ?..
  • Read-only, and that is the design. Use setProperty() on the token to change anything.
  • Attribute names, as the sheet spells them. Resolution here is a plain case-insensitive name match — it does not follow the alias and id chain that token.getProperty() does, so 'str' may miss where 'Strength' hits.
  • undefined is ambiguous. It means "not found or not exposed".

See also