Skip to main content
This guide walks you through everything you need to know to start analyzing Formula 1 data with tif1.

Prerequisites

Before you begin, ensure you have:
  • Python 3.10 or higher
  • pip or uv package manager
  • Basic knowledge of pandas or polars
  • Internet connection for data fetching

Installation

1

Install tif1

Install using pip or uv:
pip install tifone
2

Verify Installation

Check that tif1 is installed correctly:
python -c "import tif1; print(tif1.__version__)"

Your first analysis

Let’s load and analyze data from a recent race.

Step 1: load a session

import tif1

# Load the 2025 monaco grand prix race
session = tif1.get_session(2025, "Monaco Grand Prix", "Race")

print(f"Loaded session: {session.event} {session.session_type}")
The first time you load a session, tif1 fetches data from the CDN. Subsequent loads are instant thanks to caching.

Step 2: explore drivers

# Get list of drivers
drivers = session.drivers_df

print(drivers[["Driver", "Team", "DriverNumber"]])
Output:
  Driver                Team  DriverNumber
0    VER  Red Bull Racing            33
1    HAM         Mercedes            44
2    LEC          Ferrari            16
...

Step 3: analyze lap times

# Get all laps
laps = session.laps

# Show fastest laps
fastest = laps.nsmallest(10, "LapTime")
print(fastest[["Driver", "LapNumber", "LapTime", "Compound"]])

Step 4: compare drivers

# Get specific drivers
ver = session.get_driver("VER")
lec = session.get_driver("LEC")

# Compare fastest laps
ver_fastest = ver.get_fastest_lap()
lec_fastest = lec.get_fastest_lap()

print(f"VER: {ver_fastest['LapTime'].iloc[0]:.3f}s")
print(f"LEC: {lec_fastest['LapTime'].iloc[0]:.3f}s")

Step 5: analyze telemetry

# Get telemetry for fastest lap
ver_lap = ver.get_fastest_lap()
lap_number = ver_lap["LapNumber"].iloc[0]

lap = ver.get_lap(lap_number)
telemetry = lap.telemetry

# Analyze speed
print(f"Top speed: {telemetry['Speed'].max()} km/h")
print(f"Avg speed: {telemetry['Speed'].mean():.1f} km/h")

Common Patterns

Finding available data

Before loading data, check what’s available:
import tif1

# List all events in 2025
events = tif1.get_events(2025)
print(f"Found {len(events)} events")

# List sessions for an event
sessions = tif1.get_sessions(2025, "Monaco Grand Prix")
print(f"Available sessions: {sessions}")

Filtering Laps

Clean and filter lap data for analysis:
laps = session.laps

# Remove deleted laps
clean = laps[~laps["Deleted"]]

# Remove pit laps
clean = clean[clean["PitInTime"].isna()]

# Remove lap 1 (standing start)
clean = clean[clean["LapNumber"] > 1]

# Filter by compound
soft_laps = clean[clean["Compound"] == "SOFT"]

Analyzing tire strategy

# Group by driver and stint
strategy = laps.groupby(["Driver", "Stint"]).agg({
    "Compound": "first",
    "LapNumber": ["min", "max", "count"]
}).reset_index()

print(strategy)

Weather Analysis

# Get weather data
weather = session.weather

# Check for rain
if weather["Rainfall"].any():
    print("Rain detected during session")
    rain_laps = weather[weather["Rainfall"]]["Time"]
    print(f"Rain from {rain_laps.min():.0f}s to {rain_laps.max():.0f}s")

Performance Tips

Use async for cold cache

When loading data for the first time, use async for 4-5x speedup:
import asyncio
import tif1

async def load_data():
    session = tif1.get_session(2025, "Monaco", "Race")
    laps = await session.laps_async()
    return laps

laps = asyncio.run(load_data())

Batch telemetry fetching

Never fetch telemetry in a loop:
# Fetch all telemetry in parallel (28x faster)
tels = session.get_fastest_laps_tels(by_driver=True)

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

Use Polars for large datasets

# Use polars lib for 2x faster processing
session = tif1.get_session(
    2025,
    "Monaco",
    "Race",
    lib="polars"
)

laps = session.laps  # Returns polars DataFrame

Visualization

Create quick visualizations:
import matplotlib.pyplot as plt

# Plot lap times
laps = session.laps
ver_laps = laps[laps["Driver"] == "VER"]

plt.figure(figsize=(12, 6))
plt.plot(ver_laps["LapNumber"], ver_laps["LapTime"], marker="o")
plt.xlabel("Lap Number")
plt.ylabel("Lap Time (s)")
plt.title("VER Lap Times - Monaco 2025")
plt.grid(True, alpha=0.3)
plt.show()

Error Handling

Handle errors gracefully:
import tif1

try:
    session = tif1.get_session(2025, "Monaco", "Race")
    laps = session.laps
except tif1.DataNotFoundError:
    print("Session data not available")
except tif1.NetworkError as e:
    print(f"Network error: {e}")
except tif1.TIF1Error as e:
    print(f"Error: {e}")

Configuration

Customize tif1 behavior:
import tif1

# Get configuration
config = tif1.get_config()

# Change cache directory
config.cache_dir = "/custom/cache/path"

# Use polars by default
config.lib = "polars"

# Enable debug logging
config.log_level = "DEBUG"

Next Steps

Now that you understand the basics, explore:

Tutorials

Learn advanced analysis techniques

API Reference

Explore the complete API

Best Practices

Learn recommended patterns

Examples

See more code examples

Common Issues

Cache permission errors

If you get permission errors:
# Check cache directory permissions
ls -la ~/.tif1/cache/

# Fix permissions
chmod -R 755 ~/.tif1/cache/

Network Timeouts

If requests timeout:
import tif1

config = tif1.get_config()
config.request_timeout = 30  # Increase timeout to 30s

Memory Issues

For large datasets:
# Use polars (50% less memory)
session = tif1.get_session(2025, "Monaco", "Race", lib="polars")

# Or process drivers one at a time
for driver_code in session.drivers:
    driver = session.get_driver(driver_code)
    laps = driver.laps
    # Process laps
    del laps  # Free memory

Getting Help

FAQ

Common questions and answers

Troubleshooting

Solve common problems

GitHub Issues

Report bugs or request features

Contributing

Contribute to tif1

Quickstart

Quick 30-second start

Best Practices

Recommended patterns

Examples

Common use cases

Tutorials

Step-by-step guides
Last modified on March 13, 2026