Issue Nº 19 — Sep 4, 2026
OpenF1 returns the same 404 for an empty query, a bad session key, and a typo in the URL
Issue nineteen covers OpenF1, an open-source Formula 1 data API with car telemetry, lap times, and session data, all free with no key or sign-up. This session queried it live. It found a single 404 shape that covers three unrelated failures, comparison-operator filters and CSV output that both work anonymously, and a documented rate limit with no headers to show it in action.
What it covers
OpenF1 publishes Formula 1 data across 18 endpoints: sessions, meetings, drivers, car telemetry, laps, pit stops, team radio, race control, and standings. The free tier needs no key, no sign-up, and no credit card.
A live GET to /v1/sessions?year=2026 this session returned a 200 with 48,130 bytes of JSON and an access-control-allow-origin: * header, matching the cors: yes on file. GET /v1/meetings?year=2026 returned 27 meetings; the first two were both named "Pre-Season Testing".
GET /v1/drivers?session_key=9158 returned a 200 with 7,599 bytes, listing drivers such as Oscar Piastri of McLaren. All three hero endpoints on file work exactly as documented, keyless.
One 404 shape covers three different failures
GET /v1/sessions?year=2022 returned 404, not an empty array, with the body {"detail":"No results found."}. The year is valid; OpenF1's public data just starts at 2023.
The identical status and identical body came back for GET /v1/laps?session_key=9999999, a real endpoint given a session key that does not exist. It came back a third time for GET /v1/bogus_endpoint, a path that was never a real endpoint at all.
A client reading that response cannot tell a filter that matched nothing from a session key that was never valid, or from a mistyped URL. All three land on the same status code and the same one-line message.
Comparison filters and CSV both work without a key
GET /v1/car_data?session_key=11465&driver_number=1&speed>=300&csv=true returned a 200 with content-type: text/csv; charset=utf-8 and 38,134 bytes. Every row in the body carried a speed value at or above 300, so the >= operator filters the query, not just plain equality.
OpenF1's own FAQ describes the same switch: "JSON (default) and CSV. Add 'csv=true' to any request for spreadsheet-compatible output." This session's request confirms it works with no key attached.
A documented rate limit, with no headers to watch it
OpenF1's homepage lists two tiers in its own structured pricing data: a free "Historical data" tier at 0 EUR covering "all 18 endpoints and historical sessions since 2023", and a 9.90 EUR "Historical and Live data" tier adding live access during sessions.
The homepage FAQ states the free tier allows "3 req/s and 30 req/min", matching the rateLimit on file, and that live data lags real events "about 3 seconds", calling that "faster than most TV broadcasts".
Eight rapid GET /v1/sessions calls in this session all returned 200. None carried an x-ratelimit-* header or a retry-after header. The limit may well be real, but nothing in a response lets a caller see it approach before a request gets refused.
OpenF1, by the numbers
Free/Community tier: up to 3 requests/second and 30 requests/minute; Sponsor tier (€9.90/month): up to 6 requests/second and 60 requests/minute
- GET/sessions?year={year}
- GET/drivers?session_key={session_key}
- GET/laps?session_key={session_key}&driver_number={driver_number}