Skip to main content
The core module provides the primary interface for loading and working with F1 data. All data access flows through the Session object.

get_session

The main entry point for loading F1 session data.
def get_session(
    year: int,
    gp: str | int,
    session: str | int,
    enable_cache: bool | None = None,
    lib: Literal["pandas", "polars"] | None = None
) -> Session
Parameters:
  • year: Season year (2018-current)
  • gp: Grand Prix name or round number (e.g., “Monaco Grand Prix” or 6)
  • session: Session name or number (e.g., “Qualifying”, “Race”, or 5)
  • enable_cache: Enable/disable caching. If None, uses global config
  • lib: DataFrame library choice (“pandas” or “polars”). If None, uses global config
Returns:
  • Session object ready to load data
Raises:
  • DataNotFoundError: If the year, GP, or session doesn’t exist
  • NetworkError: If all CDN sources fail
Example:
import tif1

# By name
session = tif1.get_session(2025, "Monaco Grand Prix", "Qualifying")

# By number
session = tif1.get_session(2025, 6, 3)  # Round 6, Session 3

# With options
session = tif1.get_session(
    2025,
    "Monaco Grand Prix",
    "Race",
    enable_cache=True,
    lib="polars"
)

Session

The Session object is the central hub for all data related to a specific F1 weekend session.

Constructor

Session(
    year: int,
    gp: str,
    session: str,
    enable_cache: bool | None = None,
    lib: Literal["pandas", "polars"] | None = None
)
Use get_session() instead of constructing Session directly. The function handles name normalization and validation.

Properties

year
int
The season year (e.g., 2025).
gp
str
URL-encoded Grand Prix name (e.g., “Monaco_Grand_Prix”).
session
str
URL-encoded session name (e.g., “Qualifying”, “Race”).
lib
Literal['pandas', 'polars']
The DataFrame lib being used for this session.
enable_cache
bool
Whether caching is enabled for this session.
drivers
list[str]
List of driver numbers as strings in the session (e.g., [“1”, “33”, “44”]). Loaded lazily on first access.
This returns driver NUMBERS, not driver codes. For driver codes (e.g., “VER”, “HAM”), use drivers_df["Driver"].
driver_list
list[str]
Alias for drivers property. Returns driver numbers as strings.
drivers_df
DataFrame
DataFrame with driver information including:
  • Driver: 3-letter code
  • Team: Team name
  • DriverNumber: Car number
  • FirstName: Driver’s first name
  • LastName: Driver’s last name
  • TeamColor: Hex color code
  • HeadshotUrl: URL to driver photo
Loaded lazily on first access.
laps
DataFrame
All laps for all drivers. Includes weather data automatically merged. Loaded lazily on first access. Use laps_async() for faster parallel loading.
weather
DataFrame
Weather data recorded during the session with columns:
  • Time: Timestamp
  • AirTemp: Air temperature (°C)
  • TrackTemp: Track temperature (°C)
  • Humidity: Relative humidity (%)
  • Pressure: Atmospheric pressure (mbar)
  • WindSpeed: Wind speed (km/h)
  • WindDirection: Wind direction (degrees)
  • Rainfall: Rainfall indicator
weather_data
DataFrame
Alias for weather property.
race_control_messages
DataFrame
Official messages from Race Control with columns:
  • Time: Message timestamp
  • Category: Message category (e.g., “Flag”, “SafetyCar”)
  • Message: Message text
  • Status: Track status code
  • Flag: Flag type
  • Scope: Message scope
  • Sector: Affected sector
  • RacingNumber: Affected driver number
results
SessionResults
Final classification/results for the session. Contains:
  • Position: Final position
  • Driver: Driver code
  • Team: Team name
  • Points: Championship points earned
  • Status: Finish status
  • Time: Total time or gap
car_data
DataFrame
Car telemetry data aggregated across all laps with columns:
  • Time: Timestamp
  • Speed: Speed (km/h)
  • RPM: Engine RPM
  • nGear: Gear number
  • Throttle: Throttle position (%)
  • Brake: Brake status
  • DRS: DRS status
pos_data
DataFrame
Position data for all cars with columns:
  • Time: Timestamp
  • X, Y, Z: 3D coordinates (meters)
  • Status: Car status
  • Driver: Driver code
session_info
dict
Session metadata including start time, circuit info, and session status.
name
str
Human-readable session name (e.g., “Monaco Grand Prix - Qualifying”).
date
datetime
Session date and time.
event
dict
Event information including circuit details and schedule.
session_start_time
datetime
Official session start time.
t0_date
datetime
Reference time (t=0) for the session.
session_status
list
Session status changes throughout the session.
track_status
DataFrame
Track status changes (flags, safety car, etc.) with timestamps.
total_laps
int | None
Total number of laps completed in the session.
This property is not yet implemented and currently returns None.

Methods

load()

def load(
    laps: bool = True,
    telemetry: bool = True,
    weather: bool = True,
    messages: bool = True
) -> Session
Explicitly load session data. By default, data is loaded lazily when accessed. Parameters:
  • laps: Load lap timing data
  • telemetry: Prefetch telemetry for all laps (expensive)
  • weather: Load weather data
  • messages: Load race control messages
Returns:
  • Self (for method chaining)
Example:
# Load only laps and weather
session = tif1.get_session(2025, "Monaco", "Race")
session.load(laps=True, telemetry=False, weather=True, messages=False)

# Or use lazy loading (recommended)
session = tif1.get_session(2025, "Monaco", "Race")
laps = session.laps  # Loads automatically

laps_async()

async def laps_async() -> DataFrame
Asynchronously load all laps for all drivers using parallel HTTP requests. This is the fastest way to initialize a session. Returns:
  • DataFrame with all laps
Example:
import asyncio
import tif1

async def main():
    session = tif1.get_session(2025, "Monaco", "Race")
    laps = await session.laps_async()
    print(f"Loaded {len(laps)} laps")

asyncio.run(main())

get_driver()

def get_driver(driver: str | int) -> Driver
Get a Driver object for the specified driver. Parameters:
  • driver: 3-letter driver code (e.g., “VER”) or driver number (e.g., 33)
Returns:
  • Driver object
Raises:
  • DriverNotFoundError: If the driver doesn’t exist in this session
Example:
ver = session.get_driver("VER")
ver = session.get_driver(33)  # By number

get_fastest_laps()

def get_fastest_laps(
    by_driver: bool = True,
    drivers: list[str] | None = None
) -> DataFrame
Get the fastest lap(s) from the session. Parameters:
  • by_driver: If True, returns fastest lap per driver. If False, returns single overall fastest lap
  • drivers: Optional list of driver codes to filter. If None, includes all drivers
Returns:
  • DataFrame with fastest lap(s)
Example:
# Fastest lap per driver
fastest = session.get_fastest_laps(by_driver=True)

# Overall fastest lap
fastest = session.get_fastest_laps(by_driver=False)

# Fastest laps for specific drivers
fastest = session.get_fastest_laps(by_driver=True, drivers=["VER", "HAM", "LEC"])

get_fastest_laps_async()

async def get_fastest_laps_async(
    by_driver: bool = True,
    drivers: list[str] | None = None
) -> DataFrame
Async version of get_fastest_laps() for parallel data fetching.

get_fastest_lap_tel()

def get_fastest_lap_tel(ultra_cold: bool | None = None) -> DataFrame
Optimized method to get telemetry for the single overall fastest lap of the session. Uses ultra-cold start optimization to minimize latency. Parameters:
  • ultra_cold: Enable ultra-low latency mode. If None, uses global config
Returns:
  • DataFrame with telemetry data
Example:
# Get fastest lap telemetry
tel = session.get_fastest_lap_tel()
print(f"Max speed: {tel['Speed'].max()} km/h")

get_fastest_lap_tel_async()

async def get_fastest_lap_tel_async(
    ultra_cold: bool | None = None
) -> DataFrame
Async version of get_fastest_lap_tel().

get_fastest_laps_tels()

def get_fastest_laps_tels(
    by_driver: bool = True,
    drivers: list[str] | None = None,
    ultra_cold: bool | None = None
) -> dict[str, DataFrame]
Parallel fetch telemetry for multiple drivers’ fastest laps. Significantly faster than fetching telemetry sequentially. Parameters:
  • by_driver: If True, gets fastest lap per driver. If False, gets overall fastest
  • drivers: Optional list of driver codes to filter
  • ultra_cold: Enable ultra-low latency mode
Returns:
  • Dictionary mapping driver codes to telemetry DataFrames
Example:
# Get telemetry for all drivers' fastest laps
tels = session.get_fastest_laps_tels(by_driver=True)

for driver, tel in tels.items():
    print(f"{driver}: {tel['Speed'].max():.1f} km/h")

# Get telemetry for specific drivers
tels = session.get_fastest_laps_tels(
    by_driver=True,
    drivers=["VER", "HAM", "LEC"]
)
Performance Tip: This method fetches telemetry for multiple drivers in parallel, which is significantly faster than calling get_fastest_lap_tel() sequentially for each driver.

get_fastest_laps_tels_async()

async def get_fastest_laps_tels_async(
    by_driver: bool = True,
    drivers: list[str] | None = None,
    ultra_cold: bool | None = None
) -> dict[str, DataFrame]
Async version of get_fastest_laps_tels().

fetch_driver_laps_parallel()

async def fetch_driver_laps_parallel(
    drivers: list[str]
) -> dict[str, DataFrame]
Fetch lap data for multiple drivers in parallel. Parameters:
  • drivers: List of driver codes
Returns:
  • Dictionary mapping driver codes to lap DataFrames
Example:
import asyncio

async def main():
    session = tif1.get_session(2025, "Monaco", "Race")
    laps_dict = await session.fetch_driver_laps_parallel(["VER", "HAM", "LEC"])

    for driver, laps in laps_dict.items():
        print(f"{driver}: {len(laps)} laps")

asyncio.run(main())

fetch_all_laps_telemetry()

def fetch_all_laps_telemetry(
    drivers: list[str] | None = None,
    ultra_cold: bool | None = None
) -> dict[tuple[str, int], DataFrame]
Fetch telemetry for all laps of specified drivers. Parameters:
  • drivers: Optional list of driver codes. If None, fetches for all drivers
  • ultra_cold: Enable ultra-low latency mode
Returns:
  • Dictionary mapping (driver, lap_number) tuples to telemetry DataFrames
Warning: This can be very slow and data-intensive. Use sparingly.

fetch_all_laps_telemetry_async()

async def fetch_all_laps_telemetry_async(
    drivers: list[str] | None = None,
    ultra_cold: bool | None = None
) -> dict[tuple[str, int], DataFrame]
Async version of fetch_all_laps_telemetry().

get_circuit_info()

def get_circuit_info() -> CircuitInfo
Get circuit information including track length and corner locations. Returns:
  • CircuitInfo object

Driver

Represents a specific driver’s performance within a session. Provides convenient access to driver-specific lap data and telemetry.

Constructor

Driver(
    session: Session,
    driver: str,
    driver_number: str | None = None,
    team: str | None = None
)
Use session.get_driver() instead of constructing Driver directly.

Properties

driver
str
The 3-letter driver code (e.g., “VER”, “HAM”, “LEC”).
driver_number
str
The car number (e.g., “33”, “44”, “16”).
team
str
Team name (e.g., “Red Bull Racing”, “Mercedes”, “Ferrari”).
laps
DataFrame
All laps completed by this driver. Loaded lazily on first access. Contains all lap timing data including sector times, compounds, stint info, etc.
session
Session
Reference to the parent session object.

Methods

get_lap()

def get_lap(lap_number: int) -> Lap
Get a specific lap by number. Parameters:
  • lap_number: The lap number to retrieve (1-indexed)
Returns:
  • Lap object for the specified lap
Raises:
  • LapNotFoundError: If the lap doesn’t exist for this driver
Example:
ver = session.get_driver("VER")
lap_19 = ver.get_lap(19)
print(f"Lap time: {lap_19.lap_time:.3f}s")

get_fastest_lap()

def get_fastest_lap() -> DataFrame
Get this driver’s fastest lap as a single-row DataFrame. Returns:
  • Single-row DataFrame with the fastest lap data
Example:
fastest = ver.get_fastest_lap()
print(f"Fastest: {fastest['LapTime'].iloc[0]:.3f}s")
print(f"Compound: {fastest['Compound'].iloc[0]}")

get_fastest_lap_tel()

def get_fastest_lap_tel(ultra_cold: bool | None = None) -> DataFrame
Get telemetry for this driver’s fastest lap. Parameters:
  • ultra_cold: Enable ultra-low latency mode. If None, uses global config
Returns:
  • DataFrame with telemetry data (Time, Speed, RPM, Throttle, etc.)
Example:
fastest_tel = ver.get_fastest_lap_tel()
print(f"Max speed: {fastest_tel['Speed'].max():.1f} km/h")
print(f"Avg throttle: {fastest_tel['Throttle'].mean():.1f}%")

Lap

Represents a single lap, providing access to high-frequency telemetry data. This is a lightweight wrapper around lap timing data with lazy telemetry loading.

Constructor

Lap(
    session: Session,
    driver: str,
    lap_number: int
)
Use driver.get_lap() instead of constructing Lap directly.

Properties

lap_number
int
The lap number (1-indexed).
driver
str
The 3-letter driver code.
lap_time
float
The lap time in seconds. Access using Series methods:
lap_time = lap.get('LapTime')  # Returns timedelta
# or
lap_time_seconds = lap.get('LapTimeSeconds')  # Returns float
telemetry
DataFrame
High-frequency telemetry data for this lap. Loaded lazily on first access. Contains Time, Speed, RPM, Throttle, Brake, nGear, DRS, and position data.
session
Session
Reference to the parent session object.

Methods

get_telemetry()

def get_telemetry() -> DataFrame
Explicitly load telemetry data. Same as accessing the telemetry property. Returns:
  • DataFrame with telemetry samples
Example:
lap = ver.get_lap(19)
tel = lap.get_telemetry()

# Analyze telemetry
print(f"Samples: {len(tel)}")
print(f"Max speed: {tel['Speed'].max()} km/h")
print(f"Max RPM: {tel['RPM'].max()}")

get_car_data()

def get_car_data(**kwargs) -> DataFrame
Get car telemetry data (Speed, RPM, Throttle, Brake, nGear, DRS). Returns:
  • DataFrame with car telemetry channels

get_pos_data()

def get_pos_data(**kwargs) -> DataFrame
Get position data (X, Y, Z coordinates). Returns:
  • DataFrame with position data

get_weather_data()

def get_weather_data() -> DataFrame
Get weather data for this lap. Returns:
  • DataFrame with weather information

Complete Examples

Basic session usage

import tif1

# Load session
session = tif1.get_session(2025, "Monaco Grand Prix", "Qualifying")

# Access drivers
print(f"Drivers: {session.drivers}")

# Get all laps
laps = session.laps
print(f"Total laps: {len(laps)}")

# Get fastest laps
fastest = session.get_fastest_laps(by_driver=True)
print(fastest[["Driver", "LapTime", "Compound"]].head())

Working with Drivers

# Get specific driver
ver = session.get_driver("VER")
print(f"Driver: {ver.driver}")
print(f"Team: {ver.team}")
print(f"Number: {ver.driver_number}")

# Get driver's laps
ver_laps = ver.laps
print(f"Laps completed: {len(ver_laps)}")

# Get fastest lap
fastest = ver.get_fastest_lap()
print(f"Fastest: {fastest['LapTime'].iloc[0]:.3f}s")

Working with Telemetry

# Get fastest lap telemetry
tel = session.get_fastest_lap_tel()

# Analyze telemetry
# Available columns: Time, Speed, RPM, Throttle, Brake, nGear, DRS, X, Y, Z, Distance
print(f"Max speed: {tel['Speed'].max():.1f} km/h")
print(f"Max RPM: {tel['RPM'].max()}")
print(f"Avg throttle: {tel['Throttle'].mean():.1f}%")

# Find braking zones
braking = tel[tel['Brake'] == True]
print(f"Braking points: {len(braking)}")

# Plot speed trace
import matplotlib.pyplot as plt
plt.plot(tel['Distance'], tel['Speed'])
plt.xlabel('Distance (m)')
plt.ylabel('Speed (km/h)')
plt.show()
Available Telemetry Columns:
  • Time: Timestamp (timedelta)
  • Speed: Speed in km/h
  • RPM: Engine RPM
  • Throttle: Throttle position (0-100%)
  • Brake: Brake status (boolean or 0-100%)
  • nGear: Gear number
  • DRS: DRS status
  • X, Y, Z: 3D position coordinates (meters)
  • Distance: Distance along track (meters)

Parallel data loading

import asyncio
import tif1

async def load_session():
    session = tif1.get_session(2025, "Monaco", "Race")

    # Load laps in parallel
    laps = await session.laps_async()

    # Get telemetry for multiple drivers in parallel
    tels = await session.get_fastest_laps_tels_async(
        by_driver=True,
        drivers=["VER", "HAM", "LEC"]
    )

    for driver, tel in tels.items():
        print(f"{driver}: {tel['Speed'].max():.1f} km/h")

asyncio.run(load_session())
Performance Tip: laps_async() is significantly faster than the laps property for cold starts because it fetches all driver lap data in parallel. Use async methods when performance is critical.

Ultra-cold start mode

# Enable ultra-cold start for minimal latency
session = tif1.get_session(2025, "Monaco", "Qualifying")

# Get fastest lap telemetry with ultra-cold optimization
tel = session.get_fastest_lap_tel(ultra_cold=True)

# This skips loading all laps and goes directly to the fastest lap
print(f"Loaded in minimal time: {len(tel)} samples")
Ultra-cold mode bypasses cache validation and skips loading unnecessary data for faster cold starts. Use when you need minimal latency and don’t need all session data. The trade-off is that some data validation is skipped.

Error Handling

import tif1
from tif1.exceptions import DriverNotFoundError, LapNotFoundError, DataNotFoundError

try:
    session = tif1.get_session(2025, "Monaco", "Race")
    driver = session.get_driver("VER")
    lap = driver.get_lap(1)
except DriverNotFoundError as e:
    print(f"Driver not found: {e}")
except LapNotFoundError as e:
    print(f"Lap not found: {e}")
except DataNotFoundError as e:
    print(f"Session data not available: {e}")

Performance Comparison

import time
import asyncio
import tif1

# Sync approach (slower)
start = time.time()
session = tif1.get_session(2025, "Monaco", "Race")
laps = session.laps  # Sequential loading
print(f"Sync: {time.time() - start:.2f}s")

# Async approach (faster)
async def load_async():
    start = time.time()
    session = tif1.get_session(2025, "Monaco", "Race")
    laps = await session.laps_async()  # Parallel loading
    print(f"Async: {time.time() - start:.2f}s")

asyncio.run(load_async())
Best Practices:
  • Use async methods (laps_async(), get_fastest_laps_tels_async()) for cold starts
  • Enable caching to speed up subsequent loads
  • Use ultra_cold=True when you only need specific data
  • Filter drivers with the drivers parameter to reduce data transfer

Troubleshooting

Common Issues

Issue: DriverNotFoundError when using driver codes
# ❌ Wrong - drivers property returns numbers, not codes
drivers = session.drivers  # Returns ["1", "33", "44"]
driver = session.get_driver(drivers[0])  # May fail if "1" is not a valid code

# ✅ Correct - use drivers_df to get codes
drivers_df = session.drivers_df
driver_code = drivers_df.iloc[0]["Driver"]  # Returns "VER"
driver = session.get_driver(driver_code)
Issue: LapNotFoundError when accessing laps
# ❌ Wrong - lap numbers start at 1, not 0
lap = driver.get_lap(0)  # Raises LapNotFoundError

# ✅ Correct - use 1-indexed lap numbers
lap = driver.get_lap(1)  # First lap
Issue: Empty telemetry data
# Check if telemetry is available
tel = lap.get_telemetry()
if len(tel) == 0:
    print("No telemetry data available for this lap")
else:
    print(f"Telemetry loaded: {len(tel)} samples")
Issue: Slow data loading
# ❌ Slow - sequential loading
for driver_code in ["VER", "HAM", "LEC"]:
    driver = session.get_driver(driver_code)
    tel = driver.get_fastest_lap_tel()

# ✅ Fast - parallel loading
tels = session.get_fastest_laps_tels(
    by_driver=True,
    drivers=["VER", "HAM", "LEC"]
)