FastF1 includes powerful integration with the Ergast API (now hosted at jolpica-f1) for accessing historical F1 data from 1950 onwards. This includes race results, qualifying data, driver standings, constructor information, and more.
Overview
The Ergast API provides comprehensive historical F1 data that complements FastF1’s detailed telemetry and timing data. Use it to:
- Query historical race results and standings
- Access driver and constructor information
- Retrieve qualifying and sprint results
- Get championship standings for any season
- Query circuit information and race schedules
The original Ergast API was deprecated in 2024. FastF1 now uses the jolpica-f1 API (https://api.jolpi.ca/ergast/f1) which maintains the same interface and data format.
Getting Started
Import and initialize the Ergast interface:
from fastf1.ergast import Ergast
# Initialize with default settings
ergast = Ergast()
# Or customize the behavior
ergast = Ergast(
result_type='pandas', # 'pandas' or 'raw'
auto_cast=True, # Automatic type conversion
limit=100 # Max results per request (default: 30, max: 1000)
)
Configuration Options
-
result_type:
'pandas': Returns ErgastSimpleResponse or ErgastMultiResponse as DataFrames (default)
'raw': Returns ErgastRawResponse as JSON-like dict/list structures
-
auto_cast: When True, automatically converts string values to appropriate types (int, float, date)
-
limit: Maximum number of results per request. Default is 30, maximum is 1000.
Querying Race Data
Race Schedule
Get the race calendar for a season:
from fastf1.ergast import Ergast
ergast = Ergast()
# Get current season schedule
schedule = ergast.get_race_schedule(season='current')
print(schedule)
# Get specific season
schedule_2023 = ergast.get_race_schedule(season=2023)
# Get specific race
monaco_2023 = ergast.get_race_schedule(season=2023, round=6)
Race Results
Query race results for one or multiple races:
# Get race results for entire season
results = ergast.get_race_results(season=2022)
# Results are returned as ErgastMultiResponse
print(f"Total races: {len(results.content)}")
# Access results for first race
first_race_results = results.content[0]
print(first_race_results)
# Get race metadata
race_info = results.description
print(race_info)
# Get results for specific race
bahrain_2022 = ergast.get_race_results(season=2022, round=1)
print(bahrain_2022.content[0])
Qualifying Results
# Get qualifying results
quali_results = ergast.get_qualifying_results(season=2023, round=1)
# Access the qualifying data
for idx, quali in enumerate(quali_results.content):
race_name = quali_results.description.iloc[idx]['raceName']
print(f"\n{race_name} Qualifying:")
print(quali[['position', 'Driver', 'Constructor', 'Q1', 'Q2', 'Q3']].head())
Sprint Results
# Get sprint results for races that had sprints
sprint_results = ergast.get_sprint_results(season=2023)
for idx, sprint in enumerate(sprint_results.content):
race_name = sprint_results.description.iloc[idx]['raceName']
print(f"\n{race_name} Sprint:")
print(sprint[['position', 'Driver', 'points']].head())
Driver and Constructor Data
# Get all drivers from a season
drivers_2023 = ergast.get_driver_info(season=2023)
print(drivers_2023[['driverId', 'givenName', 'familyName', 'nationality']])
# Get specific driver information
hamilton = ergast.get_driver_info(driver='hamilton')
print(hamilton)
# Get all drivers who raced for a specific constructor
ferrari_drivers = ergast.get_driver_info(constructor='ferrari', season=2023)
print(ferrari_drivers)
# Get all constructors from a season
constructors = ergast.get_constructor_info(season=2023)
print(constructors[['constructorId', 'name', 'nationality']])
# Get specific constructor
redbull = ergast.get_constructor_info(constructor='red_bull')
print(redbull)
# Get constructors a driver raced for
verstappen_teams = ergast.get_constructor_info(driver='verstappen')
print(verstappen_teams)
Championship Standings
Driver Standings
# Get current driver standings
standings = ergast.get_driver_standings(season='current')
print(standings.content[0][['position', 'Driver', 'points', 'wins']])
# Get standings after specific race
standings_r10 = ergast.get_driver_standings(season=2023, round=10)
print(standings_r10.content[0])
# Get historical championship winner
champion_2010 = ergast.get_driver_standings(
season=2010,
round='last',
standings_position=1
)
print(champion_2010.content[0])
Constructor Standings
# Get constructor championship standings
const_standings = ergast.get_constructor_standings(season=2023)
print(const_standings.content[0][['position', 'Constructor', 'points', 'wins']])
# Get standings after specific race
const_r5 = ergast.get_constructor_standings(season=2023, round=5)
print(const_r5.content[0])
# Get all circuits from a season
circuits = ergast.get_circuits(season=2023)
print(circuits[['circuitId', 'circuitName', 'locality', 'country']])
# Get specific circuit information
monza = ergast.get_circuits(circuit='monza')
print(monza)
# Get circuits used in a specific season
circuits_1980 = ergast.get_circuits(season=1980)
print(circuits_1980)
Advanced Filtering
Combine multiple filters for precise queries:
# Get all pole positions for a driver
poles = ergast.get_qualifying_results(
driver='hamilton',
results_position=1 # P1 in qualifying
)
print(f"Hamilton has {len(poles.content)} pole positions")
# Get all wins for a driver at a specific circuit
monaco_wins = ergast.get_race_results(
driver='senna',
circuit='monaco',
results_position=1
)
print(f"Senna wins at Monaco: {len(monaco_wins.content)}")
# Get races where a driver started from a specific grid position
grid_wins = ergast.get_race_results(
driver='verstappen',
grid_position=1,
results_position=1
)
print(f"Verstappen wins from pole: {len(grid_wins.content)}")
# Get fastest laps for a driver
fastest_laps = ergast.get_race_results(
driver='bottas',
fastest_rank=1
)
print(f"Bottas fastest laps: {len(fastest_laps.content)}")
Handle large result sets with pagination:
# Query with custom limit
ergast = Ergast(limit=50)
results = ergast.get_race_results(season=2022)
# Check if response is complete
print(f"Is complete: {results.is_complete}")
print(f"Total results: {results.total_results}")
# Get next page of results
if not results.is_complete:
next_page = results.get_next_result_page()
print(next_page.content[0])
# Get previous page
if results.total_results > 0:
prev_page = results.get_prev_result_page()
print(prev_page.content[0])
# Get all results by increasing limit
ergast_unlimited = Ergast(limit=1000)
all_results = ergast_unlimited.get_race_results(season=2022)
Working with Response Objects
ErgastSimpleResponse
Single DataFrame response:
seasons = ergast.get_seasons()
# It's a DataFrame
print(type(seasons)) # ErgastSimpleResponse (extends DataFrame)
# Use all Pandas operations
print(seasons.head())
print(seasons['season'].unique())
recent_seasons = seasons[seasons['season'] >= 2020]
ErgastMultiResponse
Multiple DataFrames with description:
results = ergast.get_race_results(season=2023, limit=5)
# Description contains race metadata
print(results.description)
# Columns: season, round, raceName, date, time, etc.
# Content contains list of result DataFrames
print(len(results.content)) # Number of races
# Each element is a DataFrame with race results
for idx, race_results in enumerate(results.content):
race_name = results.description.iloc[idx]['raceName']
winner = race_results.iloc[0]['Driver']
print(f"{race_name}: Winner - {winner}")
Combining with FastF1
Use Ergast for historical context with FastF1 telemetry:
import fastf1
from fastf1.ergast import Ergast
ergast = Ergast()
# Get historical championship battle
standings_2021 = ergast.get_driver_standings(season=2021, round='last')
top_2 = standings_2021.content[0].head(2)
print("2021 Final Standings:")
print(top_2[['position', 'Driver', 'points']])
# Now analyze the deciding race with FastF1
finale = fastf1.get_session(2021, 'Abu Dhabi', 'R')
finale.load()
ver_laps = finale.laps.pick_drivers('VER')
ham_laps = finale.laps.pick_drivers('HAM')
print(f"\nVerstappen average pace: {ver_laps['LapTime'].mean()}")
print(f"Hamilton average pace: {ham_laps['LapTime'].mean()}")
Available Endpoints
The Ergast interface provides these methods:
| Method | Description |
|---|
get_seasons() | List of seasons |
get_race_schedule() | Race calendar/schedule |
get_race_results() | Race finishing results |
get_qualifying_results() | Qualifying session results |
get_sprint_results() | Sprint race results |
get_driver_info() | Driver information |
get_constructor_info() | Constructor/team information |
get_circuits() | Circuit information |
get_driver_standings() | Driver championship standings |
get_constructor_standings() | Constructor championship standings |
get_finishing_status() | Finishing status codes |
get_lap_times() | Lap time data |
get_pit_stops() | Pit stop data |
Error Handling
from fastf1 import exceptions
try:
results = ergast.get_race_results(season=2030) # Future season
except exceptions.ErgastInvalidRequestError as e:
print(f"Invalid request: {e}")
except exceptions.ErgastJsonError as e:
print(f"JSON parsing error: {e}")
Best Practices
- Use appropriate limits - Default is 30, increase to 100-1000 for comprehensive queries
- Cache results - Ergast data is historical and doesn’t change frequently
- Combine filters - Use multiple parameters to reduce result set size
- Check pagination - Use
is_complete property to ensure you have all results
- Use
auto_cast=True - Automatic type conversion makes data easier to work with
Next Steps