OpenF1 provides real-time and historical F1 data
OpenF1 API - Real-time and historical Formula 1 data
At a glance
- What is it?
- OpenF1 is an unofficial, free and open source Python API for real-time and historical Formula 1 data, including lap timings, telemetry and race control messages. It supports JSON and CSV, and its self-hosted stack includes an API and MongoDB.
- Who is it for?
- Adopt the hosted OpenF1 endpoint when you want lap times, throttle, brake, DRS and race control history without writing a scraper, and use the self-hosted stack when your analysis depends on data that must not leave your network or on ingestion timing you control. Do not build a production dependency on it without accepting the unofficial status the README states, and check the identifiers used by your query.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 35 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A query is a URL with a session key and a driver number
OpenF1 is a web API over Formula 1 timing data, and its interface is deliberately plain. The README's one worked example fetches a single lap:
curl "https://api.openf1.org/v1/laps?session_key=9161&driver_number=63&lap_number=8"Three query parameters and a flat JSON response. The interesting part is `session_key`. The example uses it to identify the session being queried alongside `driver_number` and `lap_number`.
The documentation lives at openf1.org, and the README says data can be explored through JSON or CSV. Both formats are offered for exploring the data.
What the feeds cover is listed in the features: live lap times, speeds and driver positioning; historical sessions for cross-race comparison; car telemetry including throttle, brake, DRS and gear; and driver details with team affiliations and performance metrics.
Three services, one MongoDB and one MQTT broker
Running it yourself means installing MongoDB and choosing which ingestion or API component to start. The README splits the work into three components, each with its own README under `src/openf1/services/`: `f1_scraping/` to fetch and ingest scraped data, `ingestor_livetiming/` to fetch and ingest live timing data, and `query_api/` to start and query the API.
The local setup is MongoDB Community Server v7 or v8, pip 23 or newer, Python 3.10 or newer, then the package itself:
git clone [email protected]:br-g/openf1.git
pip install -e openf1One environment variable connects the pieces:
export MONGO_CONNECTION_STRING="mongodb://localhost:27017"The docker-compose file shows the intended topology more clearly than the README does. Three application services share one image, built from a Dockerfile that starts at `python:3.10-slim` and installs with `pip install --no-cache-dir -e.`. Each service is the same code with a different `ROLE` value: `api`, `ingest-realtime`, `ingest-historical`. Only the api service publishes a port, `8000:8000`. The historical ingestor exists to backfill the current season, and the compose file comments that you should delete or disable it once you are up to date.
The compose configuration connects the live-timing ingestor to an MQTT service and configures an API service. The broker is `eclipse-mosquitto:2.0.22` with ports 1883 for standard MQTT and 8084 for WebSockets, and configuration mounted from `mqtt-config/`.
The dependency list explains the roles. `motor` 3.7.1 is the async MongoDB driver, `aiomqtt` 2.4.0 the async MQTT client, `fastf1_livetiming` from a git URL is the actual timing feed parser, The repository also includes `beautifulsoup4`, `lxml`, `fastapi`, `uvicorn`, `pydantic` 2.11.7 and `typer`. `slowapi` suggests rate limiting is in play, and `tqdm` progress bars.
Every dependency is pinned exactly, which cuts both ways
requirements.txt pins exact versions across the board: aiohttp 3.12.13, boto3 1.43.50, cachetools 5.5.2, requests 2.32.4, python-dateutil 2.9.0.post0, pytz 2025.2, loguru 0.7.3, tqdm 4.67.1.
Exact pins make dependency versions explicit in the installation. The trade-off is that version upgrades require editing the requirements file.
It is also why the repository's own infrastructure matters. There is a Dockerfile, a docker-entrypoint script, a `.github/` directory and a testing_requirements.txt wired in as an optional-dependencies group called `test`. pyproject.toml declares the project as `openf1` with `requires-python = ">=3.10"`, and it uses setuptools with dynamic dependencies read from requirements.txt, so the pinned file and the package metadata cannot drift apart.
One dependency is not from PyPI. `fastf1_livetiming` is installed straight from a git URL at github.com/br-g/fastf1-livetiming. That means a deployment reaches out to GitHub at install time for the component that parses live timing, and it means the pinned state of the ingestion path depends on the default branch of that repository rather than on an immutable reference in this file.
The compose file ships an MQTT broker with a guessable password
One detail in docker-compose.yml deserves to be flagged rather than glossed. The `ingest-realtime` service is configured with:
OPENF1_MQTT_USERNAME: openf1
OPENF1_MQTT_PASSWORD: openf1
OPENF1_MQTT_NO_TLS: trueThe compose file comments on this itself, noting it is obviously not remotely secure and should be changed if you expose the broker.
The exposure is easy to underestimate because of which ports are published. The mqtt service maps host ports `1883` and `8084` to the broker. `OPENF1_MQTT_NO_TLS: true` means no transport encryption on that path.
For a local development setup this is fine and convenient. For anything on a shared host or a VPS, the two steps that matter are changing the credentials and binding the broker to localhost rather than all interfaces, or removing the port mappings entirely and letting the services talk over the internal network, where the api and ingestor services already can.
The same file shows a single MongoDB image with a named volume `mongo-data:/data/db`, and no authentication configured for it. Inside the compose network that is normal. Published or not, it is worth checking before anything else in the stack is exposed.
Unofficial status and an old tag set the boundary on reliance
The README states the thing that matters most for an adoption decision: OpenF1 is an unofficial project and is not affiliated with Formula 1 companies, and all F1-related trademarks are owned by Formula One Licensing B.V.
There is also a funding angle worth knowing, since long-term availability is a real concern for a free service. The README asks for support through a Buy Me a Coffee page and a GitHub Sponsors link.
Maintenance signals are mixed in a specific way. The repository is not archived, and the last push was on 2026-09-18, so code is still landing. But the tag list has only two entries, v0.1.0 and v1.0.0, both on 2024-10-05, while pyproject.toml declares the version as 1.9.14. These releases do not correspond to the package version currently declared in pyproject.toml.
Full API documentation is available at openf1.org.
Where OpenF1 sits against the other F1 data routes
OpenF1 includes a live-timing dependency from the `br-g/fastf1-livetiming` repository.
OpenF1 provides a hosted HTTP API and a self-hostable stack.
Choose between the hosted endpoint and the self-hosted stack according to where you want the data processed.
OpenF1 is free and open source, provides an HTTP API, and can be hosted yourself. It is unofficial and not affiliated with Formula 1 companies.
Editorial conclusion
Adopt the hosted OpenF1 endpoint when you want lap times, throttle, brake, DRS and race control history without writing a scraper, and use the self-hosted stack when your analysis depends on data that must not leave your network or on ingestion timing you control. Do not build a production dependency on it without accepting the unofficial status the README states, and check the identifiers used by your query. Verify first that the session_key you want exists, that the collection you need is populated for that session, and that the pinned dependency set still installs on your Python, since requirements.txt lists exact versions.
Frequently asked questions
How do I query lap times from the OpenF1 API?
Use the laps endpoint with a session key and driver number. The README example is `curl "https://api.openf1.org/v1/laps?session_key=9161&driver_number=63&lap_number=8"`, which returns a single lap as JSON.
Does OpenF1 have rate limits or an API key?
The README does not describe an API key or rate limit for the hosted endpoint at api.openf1.org. The dependency list includes slowapi, which suggests rate limiting exists in the code, but the policy is not documented in the README. Full documentation is at openf1.org.
What does OpenF1 need to run locally?
MongoDB Community Server v7 or v8, pip 23 or newer, Python 3.10 or newer, and the openf1 package installed with `pip install -e openf1`. You then set MONGO_CONNECTION_STRING to your local instance.
Can I run OpenF1 with docker compose?
Yes. The repository ships a docker-compose.yml with api, ingest-realtime, ingest-historical, mongo and mqtt services, plus a Dockerfile based on python:3.10-slim. The api service publishes port 8000, and the compose comments suggest disabling ingest-historical once the current season is backfilled.
Is OpenF1 affiliated with Formula 1?
No. The README states OpenF1 is an unofficial project not affiliated with Formula 1 companies, and that all F1-related trademarks are owned by Formula One Licensing B.V.
What telemetry does OpenF1 provide?
The README lists car data including throttle, brake, DRS and gear information, plus live lap times, speeds and driver positioning, and driver details with team affiliations and performance metrics. Data can be explored in JSON or CSV.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/br-g-openf1)Was this useful?