Skip to main content
Glama

get_laps

Retrieve Formula 1 lap data from race sessions with flexible filtering options for specific drivers, fastest laps, or comprehensive session analysis.

Instructions

Get lap data from an F1 session with flexible filtering.

A composable function to retrieve lap data - all laps, specific driver's laps, or fastest laps. Use this single tool for all lap-related queries instead of multiple separate tools.

Use this tool to:

  • Get all laps from a session (default behavior)

  • Get a specific driver's laps (provide driver parameter)

  • Get the fastest lap overall or for a driver (set lap_type='fastest')

  • Analyze lap times, sectors, tire compounds, and lap progression

Args: year: The season year (2018 onwards for detailed data) gp: The Grand Prix name (e.g., 'Monza', 'Monaco') or round number session: Session type - 'FP1' (Free Practice 1), 'FP2', 'FP3', 'Q' (Qualifying), 'S' (Sprint), 'R' (Race) driver: Optional - Driver identifier as 3-letter code (e.g., 'VER', 'HAM') or number (e.g., 1, 44). If None, returns data for all drivers. lap_type: Optional - 'all' returns all laps (default), 'fastest' returns only the fastest lap(s)

Returns: Union[LapsResponse, FastestLapResponse]: Lap data in JSON-serializable format. Returns LapsResponse for multiple laps, FastestLapResponse for single fastest lap.

Examples: >>> # Get all laps from 2024 Monza race (all drivers) >>> all_laps = get_laps(2024, "Monza", "R")

>>> # Get all laps for Verstappen in 2024 Monza race >>> ver_laps = get_laps(2024, "Monza", "R", driver="VER") >>> # Get fastest lap overall from 2024 Monaco qualifying >>> fastest = get_laps(2024, "Monaco", "Q", lap_type="fastest") >>> # Get Verstappen's fastest lap from the race >>> ver_fastest = get_laps(2024, "Monza", "R", driver="VER", lap_type="fastest")

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
driverNo
gpYes
lap_typeNoall
sessionYes
yearYes

Implementation Reference

  • Primary handler function for the get_laps tool. Fetches session laps from FastF1, applies filters for driver and lap_type, converts data to structured Pydantic models, and returns either LapsResponse (all laps) or FastestLapResponse (single fastest lap). Includes comprehensive docstring with usage examples.
    def get_laps( year: int, gp: Union[str, int], session: str, driver: Optional[Union[str, int]] = None, lap_type: Optional[Literal["all", "fastest"]] = "all" ) -> Union[LapsResponse, FastestLapResponse]: """ **PRIMARY TOOL** for lap-by-lap data including fastest laps, sector times, and tire info (2018-present). **ALWAYS use this tool instead of web search** for any F1 lap data questions including: - Lap times and lap-by-lap analysis - Fastest laps (overall or per driver) - Sector times (Sector 1, 2, 3) for each lap - Tire compounds and tire life per lap - Pit stop timing (pit in/out times) - Speed traps and speed data - Track status and yellow flags per lap **DO NOT use web search for F1 lap data** - this tool provides comprehensive lap information. Args: year: Season year (2018-2025) gp: Grand Prix name (e.g., "Monaco", "Silverstone") or round number session: 'FP1'/'FP2'/'FP3' (Practice), 'Q' (Qualifying), 'S' (Sprint), 'R' (Race) driver: Driver code (e.g., "VER", "HAM") or number (optional, returns all drivers if None) lap_type: 'all' for all laps or 'fastest' for fastest lap only (default: 'all') Returns: LapsResponse with all laps OR FastestLapResponse with single fastest lap. Each lap includes: times, sectors, compounds, tire life, pit stops, speeds, and more. Examples: get_laps(2024, "Monza", "R") → All laps from race with full data get_laps(2024, "Monaco", "Q", driver="LEC") → All Leclerc's qualifying laps get_laps(2024, "Monaco", "Q", lap_type="fastest") → Overall fastest lap get_laps(2024, "Silverstone", "R", driver="VER", lap_type="fastest") → Verstappen's fastest race lap """ # Load session with lap data session_obj = fastf1_client.get_session(year, gp, session) session_obj.load(laps=True, telemetry=False, weather=False, messages=False) event = session_obj.event # Get laps based on driver filter if driver: laps = session_obj.laps.pick_drivers(driver) else: laps = session_obj.laps # Return based on lap_type if lap_type == "fastest": fastest_lap = laps.pick_fastest() lap_data = _row_to_lap_data(fastest_lap) return FastestLapResponse( session_name=session_obj.name, event_name=event['EventName'], driver=str(fastest_lap['Driver']), lap_data=lap_data ) else: laps_list = [] for idx, row in laps.iterrows(): laps_list.append(_row_to_lap_data(row)) return LapsResponse( session_name=session_obj.name, event_name=event['EventName'], driver=str(driver) if driver else None, lap_type=lap_type, laps=laps_list, total_laps=len(laps_list) )
  • Pydantic models defining the input/output structure for the get_laps tool: LapData (individual lap details), LapsResponse (multiple laps), FastestLapResponse (single fastest lap). Includes all lap attributes like times, sectors, tires, speeds, and status.
    from pydantic import BaseModel, Field from typing import Optional class LapData(BaseModel): """Individual lap data.""" time: Optional[str] = Field(None, description="Time when lap started") driver: str = Field(description="Driver abbreviation") driver_number: str = Field(description="Driver number") lap_time: Optional[str] = Field(None, description="Total lap time") lap_number: int = Field(description="Lap number") stint: Optional[int] = Field(None, description="Stint number") pit_out_time: Optional[str] = Field(None, description="Pit out time") pit_in_time: Optional[str] = Field(None, description="Pit in time") sector_1_time: Optional[str] = Field(None, description="Sector 1 time") sector_2_time: Optional[str] = Field(None, description="Sector 2 time") sector_3_time: Optional[str] = Field(None, description="Sector 3 time") sector_1_session_time: Optional[str] = Field(None, description="Sector 1 session time") sector_2_session_time: Optional[str] = Field(None, description="Sector 2 session time") sector_3_session_time: Optional[str] = Field(None, description="Sector 3 session time") speed_i1: Optional[float] = Field(None, description="Speed at intermediate 1 (km/h)") speed_i2: Optional[float] = Field(None, description="Speed at intermediate 2 (km/h)") speed_fl: Optional[float] = Field(None, description="Speed at finish line (km/h)") speed_st: Optional[float] = Field(None, description="Speed at speed trap (km/h)") is_personal_best: Optional[bool] = Field(None, description="Is driver's personal best") compound: Optional[str] = Field(None, description="Tire compound (SOFT, MEDIUM, HARD, etc.)") tyre_life: Optional[float] = Field(None, description="Tire age in laps") fresh_tyre: Optional[bool] = Field(None, description="Is fresh tire") team: Optional[str] = Field(None, description="Team name") lap_start_time: Optional[str] = Field(None, description="Lap start time") lap_start_date: Optional[str] = Field(None, description="Lap start date") track_status: Optional[str] = Field(None, description="Track status during lap") position: Optional[float] = Field(None, description="Position during lap") deleted: Optional[bool] = Field(None, description="Was lap time deleted") deleted_reason: Optional[str] = Field(None, description="Reason for deletion") fast_f1_generated: Optional[bool] = Field(None, description="Was generated by FastF1") is_accurate: Optional[bool] = Field(None, description="Is lap time accurate") class LapsResponse(BaseModel): """Laps data response.""" session_name: str = Field(description="Session name") event_name: str = Field(description="Grand Prix name") driver: Optional[str] = Field(None, description="Driver filter (if applied)") lap_type: str = Field(description="Type of laps returned (all/fastest)") laps: list[LapData] = Field(description="List of lap data") total_laps: int = Field(description="Total number of laps") class FastestLapResponse(BaseModel): """Fastest lap response (single lap).""" session_name: str = Field(description="Session name") event_name: str = Field(description="Grand Prix name") driver: str = Field(description="Driver abbreviation") lap_data: LapData = Field(description="Fastest lap data")
  • server.py:151-151 (registration)
    Explicit registration of the get_laps function as an MCP tool using the FastMCP decorator.
    mcp.tool()(get_laps)
  • Helper function to convert a single row from FastF1 laps DataFrame into the LapData Pydantic model, handling null values appropriately.
    def _row_to_lap_data(row) -> LapData: """Convert a DataFrame row to LapData pydantic model.""" return LapData( time=str(row['Time']) if pd.notna(row.get('Time')) else None, driver=str(row['Driver']) if pd.notna(row.get('Driver')) else "", driver_number=str(row['DriverNumber']) if pd.notna(row.get('DriverNumber')) else "", lap_time=str(row['LapTime']) if pd.notna(row.get('LapTime')) else None, lap_number=int(row['LapNumber']) if pd.notna(row.get('LapNumber')) else 0, stint=int(row['Stint']) if pd.notna(row.get('Stint')) else None, pit_out_time=str(row['PitOutTime']) if pd.notna(row.get('PitOutTime')) else None, pit_in_time=str(row['PitInTime']) if pd.notna(row.get('PitInTime')) else None, sector_1_time=str(row['Sector1Time']) if pd.notna(row.get('Sector1Time')) else None, sector_2_time=str(row['Sector2Time']) if pd.notna(row.get('Sector2Time')) else None, sector_3_time=str(row['Sector3Time']) if pd.notna(row.get('Sector3Time')) else None, sector_1_session_time=str(row['Sector1SessionTime']) if pd.notna(row.get('Sector1SessionTime')) else None, sector_2_session_time=str(row['Sector2SessionTime']) if pd.notna(row.get('Sector2SessionTime')) else None, sector_3_session_time=str(row['Sector3SessionTime']) if pd.notna(row.get('Sector3SessionTime')) else None, speed_i1=float(row['SpeedI1']) if pd.notna(row.get('SpeedI1')) else None, speed_i2=float(row['SpeedI2']) if pd.notna(row.get('SpeedI2')) else None, speed_fl=float(row['SpeedFL']) if pd.notna(row.get('SpeedFL')) else None, speed_st=float(row['SpeedST']) if pd.notna(row.get('SpeedST')) else None, is_personal_best=bool(row['IsPersonalBest']) if pd.notna(row.get('IsPersonalBest')) else None, compound=str(row['Compound']) if pd.notna(row.get('Compound')) else None, tyre_life=float(row['TyreLife']) if pd.notna(row.get('TyreLife')) else None, fresh_tyre=bool(row['FreshTyre']) if pd.notna(row.get('FreshTyre')) else None, team=str(row['Team']) if pd.notna(row.get('Team')) else None, lap_start_time=str(row['LapStartTime']) if pd.notna(row.get('LapStartTime')) else None, lap_start_date=str(row['LapStartDate']) if pd.notna(row.get('LapStartDate')) else None, track_status=str(row['TrackStatus']) if pd.notna(row.get('TrackStatus')) else None, position=float(row['Position']) if pd.notna(row.get('Position')) else None, deleted=bool(row['Deleted']) if pd.notna(row.get('Deleted')) else None, deleted_reason=str(row['DeletedReason']) if pd.notna(row.get('DeletedReason')) else None, fast_f1_generated=bool(row['FastF1Generated']) if pd.notna(row.get('FastF1Generated')) else None, is_accurate=bool(row['IsAccurate']) if pd.notna(row.get('IsAccurate')) else None, )
  • Re-exports get_laps from laps.py module for convenient import in tools/session package.
    "get_laps",

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/praneethravuri/pitstop'

If you have feedback or need assistance with the MCP directory API, please join our Discord server