Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A production-grade Python SDK for the OpenF1 API, providing easy access to real-time and historical Formula 1 data.

License

Notifications You must be signed in to change notification settings

rhtnr/OpenF1-python-client

Repository files navigation

๐ŸŽ๏ธ OpenF1 Python Client

A production-grade Python SDK for the OpenF1 API, providing easy access to real-time and historical Formula 1 data.

PyPI version PyPI downloads Publish to PyPI Python 3.10+ License: MIT Code style: black Pydantic v2 Ruff

Buy Me A Coffee


๐Ÿ“‘ Table of Contents


โœจ Features

  • ๐Ÿ”Œ Full API Coverage โ€” Access all 16 OpenF1 endpoints including telemetry, lap times, positions, weather, and more
  • ๐Ÿ”’ Type Safety โ€” Fully typed with Pydantic v2 models and comprehensive type hints
  • ๐ŸŽฏ Pythonic Filtering โ€” Use dictionaries with comparison operators for flexible queries
  • ๐Ÿ” Authentication Support โ€” OAuth2 password flow for real-time data access
  • โš ๏ธ Robust Error Handling โ€” Comprehensive exception hierarchy with detailed error information
  • ๐Ÿš€ Production Ready โ€” Automatic retries, configurable timeouts, and logging support
  • ๐Ÿ“Š Multiple Formats โ€” JSON and CSV response support

๐Ÿ“ฆ Installation

pip install OpenF1-python-client

Or install from source:

git clone https://github.com/rhtnr/OpenF1-python-client.git
cd OpenF1-python-client
pip install -e .

For development:

pip install -e ".[dev]"

๐Ÿš€ Quick Start

Basic Usage (Unauthenticated)

Historical data is available without authentication:

from openf1_client import OpenF1Client
# Create a client
client = OpenF1Client()
# Get lap data for a specific driver
laps = client.laps.list(
 session_key=9161,
 driver_number=63,
)
for lap in laps:
 print(f"Lap {lap.lap_number}: {lap.lap_duration}s")
# Don't forget to close the client when done
client.close()

Using Context Manager

from openf1_client import OpenF1Client
with OpenF1Client() as client:
 # Get driver information
 drivers = client.drivers.list(session_key=9158)
 for driver in drivers:
 print(f"{driver.name_acronym}: {driver.full_name} - {driver.team_name}")

๐Ÿ” Authenticated Usage

For real-time data and higher rate limits, authenticate with your OpenF1 credentials:

from openf1_client import OpenF1Client
client = OpenF1Client(
 username="your_email@example.com",
 password="your_password",
)
# Access real-time data
latest_session = client.sessions.first(session_key="latest")
print(f"Current session: {latest_session.session_name}")

Or use a pre-existing access token:

client = OpenF1Client(access_token="your_access_token")

๐Ÿ” Filtering Data

OpenF1 supports rich filtering with comparison operators. The client provides a Pythonic interface:

Simple Equality

# Filter by exact values
laps = client.laps.list(
 session_key=9161,
 driver_number=63,
 lap_number=8,
)

Comparison Operators

Use dictionaries with operator keys for comparisons:

# Speed >= 315 km/h
fast_telemetry = client.car_data.list(
 session_key=9159,
 driver_number=55,
 speed={">=": 315},
)
# Close intervals (< 0.5 seconds)
close_battles = client.intervals.list(
 session_key=9161,
 interval={"<": 0.5},
)

Range Filters

# Date range
location_data = client.location.list(
 session_key=9161,
 driver_number=81,
 date={
 ">": "2023-09-16T13:03:35.200",
 "<": "2023-09-16T13:03:35.800",
 },
)
# Lap range
stint_laps = client.laps.list(
 session_key=9161,
 driver_number=1,
 lap_number={">=": 10, "<=": 20},
)

Using FilterBuilder

For more complex filters, use the FilterBuilder helper:

from openf1_client import OpenF1Client, FilterBuilder
with OpenF1Client() as client:
 filters = (
 FilterBuilder()
 .eq("session_key", 9161)
 .eq("driver_number", 1)
 .gte("speed", 300)
 .lt("lap_number", 10)
 .build()
 )
 car_data = client.car_data.list(**filters)

๐Ÿ“ก Available Endpoints

Endpoint Description Example
๐ŸŽ๏ธ car_data Car telemetry (~3.7 Hz) client.car_data.list(...)
๐Ÿ‘ค drivers Driver information client.drivers.list(...)
โฑ๏ธ intervals Gap data (~4s updates) client.intervals.list(...)
๐Ÿ”„ laps Lap timing data client.laps.list(...)
๐Ÿ“ location Car positions (~3.7 Hz) client.location.list(...)
๐Ÿ meetings Grand Prix metadata client.meetings.list(...)
๐Ÿ”€ overtakes Passing events (beta) client.overtakes.list(...)
๐Ÿ›ž pit Pit stop activity client.pit.list(...)
๐Ÿ“Š position Track positions client.position.list(...)
๐Ÿšฉ race_control Flags, incidents client.race_control.list(...)
๐Ÿ“… sessions Session data client.sessions.list(...)
๐Ÿ† session_result Final results (beta) client.session_result.list(...)
๐Ÿšฆ starting_grid Grid positions (beta) client.starting_grid.list(...)
๐Ÿ”ง stints Stint/tyre data client.stints.list(...)
๐Ÿ“ป team_radio Radio communications client.team_radio.list(...)
๐ŸŒค๏ธ weather Weather data (~1 min) client.weather.list(...)

๐Ÿ› ๏ธ Endpoint Methods

Each endpoint provides several methods:

# List all matching records
laps = client.laps.list(session_key=9161, driver_number=1)
# Get first matching record (or None)
lap = client.laps.first(session_key=9161, driver_number=1, lap_number=1)
# Get raw data (dict) without model parsing
raw_data = client.laps.list_raw(session_key=9161)
# Get CSV format
csv_data = client.laps.list_csv(session_key=9161)
# Count matching records
count = client.laps.count(session_key=9161, driver_number=1)

Many endpoints also provide convenience methods:

# ๐Ÿ”„ Laps
fastest_lap = client.laps.get_fastest_lap(session_key=9161)
flying_laps = client.laps.get_flying_laps(session_key=9161, driver_number=1)
# ๐Ÿ“… Sessions
races = client.sessions.get_races(year=2023)
latest = client.sessions.get_latest()
# ๐Ÿ”ง Stints
strategy = client.stints.get_tyre_strategy(session_key=9161, driver_number=1)
# ๐ŸŒค๏ธ Weather
rain = client.weather.get_rain_periods(session_key=9161)

โš™๏ธ Configuration

from openf1_client import OpenF1Client
client = OpenF1Client(
 # ๐Ÿ” Authentication
 username="user@example.com",
 password="secret",
 # Or use a token directly
 # access_token="your_token",
 # ๐ŸŒ Connection settings
 timeout=60.0, # Request timeout in seconds
 # timeout=(5.0, 30.0), # (connect, read) timeouts
 max_retries=5, # Retry failed requests
 # ๐Ÿ“„ Response format
 default_format="json", # "json" or "csv"
 # ๐Ÿ”’ SSL/TLS
 verify_ssl=True,
)

โš ๏ธ Error Handling

The client provides a comprehensive exception hierarchy:

from openf1_client import (
 OpenF1Client,
 OpenF1Error, # Base exception
 OpenF1ConfigError, # Invalid configuration
 OpenF1TransportError, # Network errors
 OpenF1APIError, # API errors (non-2xx)
 OpenF1AuthError, # 401/403 errors
 OpenF1RateLimitError, # 429 errors
 OpenF1NotFoundError, # 404 errors
 OpenF1ServerError, # 5xx errors
 OpenF1TimeoutError, # Request timeout
 OpenF1ValidationError, # Data validation
)
try:
 with OpenF1Client() as client:
 laps = client.laps.list(session_key=99999)
except OpenF1NotFoundError as e:
 print(f"โŒ Session not found: {e}")
except OpenF1RateLimitError as e:
 print(f"โณ Rate limited. Retry after: {e.retry_after}s")
except OpenF1APIError as e:
 print(f"โš ๏ธ API error {e.status_code}: {e.message}")
except OpenF1Error as e:
 print(f"๐Ÿ’ฅ Client error: {e}")

๐Ÿ“ Logging

Enable debug logging to see HTTP requests and responses:

from openf1_client import setup_logging
import logging
# Enable debug logging
setup_logging(logging.DEBUG)
# Or configure manually
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("openf1_client")
logger.setLevel(logging.DEBUG)

๐Ÿ“Š Data Models

All responses are parsed into Pydantic models with full type annotations:

from openf1_client import OpenF1Client, Lap, Driver
with OpenF1Client() as client:
 lap: Lap = client.laps.first(session_key=9161, driver_number=1, lap_number=1)
 if lap:
 print(f"Lap duration: {lap.lap_duration}")
 print(f"Sector 1: {lap.duration_sector_1}")
 print(f"Sector 2: {lap.duration_sector_2}")
 print(f"Sector 3: {lap.duration_sector_3}")
 print(f"Speed trap: {lap.st_speed} km/h")

๐Ÿ’ก Examples

๐Ÿ Analyze a Race

from openf1_client import OpenF1Client
with OpenF1Client() as client:
 # Get session info
 session = client.sessions.first(session_key=9161)
 print(f"๐Ÿ Session: {session.session_name} - {session.country_name}")
 # Get all drivers
 drivers = client.drivers.list(session_key=9161)
 for driver in drivers:
 # Get their fastest lap
 fastest = client.laps.get_fastest_lap(
 session_key=9161,
 driver_number=driver.driver_number,
 )
 # Get pit stops
 pit_count = client.pit.count_pit_stops(
 session_key=9161,
 driver_number=driver.driver_number,
 )
 # Get tyre strategy
 strategy = client.stints.get_tyre_strategy(
 session_key=9161,
 driver_number=driver.driver_number,
 )
 print(f"๐ŸŽ๏ธ {driver.name_acronym}: "
 f"Fastest: {fastest.lap_duration if fastest else 'N/A'}s, "
 f"Stops: {pit_count}, "
 f"Tyres: {' โ†’ '.join(strategy)}")

๐ŸŒค๏ธ Track Weather Changes

from openf1_client import OpenF1Client
with OpenF1Client() as client:
 weather_data = client.weather.list(session_key=9161)
 for w in weather_data:
 rain_emoji = "๐ŸŒง๏ธ" if w.rainfall else "โ˜€๏ธ"
 print(f"{rain_emoji} {w.date}")
 print(f" ๐ŸŒก๏ธ Air: {w.air_temperature}ยฐC")
 print(f" ๐Ÿ›ฃ๏ธ Track: {w.track_temperature}ยฐC")
 print(f" ๐Ÿ’ง Humidity: {w.humidity}%")

๐Ÿ”€ Find Overtakes

from openf1_client import OpenF1Client
from collections import Counter
with OpenF1Client() as client:
 overtakes = client.overtakes.list(session_key=9161)
 print(f"๐Ÿ”€ Total overtakes: {len(overtakes)}")
 # Get drivers with most overtakes
 overtake_counts = Counter(o.driver_number for o in overtakes)
 print("\n๐Ÿ† Top overtakers:")
 for driver_num, count in overtake_counts.most_common(5):
 driver = client.drivers.first(
 session_key=9161,
 driver_number=driver_num,
 )
 print(f" {driver.name_acronym}: {count} overtakes")

๐Ÿ”ฎ Future Enhancements

The client is designed to be easily extended. Planned additions:

โšก Async Support

# Future async client (design ready, not yet implemented)
from openf1_client import AsyncOpenF1Client
async with AsyncOpenF1Client() as client:
 laps = await client.laps.list(session_key=9161)

๐Ÿ“ก Real-time Streaming

# Future streaming support (design ready)
# Via MQTT or WebSockets for live data
async for telemetry in client.car_data.stream(driver_number=1):
 print(f"๐ŸŽ๏ธ Speed: {telemetry.speed} km/h")

๐Ÿค Contributing

Contributions are welcome! Please read our Contributing Guide for details.

# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run type checking
mypy src/openf1_client
# Format code
black src tests
# Lint code
ruff check src tests

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


๐Ÿ™ Acknowledgements

  • ๐ŸŽ๏ธ OpenF1 for providing the excellent Formula 1 data API
  • โค๏ธ The Formula 1 community for their passion and support

If you find this project useful, consider supporting its development:

Buy Me A Coffee

Made with โค๏ธ for the F1 community

About

A production-grade Python SDK for the OpenF1 API, providing easy access to real-time and historical Formula 1 data.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

AltStyle ใซใ‚ˆใฃใฆๅค‰ๆ›ใ•ใ‚ŒใŸใƒšใƒผใ‚ธ (->ใ‚ชใƒชใ‚ธใƒŠใƒซ) /