Ratings & Levels
<home_name> is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. Can't find a sensor? Use the Entity Reference (All Languages) to search by name in your language.
The integration provides two classification systems for electricity prices. Both are useful, but serve different purposes.
Ratings vs Levels at a Glance
| Ratings | Levels | |
|---|---|---|
| Source | Calculated by integration | Provided by Tibber API |
| Scale | 3 levels (LOW, NORMAL, HIGH) | 5 levels (VERY_CHEAP → VERY_EXPENSIVE) |
| Basis | Trailing 24h average | Daily min/max range |
| Best for | Automations (simple thresholds) | Dashboard displays (fine granularity) |
| Configurable | Yes (thresholds) | Gap tolerance only |
| Automation attribute | rating_level (always lowercase English) | level (always uppercase English) |
Which to use?
- Automations: Use ratings (3 simple states, configurable thresholds, hysteresis)
- Dashboards: Use levels (5 color-coded states, more visual granularity)
- Advanced automations: Combine both (e.g., "LOW rating AND VERY_CHEAP level")
Rating Sensors
Rating sensors classify prices relative to the trailing 24-hour average, answering: "Is the current price cheap, normal, or expensive compared to recent history?"
How Ratings Work
The integration calculates a percentage difference between the current price and the trailing 24-hour average:
Show formula: How Ratings Work
difference = ((current_price - trailing_avg) / abs(trailing_avg)) × 100%
This percentage is then classified:
| Rating | Condition (default) | Meaning |
|---|---|---|
| LOW | difference ≤ -10% | Significantly below recent average |
| NORMAL | -10% < difference < +10% | Within normal range |
| HIGH | difference ≥ +10% | Significantly above recent average |
Hysteresis (default 2%) prevents flickering: once a rating enters LOW, it must cross -8% (not -10%) to return to NORMAL. This avoids rapid switching at threshold boundaries.
The 2% gap between entering (−10%) and leaving (−8%) a state prevents the sensor from flickering back and forth when prices hover near a threshold.
Available Rating Sensors
| Sensor | Scope | Description |
|---|---|---|
| Current Price Rating | Current interval | Rating of the current 15-minute price |
| Next Price Rating | Next interval | Rating for the upcoming 15-minute price |
| Previous Price Rating | Previous interval | Rating for the past 15-minute price |
| Current Hour Price Rating | Rolling 5-interval | Smoothed rating around the current hour |
| Next Hour Price Rating | Rolling 5-interval | Smoothed rating around the next hour |
| Yesterday's Price Rating | Calendar day | Aggregated rating for yesterday |
| Today's Price Rating | Calendar day | Aggregated rating for today |
| Tomorrow's Price Rating | Calendar day | Aggregated rating for tomorrow |
Key Attributes
| Attribute | Description | Example |
|---|---|---|
rating_level | Language-independent rating (always lowercase) | low |
difference | Percentage difference from trailing average | -12.5 |
trailing_avg_24h | The reference average used for classification | 22.3 |
Usage in Automations
Best Practice: Always use the rating_level attribute (lowercase English) instead of the sensor state (which is translated to your HA language):
Show YAML: Usage in Automations
# ✅ Correct — language-independent
condition:
- condition: template
value_template: >
{{ state_attr('sensor.<home_name>_current_price_rating', 'rating_level') == 'low' }}
# ❌ Avoid — breaks when HA language changes
condition:
- condition: state
entity_id: sensor.<home_name>_current_price_rating
state: "Low" # "Niedrig" in German, "Lav" in Norwegian...
Configuration
Rating thresholds can be adjusted in the options flow:
- Go to Settings → Devices & Services → Tibber Prices → Configure
- Navigate to Price Rating Thresholds
- Adjust LOW/HIGH thresholds, hysteresis, and gap tolerance
See Price Rating Thresholds for details.
Level Sensors
Level sensors show the Tibber API's own price classification with a 5-level scale:
| Level | Meaning | Numeric Value |
|---|---|---|
| VERY_CHEAP | Exceptionally low | -2 |
| CHEAP | Below average | -1 |
| NORMAL | Typical range | 0 |
| EXPENSIVE | Above average | +1 |
| VERY_EXPENSIVE | Exceptionally high | +2 |
Available Level Sensors
| Sensor | Scope |
|---|---|
| Current Price Level | Current interval |
| Next Price Level | Next interval |
| Previous Price Level | Previous interval |
| Current Hour Price Level | Rolling 5-interval window |
| Next Hour Price Level | Rolling 5-interval window |
| Yesterday's Price Level | Calendar day (aggregated) |
| Today's Price Level | Calendar day (aggregated) |
| Tomorrow's Price Level | Calendar day (aggregated) |
Gap tolerance smoothing is applied to prevent isolated level flickers (e.g., a single NORMAL between two CHEAPs → corrected to CHEAP). Configure in Price Level Gap Tolerance.
How Long Does It Stay Cheap?
The Current Price Level sensor (current_interval_price_level) tells you how long the current cheap or expensive stretch lasts, and when the next one starts. A stretch is a run of intervals with CHEAP or VERY_CHEAP (or EXPENSIVE or VERY_EXPENSIVE), after gap tolerance smoothing.
| Attribute | Description | Example |
|---|---|---|
cheap_until | End of the current cheap stretch; null if the price isn't cheap right now, or if the end isn't known yet (see below) | 2026-10-14T05:30:00+02:00 |
next_cheap_start | Start of the next cheap stretch after the current one | 2026-10-13T20:15:00+02:00 |
expensive_until | End of the current expensive stretch; null if the price isn't expensive right now, or if the end isn't known yet | null |
next_expensive_start | Start of the next expensive stretch after the current one | 2026-10-14T07:00:00+02:00 |
These complement the best and peak price periods, which are calculated differently and can be shorter or longer. Typical cases:
- The best price period ends at 04:15, but prices stay cheap until 05:30 (
cheap_until): no need to rush. - Prices turn cheap at 20:15 (
next_cheap_start), an hour before the best price period starts.
All values only cover the prices that are already known (today, and tomorrow from the early afternoon). If a stretch lasts until the last known price, its end isn't known yet, so cheap_until stays null even though the price is cheap. Example: at 22:00, before tomorrow's prices are published, a cheap stretch running into the night has no cheap_until. Check the sensor state to tell "not cheap" from "cheap, end unknown".
Show YAML: Notify when prices stay cheap after the best price period
automation:
- alias: "Cheap prices continue after best price period"
trigger:
- platform: state
entity_id: binary_sensor.<home_name>_best_price_period
to: "off"
condition:
- condition: state
entity_id: sensor.<home_name>_current_price_level
state: ["cheap", "very_cheap"]
action:
- service: notify.mobile_app_phone
data:
message: >
{% set until = state_attr('sensor.<home_name>_current_price_level', 'cheap_until') %}
Best price period is over, but prices stay cheap
{{ 'until ' ~ (as_timestamp(until) | timestamp_custom('%H:%M')) if until else 'for now (end not known yet)' }}.
💬 Comments are page-specific. For a new question or idea, open a dedicated Discussion on GitHub so it gets its own thread and proper visibility.