Josh Bruce Online

F1 Fantasy 2026 — JSON Data Format Specification

This document describes the two standardised JSON formats produced by the scraper and consumed by the web dashboard. Both file types share the same metadata block and are scraped from the official F1 Fantasy platform.

File Locations & Naming

Directory Naming Convention Contents
prices/ prices-PRE-ROUND-{N}.json All drivers and constructors on the market with prices and ownership
team-price/ team-PRE-ROUND-{N}.json Current GPT RS team composition, prices, and captain selection

{N} is the upcoming round number (1-indexed). Files are generated by a scraper that runs on Tuesdays, plus ad-hoc runs before each round.


Shared: metadata Object

Both file types begin with an identical metadata block.

{
  "metadata": {
    "scraped_at": "2026-02-26T23:32:44Z",
    "round_context": {
      "last_completed_round": null,
      "last_completed_race": null,
      "upcoming_round": 1,
      "upcoming_race": "Australian GP",
      "is_race_week": false,
      "file_type": "pre-round"
    }
  }
}
Field Type Description
scraped_at string (ISO 8601, UTC) Timestamp when the data was scraped. Always UTC with Z suffix.
round_context.last_completed_round number \| null Round number of the most recently completed race. null before the season starts.
round_context.last_completed_race string \| null Human-readable name of the last completed race (e.g. "Australian GP"). null before the season starts.
round_context.upcoming_round number Round number of the next upcoming race (1–24).
round_context.upcoming_race string Human-readable name of the next upcoming race.
round_context.is_race_week boolean true if the scrape occurred during the race weekend (Friday–Sunday), false otherwise.
round_context.file_type string Always "pre-round" for these snapshots. Reserved for future types like "post-round" or "mid-weekend".

Prices File (prices/prices-PRE-ROUND-{N}.json)

Contains the full market — every driver and constructor available in the game.

Top-Level Structure

{
  "metadata": { ... },
  "drivers": [ ... ],
  "constructors": [ ... ]
}

drivers Array

An array of all 21 drivers on the grid, sorted by price_millions descending.

{
  "name": "Max Verstappen",
  "team": "Red Bull Racing",
  "price_millions": 27.7,
  "ownership_pct": 28.0
}
Field Type Description
name string Driver’s full display name as shown on the F1 Fantasy platform.
team string Constructor/team name the driver races for. Matches the name field in the constructors array.
price_millions number Current price in millions (e.g. 27.7 = $27.7M). One decimal place.
ownership_pct number Global ownership percentage across all F1 Fantasy players. One decimal place.

constructors Array

An array of all 11 constructors, sorted by price_millions descending.

{
  "name": "Mercedes",
  "price_millions": 29.3,
  "ownership_pct": 23.0
}
Field Type Description
name string Constructor’s display name. Used as the join key to link drivers to their team.
price_millions number Current price in millions. One decimal place.
ownership_pct number Global ownership percentage. One decimal place.

Notes


Team File (team-price/team-PRE-ROUND-{N}.json)

Contains the current composition of the GPT RS fantasy team.

Top-Level Structure

{
  "metadata": { ... },
  "team": {
    "drivers": [ ... ],
    "constructors": [ ... ],
    "total_team_value_millions": 99.9
  }
}
Field Type Description
team.total_team_value_millions number Sum of all driver and constructor prices. The budget cap is $100.0M, so 100.0 - total_team_value_millions = remaining budget.

team.drivers Array

Exactly 5 driver objects, representing the selected fantasy squad.

{
  "name": "George Russell",
  "team": "Mercedes",
  "price_millions": 27.4,
  "price_change_millions": 0.0,
  "is_captain": true
}
Field Type Description
name string Driver’s full display name. Matches entries in the prices file.
team string Constructor name.
price_millions number Current price in millions.
price_change_millions number Cumulative price change since the driver was acquired. 0.0 at start of season or if just purchased. Can be negative.
is_captain boolean true if this driver has the DRS Boost (2x points multiplier). Exactly one driver will have is_captain: true.

team.constructors Array

Exactly 2 constructor objects.

{
  "name": "Ferrari",
  "price_millions": 23.3,
  "price_change_millions": 0.0
}
Field Type Description
name string Constructor display name. Matches entries in the prices file.
price_millions number Current price in millions.
price_change_millions number Cumulative price change since acquisition.

Derived Values

These are not in the JSON but are straightforward to compute:

Value Formula
Budget remaining 100.0 - team.total_team_value_millions
Captain driver team.drivers.find(d => d.is_captain)
Team value change sum(all price_change_millions) across drivers + constructors

Linking the Two Files

The name field is the join key between files. To enrich the team view with market data (e.g. ownership percentage), match team.drivers[].name against drivers[].name in the prices file, and likewise for constructors.

team.drivers[i].name === prices.drivers[j].name
team.constructors[i].name === prices.constructors[j].name

Both files from the same scrape run share the same scraped_at timestamp and round_context.


Update Cadence


Example: Rendering the Dashboard

A typical dashboard view would:

  1. Load the latest file from each directory (sort by filename or scraped_at).
  2. Display the 5 drivers + 2 constructors from the team file, highlighting the captain with a badge/icon.
  3. Show price_millions and price_change_millions for each pick (green/red for positive/negative change).
  4. Show total_team_value_millions and the derived budget remaining.
  5. Optionally join against the prices file to show ownership_pct for each team member.
  6. List the full market from the prices file for a “transfer market” view, sortable by price and ownership.