Skip to main content

Frontend data

The frontend passes a single hass object around. This object contains the latest state, allows you to send commands back to the server and provides helpers to format entity state.

Components that only need part of this data should consume the relevant context instead.

Whenever a state changes, a new version of the objects that changed are created. So you can easily see if something has changed by doing a strict equality check:

const changed = newVal !== oldVal;

In order to see the data available in the hass object, visit your HomeAssistant frontend in your favorite browser and open the browser's developer tools. On the elements panel, select the <home-assistant> element, or any other element that has the hass property, and then run the following command in the console panel:

$0.hass

This method of reading the hass object should only be used as a reference. In order to interact with hass in your code, make sure it is passed to your code correctly.

Data

Context

The recommended way for a component to get a specific part of Home Assistant data is to consume one of the available Lit contexts. You can also create local contexts to pass data within a component tree.

Use Lit's @consume decorator to register with the context provider. The provider sends the initial value and, when subscribe: true is set, sends updates whenever the value changes.

Available contexts

Contexts are exported from src/data/context/index.ts:

  • statesContext: states of all entities
  • servicesContext: available service actions
  • registriesContext: entity, device, area, and floor registries
  • entitiesContext, devicesContext, areasContext, and floorsContext: individual registry data
  • internationalizationContext: localization, locale settings, translation metadata, and translation loaders
  • apiContext: HTTP and WebSocket API methods
  • connectionContext: WebSocket connection state
  • uiContext: themes, panels, sidebar settings, and other global UI state
  • configContext: Home Assistant configuration, authentication, and user data
  • formattersContext: entity state, attribute, and name formatting methods
  • narrowViewportContext: whether the main viewport uses the narrow layout

Some contexts are loaded only when a component first consumes them. These include labelsContext, fullEntitiesContext, configEntriesContext, manifestsContext, triggerDescriptionsContext, and conditionDescriptionsContext. Their backend subscriptions are removed after the last subscribing component disconnects.

Consume a context in lit

@consume({ context: labelsContext, subscribe: true })
@state()
private _labels?: LabelRegistryEntry[];

hass.states

An object containing the states of all entities in Home Assistant. The key is the entity_id, the value is the state object.

{
"sun.sun": {
"entity_id": "sun.sun",
"state": "above_horizon",
"attributes": {
"next_dawn": "2018-08-18T05:39:19+00:00",
"next_dusk": "2018-08-17T18:28:52+00:00",
"next_midnight": "2018-08-18T00:03:51+00:00",
"next_noon": "2018-08-18T12:03:58+00:00",
"next_rising": "2018-08-18T06:00:33+00:00",
"next_setting": "2018-08-17T18:07:37+00:00",
"elevation": 60.74,
"azimuth": 297.69,
"friendly_name": "Sun"
},
"last_changed": "2018-08-17T13:46:59.083836+00:00",
"last_updated": "2018-08-17T13:49:30.378101+00:00",
"context": {
"id": "74c2b3b429c844f18e59669e4b41ec6f",
"user_id": null
},
},
"light.ceiling_lights": {
"entity_id": "light.ceiling_lights",
"state": "on",
"attributes": {
"min_mireds": 153,
"max_mireds": 500,
"brightness": 180,
"color_temp": 380,
"hs_color": [
56,
86
],
"rgb_color": [
255,
240,
35
],
"xy_color": [
0.459,
0.496
],
"white_value": 200,
"friendly_name": "Ceiling Lights",
"supported_features": 151
},
"last_changed": "2018-08-17T13:46:59.129248+00:00",
"last_updated": "2018-08-17T13:46:59.129248+00:00",
"context": {
"id": "2c6bbbbb66a84a9dae097b6ed6c93383",
"user_id": null
},
}
}

hass.user

The logged in user.

{
"id": "758186e6a1854ee2896efbd593cb542c",
"name": "Paulus",
"is_owner": true,
"is_admin": true,
"credentials": [
{
"auth_provider_type": "homeassistant",
"auth_provider_id": null
}
]
}

Methods

All methods starting with call are async methods. This means that they will return a Promise that will resolve with the result of the call.

hass.callService(domain, service, data)

Call a service action on the backend.

hass.callService('light', 'turn_on', {
entity_id: 'light.kitchen'
});

hass.callWS(message)

Call a WebSocket command on the backend.

this.hass.callWS({
type: 'config/auth/create',
name: 'Paulus',
}).then(userResponse =>
console.log("Created user", userResponse.user.id));

hass.callApi(method, path, data)

Call an API on the Home Assistant server. For example, if you want to fetch all Home Assistant backups by issuing a GET request to /api/hassio/backups:

hass.callApi('get', 'hassio/backups')
.then(backups => console.log('Received backups!', backups));

If you need to pass in data, pass a third argument:

hass.callApi('delete', 'notify.html5', { subscription: 'abcdefgh' });
info

We're moving away from API calls and are migrating everything to hass.callWS(message) calls.

Entity state formatting

These methods allow you to format the state and attributes of an entity. The value will be localized using user profile settings (language, number format, date format, timezone) and unit of measurement.

hass.formatEntityState(stateObj, state)

Format the state of an entity. You need to pass the entity state object.

hass.formatEntityState(hass.states["light.my_light"]); // "On"

You can force the state value using the second optional parameter.

hass.formatEntityState(hass.states["light.my_light"], 'off'); // "Off"

hass.formatEntityAttributeValue(stateObj, attribute, value)

Format the attribute value of an entity. You need to pass the entity state object and the attribute name.

hass.formatEntityAttributeValue(hass.states["climate.thermostat"], "current_temperature"); // "20.5 °C"

You can force the state value using the third optional parameter.

hass.formatEntityAttributeValue(hass.states["climate.thermostat"], "current_temperature", 18); // "18 °C"

hass.formatEntityAttributeName(stateObj, attribute)

Format the attribute name of an entity. You need to pass the entity state object and the attribute name.

hass.formatEntityAttributeName(hass.states["climate.thermostat"], "current_temperature"); // "Current temperature"

hass.formatEntityName(stateObj, name, options)

Available since Home Assistant 2026.4.

Format the display name of an entity using its registry context (entity, device, area, floor). This is the same helper used by the built-in cards (tile, entity rows, etc.) so custom cards can produce consistent labels.

The name argument can be:

  • A plain string — returned as-is. Use this to honor a user-provided override.
  • A single name item, like { type: "entity" }.
  • An array of name items, joined with the separator. Items can reference registry data (entity, device, area, floor) or be literal text.
  • undefined — falls back to the entity's friendly name.
type EntityNameItem =
| { type: "entity" | "device" | "area" | "floor" }
| { type: "text"; text: string };

interface EntityNameOptions {
separator?: string; // defaults to " "
}

For the examples below, assume sensor.living_room_thermostat_temperature is the temperature sensor of a thermostat device, where:

  • entity name: Temperature
  • device name: Thermostat
  • area: Living room
  • floor: Ground floor
const stateObj = hass.states["sensor.living_room_thermostat_temperature"];

// Friendly name fallback
hass.formatEntityName(stateObj, undefined); // "Thermostat Temperature"

// User-provided override
hass.formatEntityName(stateObj, "Indoor temperature"); // "Indoor temperature"

// Single registry item
hass.formatEntityName(stateObj, { type: "entity" }); // "Temperature"
hass.formatEntityName(stateObj, { type: "area" }); // "Living room"

// Composed display with a custom separator
hass.formatEntityName(
stateObj,
[{ type: "device" }, { type: "entity" }],
{ separator: " · " }
); // "Thermostat · Temperature"

// Mix literal text and registry items
hass.formatEntityName(
stateObj,
[{ type: "text", text: "Floor:" }, { type: "floor" }]
); // "Floor: Ground floor"

Using it in a custom card

A common pattern is to accept a name option in the card configuration and forward it directly to formatEntityName. This lets users either provide a string or use the structured form to combine registry data.

type: custom:my-card
entity: sensor.living_room_thermostat_temperature
name:
- type: area
- type: entity

Inside your card class:

setConfig(config) {
if (!config.entity) {
throw new Error("You need to define an entity");
}
this._config = config;
}

render() {
const stateObj = this.hass.states[this._config.entity];
const name = this.hass.formatEntityName(stateObj, this._config.name);
return html`<div>${name}</div>`;
}

Editing it in the visual editor

The frontend ships an entity_name selector that produces values in the shape formatEntityName accepts. In a card using the built-in form editor, reference the entity field through context so the selector knows which entity to resolve the registry context against:

{
name: "name",
selector: {
entity_name: {},
},
context: {
entity: "entity",
},
}

The value produced by the selector matches what formatEntityName accepts: either a plain string (free-form custom name) or one or more EntityNameItem entries (composed from registry data). The selector UI lets users switch between the two modes.

The selector accepts two options:

  • entity_id: hardcode the entity used to preview names (overrides context.entity).
  • default_name: the value shown when the field is empty. Accepts the same string | EntityNameItem | EntityNameItem[] shape.