Usage Guide
Getting Started
from f1_replay import Manager
mgr = Manager()
The Manager is the main entry point. It handles data loading, caching, and launching the viewer.
Options:
mgr = Manager(
cache_dir="/path/to/data", # Override cache directory
timezone="Europe/Oslo", # Display times in local timezone
)
Seasons & Schedules
Browsing Seasons
mgr.list_years() # Available seasons: [2018, 2019, ..., 2025]
mgr.get_season(2024) # All events for a year
mgr.seasons # Full catalog: {year: [EventInfo, ...]}
Schedule Queries
Print formatted schedule tables filtered by session type:
mgr.season_schedule(2024) # Full season overview
mgr.race_schedule(2024) # Race sessions only
mgr.sprint_schedule(2024) # Sprint weekends
mgr.qualification_schedule(2024) # Qualifying sessions
mgr.practice_schedule(2024) # Practice sessions
Flexible Event Lookup
Events can be found by round number or name (case-insensitive, partial match):
mgr.load_weekend(2024, 8) # By round number
mgr.load_weekend(2024, "monaco") # By name
mgr.load_weekend(2024, "abu dhabi") # Partial match
Loading Data
f1-replay uses a 3-tier caching system. Each tier builds on the previous one.
Tier 1: Season Catalog
Loaded automatically when needed. Contains event metadata for all races in a year.
Tier 2: Weekend Data
Load circuit geometry and weekend metadata:
weekend = mgr.load_weekend(2024, "monaco")
weekend.circuit.track # Track geometry (x, y, z coordinates)
weekend.circuit.pit_lane # Pit lane coordinates
weekend.circuit.corners # Corner positions and numbers
weekend.circuit.circuit_length # Total lap distance in meters
Tier 3: Session Telemetry
Load full telemetry, events, and results for a specific session:
session = mgr.load_session(2024, "monaco", "Race")
# Or shorthand:
session = mgr.load_race(2024, "monaco")
session.drivers # ["VER", "NOR", "LEC", ...]
session.driver_colors # {"VER": "#3671C6", ...}
session.driver_names # {"VER": "Max Verstappen", ...}
session.driver_teams # {"VER": "Red Bull Racing", ...}
session.telemetry # Dict[str, pl.DataFrame]
session.track_status # Yellow flags, safety cars, etc.
session.race_control # Race control messages
session.fastest_laps # Fastest lap events
Telemetry columns: session_time, x, y, z, speed, throttle, brake, rpm, gear, drs, lap_number, compound, tyre_life, track_distance, race_distance, position, interval, status, vx, vy
See Telemetry Reference for full column documentation.
Advanced: DataLoader
For lower-level control over data loading and caching:
from f1_replay import DataLoader
loader = DataLoader() # uses ~/Documents/f1-replay by default
seasons = loader.load_seasons()
weekend = loader.load_weekend(year, round_num, event)
result = loader.load_session(year, round_num, "Race",
event=event,
circuit_length=weekend.circuit.circuit_length)
# result.data = SessionData, result.raw_session = FastF1 session (optional)
Working with Telemetry
Per-Driver DataFrames
Each driver’s telemetry is a Polars DataFrame:
ver = session.telemetry["VER"]
print(ver.columns) # ['session_time', 'x', 'y', 'speed', 'lap_number', ...]
print(ver.shape) # (rows, columns)
Sampling Helpers
Get one telemetry point per lap:
# First point of each lap
lap_data = session.get_telemetry_every_lap("VER")
# Last point of each lap
lap_data = session.get_telemetry_every_lap("VER", offset=-1)
Get telemetry at regular time intervals:
# Every minute
minute_data = session.get_telemetry_every_minute("VER")
# Every 30 seconds
half_min = session.get_telemetry_every_minute("VER", interval=0.5)
Race Order Queries
# Who was in what position at session time 3600s?
order = session.get_order_at_time(3600.0)
# Returns: [(1, "VER", 45230.5), (2, "NOR", 45180.2), ...]
# Standings after lap 30
order = session.get_order_at_lap(30)
# Race leader at a specific time
leader = session.get_leader_at_time(3600.0) # "VER"
For the full method reference, see the Python API Reference.
Circuit Plotting
Generate poster-style circuit maps with customizable visualization:
weekend = mgr.load_weekend(2024, "monaco")
# Clean white track
weekend.plot()
# Colored by marshal sectors
weekend.plot(color_mode="sectors")
# Telemetry overlays (requires session data loaded first)
weekend.plot(color_mode="speed")
weekend.plot(color_mode="throttle")
weekend.plot(color_mode="brake")
weekend.plot(color_mode="height")
Saving to file:
weekend.plot(save_path="monaco_2024.png", dpi=300)
Customizing:
weekend.plot(
figsize=(16, 12), # Figure size (width, height)
color_mode="speed", # Track coloring
track_width=6, # Line width
dpi=150, # Resolution for saved file
)
You can also use the lower-level function directly:
from f1_replay.tools import plot_weekend
fig = plot_weekend(weekend.circuit, weekend.event, color_mode="sectors")
Race Replay Viewer
Launching from Python
mgr.race(2024, "monaco")
# With options
mgr.race(2024, 8, port=8080, force_update=True, sessions=["R", "Q"])
Launching from CLI
f1-replay race 2024 monaco
f1-replay race 2024 8 --port 8080
f1-replay race 2024 "abu dhabi" --force-update
Viewer Features
2D track map with animated car positions and driver colors
Live standings with position tracking, gap times, and tyre compounds
Strategy panel with tyre stint bars and pit stop markers
Lap time chart overlay (top 5 + chased driver)
Starting lights animation and formation lap
Track status overlays (safety car, VSC, red flag, sector yellows)
Rain overlay with particle animation
Race control message feed
Chase mode (follow individual driver with auto-zoom)
Pan/zoom with mouse, session tabs (switch R/Q/FP)
Qualifying results view with delta to pole
Data export (CSV/JSON)
Keyboard Shortcuts
Key |
Action |
|---|---|
|
Play / Pause |
|
Seek 10 seconds |
|
Seek 60 seconds |
|
Increase / Decrease playback speed |
|
Exit chase mode |
|
Toggle lap time chart |
|
Toggle strategy panel |
Configuration
Cache Directory
from f1_replay import set_cache_dir, get_cache_dir
set_cache_dir("/path/to/data") # Persists to ~/.f1replay/config.json
get_cache_dir() # Current cache directory
# Environment variable (highest priority)
export F1_REPLAY_CACHE_DIR=/path/to/data
Priority order: Environment variable > Config file (~/.f1replay/config.json) > Default (~/Documents/f1-replay)
Cache Structure
~/Documents/f1-replay/
├── seasons.pkl
└── 2024/
└── 08_Monaco/
├── Weekend.pkl # Circuit geometry + metadata
├── Race.pkl # Race telemetry
├── Qualifying.pkl # Qualifying telemetry
└── ...
CLI Reference
Entry point: f1-replay (installed via pip)
f1-replay race
Launch the interactive race viewer.
f1-replay race <year> <round|name> [options]
# Examples
f1-replay race 2024 monaco
f1-replay race 2024 8 --port 8080
f1-replay race 2024 "abu dhabi" --force-update
Option |
Default |
Description |
|---|---|---|
|
|
Host to bind |
|
|
Port number |
|
Disable Flask debug mode |
|
|
Force reload from FastF1 (bypass cache) |
|
|
auto |
Override cache directory |
f1-replay seasons
List available seasons and races.
f1-replay seasons # List all available years
f1-replay seasons 2024 # List races for 2024
f1-replay server
Run the Flask API server without pre-loading any race.
f1-replay server --port 8080
Option |
Default |
Description |
|---|---|---|
|
|
Host to bind |
|
|
Port number |
|
Disable Flask debug mode |
|
|
auto |
Override cache directory |
f1-replay config
Show or set configuration.
f1-replay config # Show current config
f1-replay config --set-cache-dir /path/to/data # Set cache directory
f1-replay migrate-cache
Migrate legacy cache files with placeholder track geometry.
f1-replay migrate-cache # Migrate all legacy caches
f1-replay migrate-cache --dry-run # Show what would be migrated
Option |
Description |
|---|---|
|
Preview without modifying files |
|
Override cache directory |
REST API
All endpoints return JSON. The API is served by Flask at http://localhost:5000 by default.
GET /api/seasons
Returns the complete seasons catalog.
Response:
{
"seasons": {
"2024": {
"total_rounds": 24,
"rounds": [
{
"name": "Bahrain Grand Prix",
"official_name": "...",
"circuit_name": "Bahrain International Circuit",
"country": "Bahrain",
"year": 2024,
"round_number": 1,
"start_date": "2024-02-29",
"end_date": "2024-03-02",
"sessions": [
{"name": "Practice 1", "date": "2024-02-29T11:30:00+03:00"},
{"name": "Race", "date": "2024-03-02T18:00:00+03:00"}
],
"timezone_offset": "+03:00",
"format": "conventional"
}
]
}
}
}
Errors: 500 if seasons cannot be loaded.
GET /api/weekend/<year>/<round>
Returns weekend metadata and circuit geometry.
Parameters:
Parameter |
Type |
Example |
|---|---|---|
|
int |
|
|
int |
|
Response:
{
"event": {
"name": "Monaco Grand Prix",
"circuit_name": "Monte Carlo",
"year": 2024,
"round_number": 8,
"sessions": [...]
},
"circuit": {
"track": {
"x": [1234.5, 1235.1, ...],
"y": [5678.3, 5679.0, ...],
"distance": [0.0, 5.6, 11.2, ...],
"lap_distance": 3337.0,
"marshal_sectors": [
{"number": 1, "start_distance": 0.0, "end_distance": 450.0}
],
"speed": [120.5, 125.3, ...],
"z": [100.2, 100.5, ...]
},
"pit_lane": {
"x": [...], "y": [...],
"length": 235.0,
"entry_track_dist": 3100.0,
"exit_track_dist": 200.0
},
"corners": [
{"number": 1, "distance": 120.5, "angle": 90.0, "letter": ""}
],
"rotation": 38.0,
"circuit_length": 3337.0,
"direction_arrow": {"x": 1200.0, "y": 5600.0, "dx": 0.7, "dy": 0.3}
}
}
Errors: 404 if round not found, 500 on server error.
GET /api/session/<year>/<round>/<session_type>
Returns complete session data: metadata, telemetry, events, and results.
Parameters:
Parameter |
Type |
Values |
|---|---|---|
|
int |
|
|
int |
|
|
string |
|
Query Parameters:
Param |
Type |
Description |
|---|---|---|
|
string |
Comma-separated column names to include. If omitted, uses default set. |
Default telemetry fields: session_time, lap_number, x, y, track_distance, race_distance, position, interval, status, compound, tyre_life, speed, vx, vy
Response:
{
"metadata": {
"session_type": "R",
"year": 2024,
"round_number": 8,
"event_name": "Monaco Grand Prix",
"drivers": ["VER", "LEC", "NOR"],
"driver_numbers": {"VER": 1, "LEC": 16, "NOR": 4},
"driver_names": {"VER": "Max Verstappen", "LEC": "Charles Leclerc"},
"driver_teams": {"VER": "Red Bull Racing", "LEC": "Ferrari"},
"driver_colors": {"VER": "#3671C6", "LEC": "#E8002D"},
"team_colors": {"Red Bull Racing": "#3671C6", "Ferrari": "#E8002D"},
"track_length": 3337.0,
"total_laps": 78,
"dnf_drivers": ["PER"]
},
"telemetry": {
"VER": {
"session_time": [0.0, 0.22, 0.44, ...],
"x": [1234.5, 1236.1, ...],
"y": [5678.3, 5680.0, ...],
"lap_number": [0, 0, 1, 1, ...],
"position": [1, 1, 1, ...],
"compound": ["MEDIUM", "MEDIUM", ...],
"speed": [0.0, 45.2, 120.5, ...]
}
},
"events": {
"track_status": [...],
"race_control": [...],
"status_messages": [...]
},
"results": {
"fastest_laps": [...],
"position_history": [...]
}
}
Scheduled sessions (future races) return:
{
"scheduled": true,
"name": "Monaco Grand Prix",
"session_type": "Race",
"scheduled_date": "2025-05-25T15:00:00+02:00",
"scheduled_date_formatted": "Sun 25th May at 15:00",
"message": "The Race is scheduled for Sun 25th May at 15:00"
}
Errors: 404 if session not found, 500 on server error.