Skip to main content

🏎️ pyopenf1

A production-grade, asynchronous Python wrapper for the OpenF1 API.

PyPI CI Python versions License


✨ Features

  • Fully Async — Built on httpx.AsyncClient with first-class async/await support.
  • Sync Wrapper — OpenF1Client for users who don't need async.
  • All 18 Endpoints — Complete coverage: telemetry, laps, drivers, sessions, weather, pit stops, stints, overtakes, race control, team radio, championship standings, results, starting grid, and more.
  • Pydantic V2 Models — Every response is validated and returned as a strict, typed model.
  • Auto-Retry — Exponential backoff on 429/5xx via tenacity.
  • Rate Limiting — Built-in client-side throttle (3 req/s free tier).
  • Response Caching — Optional in-memory TTL cache.
  • CLI Tool — Query the API from your terminal.
  • DataFrame Support — Optional pandas integration.
  • Production-Ready — Custom exceptions, structured logging, connection pooling.

📦 Installation

pip install pyopenf1

With pandas support:

pip install pyopenf1[pandas]

🚀 Quickstart

Async (recommended)

import asyncio
from pyopenf1 import AsyncOpenF1Client

async def main() -> None:
    async with AsyncOpenF1Client() as client:
        # Fetch telemetry
        car_data = await client.telemetry.get_car_data(driver_number=1, session_key=9159)
        for entry in car_data[:5]:
            print(f"Speed: {entry.speed} km/h | Gear: {entry.n_gear}")

        # Fetch drivers
        drivers = await client.drivers.get_drivers(session_key=9158)
        for d in drivers[:3]:
            print(f"#{d.driver_number} {d.full_name} - {d.team_name}")

asyncio.run(main())

Sync

from pyopenf1 import OpenF1Client

with OpenF1Client() as client:
    drivers = client.drivers.get_drivers(session_key=9158)
    for d in drivers:
        print(f"{d.name_acronym} - {d.team_name}")

CLI

pyopenf1 car-data --driver 1 --session 9159 --format table
pyopenf1 drivers --session 9158 --format json
pyopenf1 weather --meeting 1208 --format csv --output weather.csv

DataFrame

from pyopenf1.ext.pandas import to_dataframe

data = await client.telemetry.get_car_data(driver_number=1)
df = to_dataframe(data)
print(df.describe())

⚙️ Configuration

async with AsyncOpenF1Client(
    cache_ttl=300.0,        # Cache responses for 5 minutes
    max_retries=5,          # Retry up to 5 times
    max_per_second=6.0,     # Sponsor-tier rate limit
    max_per_minute=60.0,
) as client:
    ...

📡 Available Endpoints

Namespace Methods OpenF1 Endpoints
client.telemetry get_car_data(), get_location() /car_data, /location
client.sessions get_sessions(), get_meetings() /sessions, /meetings
client.drivers get_drivers() /drivers
client.timing get_laps(), get_intervals(), get_positions() /laps, /intervals, /position
client.race get_race_control(), get_pit_stops(), get_stints(), get_overtakes() /race_control, /pit, /stints, /overtakes
client.championship get_drivers_championship(), get_teams_championship() /championship_drivers, /championship_teams
client.results get_session_results(), get_starting_grid() /session_result, /starting_grid
client.weather get_weather() /weather
client.team_radio get_team_radio() /team_radio

🏗️ Architecture

pyopenf1/
├── __init__.py              # Public API surface
├── client.py                # AsyncOpenF1Client facade
├── sync_client.py           # OpenF1Client (sync wrapper)
├── cli.py                   # Click CLI
├── exceptions.py            # Custom exception hierarchy
├── core/
│   ├── http_client.py       # httpx wrapper + retry + logging
│   ├── rate_limiter.py      # Token-bucket rate limiter
│   └── cache.py             # In-memory TTL cache
├── models/                  # Pydantic V2 data models
│   ├── telemetry.py         # CarData, Location
│   ├── session.py           # Session, Meeting
│   ├── driver.py            # Driver
│   ├── timing.py            # Lap, Interval, Position
│   ├── race.py              # RaceControl, Pit, Stint, Overtake
│   ├── championship.py      # ChampionshipDriver, ChampionshipTeam
│   ├── results.py           # SessionResult, StartingGrid
│   ├── weather.py           # Weather
│   └── team_radio.py        # TeamRadio
├── endpoints/               # API endpoint classes
│   ├── telemetry_api.py
│   ├── session_api.py
│   ├── driver_api.py
│   ├── timing_api.py
│   ├── race_api.py
│   ├── championship_api.py
│   ├── results_api.py
│   ├── weather_api.py
│   └── team_radio_api.py
└── ext/
    └── pandas.py            # Optional DataFrame integration

🧪 Development

# Install dev dependencies
poetry install

# Lint & format
poetry run ruff check .
poetry run ruff format .

# Type check
poetry run mypy pyopenf1/

# Test
poetry run pytest -v

# Build docs
poetry run mkdocs serve

📄 License

Distributed under the MIT License. See LICENSE for details.

Metadata

Release files for pyopenf1 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyopenf1 0.1.3
File Size Uploaded
pyopenf1-0.1.3.tar.gz 21.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyopenf1 0.1.3
File Interpreter ABI Platform
pyopenf1-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 55.4 kB

Release files / pyopenf1-0.1.3.tar.gz

Download URL pyopenf1-0.1.3.tar.gz
Size 21.8 kB
Tags Source
SHA-256 checksum
How to use checksums
329e8f137738117a2783bb55fac90cc924b66d40d8c3dfbde3b41d369e4d56c8
BLAKE2b-256 checksum
How to use checksums
0393bbda23151bbea2eb0884b3c8ffe18f14451b9766b0e95e84d53fb08d038b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 27, 2026.

Transparency log

Release files / pyopenf1-0.1.3-py3-none-any.whl

Download URL pyopenf1-0.1.3-py3-none-any.whl
Size 33.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e5e51d957aba0dc80995f798ba833167951f3fe27dcec66eb84cc199f0167d09
BLAKE2b-256 checksum
How to use checksums
38deccbc6949d72a2746716ce5eeca092f0996fe215663804550b66d61724b44
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 27, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page