/f1_sensor

A Home Assistant Custom Integration that provides information about the next Formula 1 race and the full season calendar including Live data like race flags and Race Control messages

Primary LanguagePythonMIT LicenseMIT

F1 Sensor for Home Assistant

hacs_badge Maintenance GitHub last commit

GitHub Repo stars

What is F1 Sensor?

This is a custom integration for Home Assistant that creates sensors using data from the Jolpica-F1 API.

It also fetches live data from Formula 1’s unofficial Live Timing API during active sessions (practice, qualifying, sprint, race). These live sensors only update shortly before, during, and shortly after a session. Outside of session times, they will not update.

It is designed for users who want to build automations, scripts, notifications, TTS messages, or more advanced use cases such as generating dynamic dashboards, triggering race-day routines, syncing events to calendars, or integrating with external services based on upcoming Formula 1 events.

Tip

Visit the F1 Sensor Community at Home Assistant Community Forum to share your project and get help and inspiration. Visit to share you procejt and get help and inspiration

ENTITIES

Entity Info
sensor.f1_next_race Next race info
sensor.f1_season_calendar Full race schedule
sensor.f1_driver_standings Current driver championship standings
sensor.f1_constructor_standings Current constructor standings
sensor.f1_weather Weather forecast at next race circuit
sensor.f1_last_race_results Most recent race results
sensor.f1_season_results All season race results
binary_sensor.f1_race_week on during race week
sensor.f1_constructor_points_progression Constructors Point Progression
ssensor.f1_driver_points_progression Constructors Point Progression
sensor.f1_session_status LIVE - Current session phase (pre, live, suspended, finished, finalised, ended)
sensor.f1_track_status LIVE - Current track status (CLEAR, YELLOW, VSC, SC, RED)
binary_sensor.f1_safety_car LIVE - on when Safety Car (SC) or Virtual Safety Car (VSC) is active
sensor.f1_track_weather LIVE - Current on-track weather (air temp, track temp, rainfall, wind speed, etc.)
sensor.f1_race_lap_count LIVE - Current race lap number (only updates during a race, not during practice/qualy)
sensor.f1_current_session LIVE - Current ongoing session, like Practice 1, Qualification, Race
sensor.f1_driver_list Show list and details on all drivers, including team color, headshot URL etc from the Live API

Installation

You can install this integration as a custom repository by following one of these guides:

With HACS (Recommended)

To install the custom component using HACS:

Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.

or

  1. Install HACS if you don't have it already
  2. Open HACS in Home Assistant
  3. Search for "F1 Sensor"
  4. Click the download button. ⬇️
Without HACS
  1. Download the latest release of the F1 Sensor integration from GitHub Releases.
  2. Extract the downloaded files and place the f1_sensor folder in your Home Assistant custom_components directory (usually located in the config/custom_components directory).
  3. Restart your Home Assistant instance to load the new integration.

Configuration

To add the integration to your Home Assistant instance, use the button below:

Open your Home Assistant instance and start configuration

Manual Configuration

If the button above does not work, you can also perform the following steps manually:

  1. Browse to your Home Assistant instance.
  2. Go to Settings > Devices & Services.
  3. In the bottom right corner, select the Add Integration button.
  4. From the list, select F1 Sensor.
  5. Follow the on-screen instructions to complete the setup.

Live data setup

When adding or reconfiguring the integration, you can choose to enable live data via Formula 1’s unofficial Live Timing API.

  • Enable live F1 API (Race Control/Track/Session)
    Creates three additional live entities:

    • sensor.f1_session_status
    • sensor.f1_track_status
    • binary_sensor.f1_safety_car
    • sensor.f1_track_weather
    • sensor.f1_race_lap_count
    • sensor.f1_current_session
    • sensor.f1_driver_list

    If this option is not selected, these live sensors are not created.

  • Live update delay (seconds)
    Lets you delay delivery of live messages to better align with what you see on TV or streaming.

    Typical broadcast delays:

    • Broadcast TV (satellite/cable/terrestrial): ~5–10 seconds behind
    • Streaming services: ~20–45 seconds behind, sometimes more
    • Sports cable/OTT providers: 45–60 seconds or more depending on provider

    By setting the delay accordingly, your Home Assistant automations (for example flashing lights on a red flag) can sync more closely with the live pictures you are watching.

F1SensorFlag-ezgif com-video-to-gif-converter (5)

More info! - Live session entities
In addition to season and race data, F1 Sensor provides live session entities during race weekends.
sensor.f1_session_status

Reflects the current phase of a session, powered by SessionStatus feed and an internal started_flag.

Possible states

  • pre – session is open but not yet started (typically ~1h before lights out).

  • live – session is running.

  • suspended – a started session is stopped (red flag or interruption).

  • finished – clock is over, chequered flag. RaceControl may still send flags on in-laps.

  • finalised – results have been confirmed.

  • ended – feed is closed for the session.

Typical transitions
pre → live → suspended ↔ live → finished → finalised → ended
After finalised or ended, logic resets and next session begins at pre.


sensor.f1_track_status

Directly reflects the latest TrackStatus feed.

Possible states

  • CLEAR
  • YELLOW
  • VSC
  • SC
  • RED

State reflects the last received track status and may persist briefly after finished while in-laps are ongoing.


binary_sensor.f1_safety_car

Boolean entity derived from track status.

States

  • on – when sensor.f1_track_status is SC or VSC.
  • off – in all other cases.

sensor.f1_track_weather

Updates approximately every minute during an active session.

Attributes include

  • Air temperature
  • Track temperature
  • Rainfall
  • Wind speed

sensor.f1_race_lap_count

Only updates during an active race session.
Shows the current lap number in real time.


image

Race Control messages

Race Control messages are sent as events in Home Assistant under the event type f1_sensor_race_control_event.
These include flags, steward notes, incident reports, and other live race control communications.

Example payloads:

event_type: f1_sensor_race_control_event
data:
  message:
    Utc: "2025-09-19T12:40:18"
    Category: Flag
    Flag: CLEAR
    Scope: Sector
    Sector: 6
    Message: CLEAR IN TRACK SECTOR 6
  received_at: "2025-09-19T12:40:44+00:00"
origin: LOCAL
time_fired: "2025-09-19T12:40:44.106956+00:00"

event_type: f1_sensor_race_control_event
data:
  message:
    Utc: "2025-09-19T12:40:07"
    Category: Flag
    Flag: YELLOW
    Scope: Sector
    Sector: 6
    Message: YELLOW IN TRACK SECTOR 6
  received_at: "2025-09-19T12:40:44+00:00"

event_type: f1_sensor_race_control_event
data:
  message:
    Utc: "2025-09-19T12:40:06"
    Category: Other
    Message: INCIDENT INVOLVING CAR 81 (PIA) NOTED - YELLOW FLAG INFRINGEMENT
  received_at: "2025-09-19T12:40:44+00:00"

Note

Currently, Race Control is published as events only. In a future release, these messages will also be exposed as a > sensor.


Each timestamp attribute (e.g. race_start) is still provided in UTC. In addition, a _local variant such as race_start_local is available. These values use the circuit's timezone so you can easily create automations at the correct local time.

During installation, you can choose exactly which sensors you want to include in your setup.
This gives you control over which data points to load — for example, only the next race and weather, without standings or calendar.

You can always change this selection later by reconfiguring the integration via Settings > Devices & Services in Home Assistant.

The integration fetches fresh data from the Jolpica-F1 API every 1 hours.

I personally use this integration to display the next race and the following three races on an e-ink display. You can read more about that setup here.

Note

If your goal is to visually display upcoming race information, current standings, and more in your Home Assistant dashboard, the FormulaOne Card is the better choice for that purpose.


Known Issue

sensor.f1_season_results may trigger a warning in the Home Assistant logs:

Logger: homeassistant.components.recorder.db_schema
Source: components/recorder/db_schema.py:663
Integration: Recorder
State attributes for sensor.f1_season_results exceed maximum size of 16384 bytes. This can cause database performance issues; Attributes will not be stored

Despite the warning, the sensor should still work fine for display in the frontend. However, to avoid any database load/performance issues, it is recommended to exclude this sensor from being recorded in your recorder: config:

recorder:
  exclude:
    entities:
      - sensor.f1_season_results

Example

Season Progression Charts

These two charts visualize the season progression for both the Drivers’ Championship and the Constructors’ Championship. They rely on data from the sensors sensor.f1_driver_standings and sensor.f1_constructor_standings.

image image

To use these examples, make sure you have the following custom cards installed in Home Assistant: • F1 Sensor integration version 2.3.0 or later • auto-entitiesApexCharts Card

Once installed, you can add the provided YAML configuration to your dashboard to display the charts.

Drivers Progression Chart

type: custom:auto-entities
card_param: series
show_empty: false
card:
  type: custom:apexcharts-card
  header:
    show: true
    title: Season progression - drivers points
    show_states: false
  apex_config:
    chart:
      animations:
        enabled: false
    markers:
      size: 6
      strokeWidth: 2
      hover:
        sizeOffset: 8
    states:
      hover:
        filter:
          type: darken
          value: 0.45
      active:
        allowMultipleDataPointsSelection: false
        filter:
          type: darken
          value: 0.55
    legend:
      show: true
      position: left
      horizontalAlign: left
      itemMargin:
        vertical: 4
      fontSize: 12px
    xaxis:
      type: category
      tickPlacement: between
      labels:
        rotate: -35
        trim: false
        minHeight: 60
    tooltip:
      shared: false
      intersect: true
      x:
        formatter: |
          EVAL:function (val) { return val; }
      "y":
        formatter: |
          EVAL:function (val) { return Math.round(val); }
filter:
  template: >
    {%- set e = 'sensor.f1_driver_points_progression' -%} {%- set drivers =
    state_attr(e, 'drivers') or {} -%} {%- set palette = {
      'VER':'#4781D7','PER':'#6C98FF','NOR':'#F47600','PIA':'#F47600',
      'LEC':'#ED1131','SAI':'#1868DB','HAM':'#ED1131','RUS':'#00D7B6',
      'ALO':'#229971','STR':'#229971','ALB':'#1868DB','SAR':'#1868DB',
      'HUL':'#01C00E','MAG':'#01C00E','TSU':'#4781D7','HAD':'#6C98FF',
      'OCO':'#9C9FA2','GAS':'#00A1E8','BOT':'#9C9FA2','ZHO':'#9C9FA2',
      'LAW':'#6C98FF','RIC':'#6C98FF','ANT':'#00D7B6','DOO':'#00A1E8',
      'BOR':'#01C00E','BEA':'#9C9FA2','COL':'#00A1E8'
    } -%} {%- set ns = namespace(items=[]) -%} {%- for code, d in
    drivers.items() -%}
      {%- set pts = d.cumulative_points if d.cumulative_points is defined else [] -%}
      {%- set last = pts[-1] if pts else 0 -%}
      {%- set name = d.name if d.name is defined else (d.tla if d.tla is defined else code) -%}
      {%- set js = "const a = entity.attributes || {}; const rounds = a.rounds || []; const drv = (a.drivers && a.drivers['" ~ code ~ "']) || {}; const pts = drv.cumulative_points || []; return pts.map((y, i) => { const r = rounds[i] || {}; const rn = (r.round != null) ? r.round : (i+1); const label = 'R' + rn + ' — ' + (r.race_name || ''); return { x: label, y: y }; });" -%}
      {%- set obj = {
        "entity": e,
        "name": name,
        "type": "line",
        "color": palette.get(code, "#888888"),
        "data_generator": js
      } -%}
      {%- set ns.items = ns.items + [ {"code": code, "last": last, "obj": obj} ] -%}
    {%- endfor -%} [ {%- for it in ns.items | sort(attribute='last',
    reverse=true) -%}
      {{ it.obj | tojson }}{{ "," if not loop.last }}
    {%- endfor -%} ]

Constructors Progression Chart

type: custom:auto-entities
card_param: series
show_empty: false
card:
  type: custom:apexcharts-card
  header:
    show: true
    title: Season progression - constructors points
    show_states: false
  apex_config:
    chart:
      animations:
        enabled: false
    markers:
      size: 6
      strokeWidth: 2
      hover:
        sizeOffset: 8
    states:
      hover:
        filter:
          type: darken
          value: 0.45
      active:
        allowMultipleDataPointsSelection: false
        filter:
          type: darken
          value: 0.55
    legend:
      show: true
      position: left
      horizontalAlign: left
      itemMargin:
        vertical: 4
      fontSize: 12px
    xaxis:
      type: category
      tickPlacement: between
      labels:
        rotate: -35
        trim: false
        minHeight: 60
    tooltip:
      shared: false
      intersect: true
      x:
        formatter: |
          EVAL:function (val) { return val; }
      "y":
        formatter: |
          EVAL:function (val) { return Math.round(val); }
filter:
  template: >
    {%- set e = 'sensor.f1_constructor_points_progression' -%} {%- set teams =
    state_attr(e, 'constructors') or {} -%} {# Färg per team (ändra fritt) #}
    {%- set palette = {
      'mclaren':'#F47600', 'red_bull':'#4781D7', 'mercedes':'#00D7B6',
      'williams':'#1868DB', 'aston_martin':'#229971', 'sauber':'#01C00E',
      'ferrari':'#ED1131', 'alpine':'#00A1E8', 'rb':'#6C98FF', 'haas':'#9C9FA2'
    } -%} {%- set ns = namespace(items=[]) -%} {%- for key, t in teams.items()
    -%}
      {%- set pts = t.cumulative_points if t.cumulative_points is defined else [] -%}
      {%- set last = pts[-1] if pts else 0 -%}
      {%- set name =
            (t.identity.name if t.identity is defined and t.identity.name is defined
             else (t.name if t.name is defined
             else (key | replace('_',' ') | title))) -%}
      {%- set js = "const a = entity.attributes || {}; const rounds = a.rounds || []; const team = (a.constructors && a.constructors['" ~ key ~ "']) || {}; const pts = team.cumulative_points || []; return pts.map((y, i) => { const r = rounds[i] || {}; const rn = (r.round != null) ? r.round : (i+1); const label = 'R' + rn + ' — ' + (r.race_name || ''); return { x: label, y: y }; });" -%}
      {%- set obj = {
        "entity": e,
        "name": name,
        "type": "line",
        "color": palette.get(key, "#888888"),
        "data_generator": js
      } -%}
      {%- set ns.items = ns.items + [ {"key": key, "last": last, "obj": obj} ] -%}
    {%- endfor -%} [ {%- for it in ns.items | sort(attribute='last',
    reverse=true) -%}
      {{ it.obj | tojson }}{{ "," if not loop.last }}
    {%- endfor -%} ]

Blueprint

Note

The Formula 1 track status blueprint for Home Assistant is now maintained by EvertJob. You can find the latest version and full instructions here: 👉 github.com/EvertJob/F1-Blueprint

E-ink display

This e-ink display project uses the sensors from this integration to show upcoming Formula 1 races, including race countdown and schedule.

E-ink example


Custom F1 Card by the Community

Community user Tiidler has used the sensors from this integration to create a fully custom F1 dashboard card in Home Assistant, displaying race schedule, standings, podium results, and weather, all styled to fit their setup.

image (1)


Note

Support the API that makes this possible

This integration relies entirely on the amazing Jolpica-F1 API, which provides high-quality and up-to-date Formula 1 data for free.
If you find this integration useful, please consider supporting the creator of the API by donating to their Ko-fi page: https://ko-fi.com/jolpic
Without this API, this integration would not be possible, so any support helps keep it live and maintained. 🙏

Contributing

Contributions, bug reports, and feedback are welcome. Please feel free to open issues or pull requests on GitHub.