TypeScript SDK

f1.js

Formula 1 data for Node.js developers

Full race results, standings, and live telemetry — 1950 to present.
Zero config. Zero dependencies. Typed, cached, rate-limited.

$npm install @paraspatankar/f1js
75+
years of data
0
runtime deps
9
API methods
3.7Hz
telemetry rate

/ 01 — Quick start

Three lines
to race data

import { f1 } from '@paraspatankar/f1js'

// Get every race result from the 2024 Bahrain GP
const results = await f1.races.getResults(2024, 1)
// → Race[], fully typed. Cached forever (historical data).

// Who won?
const winner = results.find(r => r.position === 1)
console.log(winner?.driverId)  // → "verstappen"

// Full season schedule
const races = await f1.races.getSeason(2023)
console.log(races.length)       // → 22
import { f1 } from '@paraspatankar/f1js'

// Verstappen's full telemetry trace — Bahrain 2024
// session_key resolved automatically from season + round
const carData = await f1.telemetry.getCarData(2024, 1, 'VER')
// → 34,819 CarData samples. Cached on first fetch.

// Top speed at Bahrain
const topSpeed = Math.max(...carData.map(d => d.speed))
console.log(topSpeed)  // → 342 (km/h)

// Tyre strategy
const stints = await f1.telemetry.getStints(2024, 1, 'HAM')
stints.forEach(s =>
  console.log(`${s.compound} — laps ${s.lapStart}–${s.lapEnd}`)
import { f1 } from '@paraspatankar/f1js'

// Parse a lap time string into milliseconds
f1.utils.parseLapTime('1:23.456')         // → 83456

// Format milliseconds back to M:SS.mmm
f1.utils.formatLapTime(83456)             // → '1:23.456'

// Calculate the gap between two laps
f1.utils.lapGap('1:23.456', '1:23.891')  // → '+0.435'

/ 02 — Architecture

Everything
handled for you

Smart caching

Historical data cached forever to disk. Current season cached 5 min. Never fetches the same historical data twice — even across restarts.

Rate limited

Built-in sliding-window rate limiter keeps calls under OpenF1's 3 req/s ceiling. You call the method; the library queues everything safely.

Session resolver

Pass season + round. The library maps it to OpenF1's session_key automatically. You never deal with two APIs' ID systems.

Auto-pagination

Jolpica caps responses at 100. fetchAll() loops transparently so you get the complete dataset in one call, every time.

Full TypeScript

Every method, parameter, and return type is strictly typed. Ships .d.ts declarations. Works in CJS and ESM projects.

Zero dependencies

Cache, rate limiter, HTTP client — all Node.js builtins. No supply chain risk. npm install and you're done.

/ 03 — API Reference

9 methods.
All of F1.

NamespaceMethodReturnsSourceCoverage
racesgetSeason(season)Race[] — full calendarJolpica1950–present
racesgetResults(season, round)RaceResult[] — full gridJolpica1950–present
driversgetSeason(season)Driver[] — all driversJolpica1950–present
driversgetDriver(driverId)Driver — single recordJolpica1950–present
standingsgetDriverStandings(season)DriverStanding[]Jolpica1950–present
standingsgetConstructorStandings(season)ConstructorStanding[]Jolpica1950–present
telemetrygetCarData(season, round, driver)CarData[] — speed/throttle/brake/RPM/gear/DRSOpenF12023–present
telemetrygetStints(season, round, driver?)Stint[] — compound, lap rangeOpenF12023–present
telemetrygetWeather(season, round)WeatherSample[] — temp/humidity/windOpenF12023–present

/ 04 — Limitations

Honest about
the boundaries

Telemetry is 2023+ only

OpenF1 only covers 2023 onwards. Race results and standings go back to 1950 via Jolpica.

Node.js only (v1)

The filesystem cache uses Node's fs/promises. Browser support is planned for v2 with an isomorphic cache adapter.

No live race data

This version targets historical and post-session data. A f1.live.* namespace with event-driven polling is on the v2 roadmap.

First telemetry fetch is slow

~35,000 samples per driver race. Rate limiter queues everything safely. Second run: instant (filesystem cache hit).