
History Stats creates a sensor from another entity’s recorded state history. It is the practical way to measure device runtime, the percentage of a day an appliance was active, or how often an entity matched a state.
History Stats versus Counter
A Counter stores a value that automations change. History Stats analyses an entity’s existing state history over a time window. Use Counter for events you actively count; use History Stats for runtime, ratios, and historical state matches.
Create History Stats in the UI
- Open Settings > Devices & services > Helpers.
- Select Create helper, then History Stats.
- Choose the source entity, target state, type, and time period.
- Save it to create a sensor for dashboards and automations.
Time, ratio, and count
- time reports hours in the selected state.
- ratio reports the percentage of the period in that state.
- count reports how many times the state matched in the period. It counts matching states, not necessarily transitions; a state already present at the period start is included.
YAML and useful periods
Specify exactly two of start, end, and duration. Prefer today_at() for local time boundaries.
sensor:
- platform: history_stats
name: Living room light on today
entity_id: light.living_room
state: "on"
type: time
start: "{{ today_at('00:00') }}"
end: "{{ now() }}"
state_class: total_increasingFor yesterday, end at today_at('00:00') and use a 24-hour duration. The same approach works for the current week, month, or a custom trailing window.
Practical runtime examples
Track the time a heater, washer, dryer, dishwasher, or fan is on. Use count for door openings or appliance activations, and ratio for the share of the day a device was active. Use min_state_duration to filter short, noisy state changes.
Recorder and limitations
History Stats requires Recorder history. If a requested duration is longer than purge_keep_days, the result cannot include purged data. The sensor updates when the source changes or about once per minute.
See the official History Stats documentation for the current configuration reference.
Safe periods and practical reporting
For today, use start: "{{ today_at('00:00') }}" and end: "{{ now() }}". For yesterday, end at today_at('00:00') with a 24-hour duration. The current week starts at today_at('00:00') - timedelta(days=now().weekday()), and the current month at today_at('00:00').replace(day=1). These current patterns avoid fragile manual date construction around daylight-saving changes.
Use ratio for the share of a day a light was on. Use count for state matches such as a door being open; it counts matching states, which is not always identical to counting transitions.
Heating mode is not physical runtime
Do not automatically treat climate.heating with state: heat as actual boiler, compressor, or heat-pump runtime. heat commonly means the selected HVAC mode and can remain set while no heat is being delivered. Prefer hvac_action: heating when exposed, or a real demand/boiler relay/pump binary sensor. A template binary sensor that represents that real signal is also a sound source entity.
- platform: history_stats
name: Actual heating runtime today
entity_id: binary_sensor.boiler_active
state: "on"
type: time
start: "{{ today_at('00:00') }}"
end: "{{ now() }}"Validate the data source
Check the exact source state in Developer tools > States and test templates before relying on the value. Use min_state_duration, for example "00:02:00", to ignore short noisy changes. A period longer than Recorder’s purge_keep_days cannot include purged history.

