Version: 3.1
Last Updated: August 11, 2025
Repository: https://github.com/JoshCBruce/fantasy-data
latest/
βββ driver_data/
β βββ {DRIVER_ABBREVIATION}.json (21 files)
β βββ ...
βββ constructor_data/
β βββ {CONSTRUCTOR_ABBREVIATION}.json (10 files)
β βββ ...
βββ summary_data/
βββ weekend_summary.json
βββ constructor_weekend_summary.json
βββ extraction_summary.json
βββ team_summary.json
βββ percentage_picked_ranking.json
βββ constructor_percentage_picked_ranking.json
File Path: latest/driver_data/{ABBREVIATION}.json
Example: ALO.json, NOR.json, VER.json
{
"driverId": "string",
"name": "string",
"displayName": "string",
"abbreviation": "string",
"team": "string",
"position": number,
"value": "string",
"seasonTotalPoints": number,
"percentagePicked": number,
"isInactive": boolean,
"teamSwap": boolean,
"teams": ["string"],
"races": [RaceObject],
"extractedAt": "ISO8601 timestamp"
}
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
driverId |
String | Yes | Unique driver identifier from F1 Fantasy | "landonorrisdriver" |
name |
String | Yes | Driverβs name (lowercase, no spaces) | "landonorris" |
displayName |
String | Yes | Driverβs display name | "landonorris" |
abbreviation |
String | Yes | 3-letter driver code | "NOR" |
team |
String | Yes | Current team name | "McLaren" |
position |
Number | Yes | Championship position | 1 |
value |
String | Yes | Fantasy value with currency | "31.4M" |
seasonTotalPoints |
Number | Yes | Total fantasy points this season | 500 |
percentagePicked |
Number | Yes | Percentage of users who picked driver | 23 |
isInactive |
Boolean | Yes | Whether driver is currently inactive | false |
teamSwap |
Boolean | No | Whether driver switched teams mid-season | false |
teams |
Array | No | List of teams if team swap occurred | ["Red Bull Racing", "Racing Bulls"] |
races |
Array | Yes | Array of race data objects | See Race Object Structure |
extractedAt |
String | Yes | ISO8601 timestamp of data extraction | "2025-08-10T20:16:57.036Z" |
{
"round": "string",
"raceName": "string",
"totalPoints": number,
"race": {
"dotd": number,
"position": number,
"qualifyingPosition": number,
"fastestLap": number,
"overtakeBonus": number,
"positionsGained": number,
"positionsLost": number,
"disqualificationPenalty": number
},
"qualifying": {
"position": number,
"disqualificationPenalty": number
},
"sprint": {
"position": number,
"qualifyingPosition": number,
"fastestLap": number,
"overtakeBonus": number,
"positionsGained": number,
"positionsLost": number,
"disqualificationPenalty": number
}
}
| Field | Type | Description | Points |
|---|---|---|---|
round |
String | Race round number | "1", "2", etc. |
raceName |
String | Official race name | "Australia", "Monaco" |
totalPoints |
Number | Total fantasy points for this race | Can be negative |
race.dotd |
Number | Driver of the Day bonus | 0 or 10 |
race.position |
Number | Race finishing position points | Variable based on position |
race.qualifyingPosition |
Number | Qualifying position points | 0 (handled in qualifying object) |
race.fastestLap |
Number | Fastest lap bonus | 0 or 10 |
race.overtakeBonus |
Number | Overtaking bonus points | Variable |
race.positionsGained |
Number | Positions gained during race | Positive number |
race.positionsLost |
Number | Positions lost during race | Negative number or 0 |
race.disqualificationPenalty |
Number | Disqualification penalty | 0 or negative |
qualifying.position |
Number | Qualifying finishing position points | Variable |
qualifying.disqualificationPenalty |
Number | Qualifying penalties | 0 or negative |
sprint.* |
Various | Sprint race data (same structure as race) | Only present for sprint weekends |
For drivers with teamSwap: true:
{
"teamSwap": true,
"teams": ["Previous Team", "Current Team"],
"teamSwapDetails": [
{
"team": "Previous Team",
"position": number,
"value": "string",
"points": number
},
{
"team": "Current Team",
"position": number,
"value": "string",
"points": number
}
],
"versions": number,
"races": [
{
"round": "string",
"raceName": "string",
"totalPoints": number,
"team": "string",
"source": "single|merged",
"race": {},
"qualifying": {},
"sprint": {}
}
]
}
File Path: latest/constructor_data/{ABBREVIATION}.json
Example: MCL.json, FER.json, RBR.json
{
"constructorId": "string",
"name": "string",
"displayName": "string",
"abbreviation": "string",
"position": number,
"value": "string",
"seasonTotalPoints": number,
"percentagePicked": number,
"races": [ConstructorRaceObject],
"extractedAt": "ISO8601 timestamp"
}
{
"round": "string",
"raceName": "string",
"totalPoints": number,
"race": {
"position": number,
"qualifyingPosition": number,
"fastestLap": number,
"pitStopBonus": number,
"fastestPitStop": number,
"worldRecordBonus": number,
"disqualificationPenalty": number,
"positionsGained": number,
"positionsLost": number,
"overtakes": number
},
"qualifying": {
"q2Bonus": number,
"q3Bonus": number,
"disqualificationPenalty": number
},
"sprint": {
"position": number,
"qualifyingPosition": number,
"fastestLap": number,
"disqualificationPenalty": number,
"positionsGained": number,
"positionsLost": number,
"overtakes": number
}
}
weekend_summary.json)Race-by-race points for all drivers:
{
"1": {
"raceName": "Australia",
"drivers": {
"NOR": 59,
"PIA": 10,
"VER": 29,
"RUS": 25,
"HAM": 4
}
},
"2": {
"raceName": "China",
"drivers": {
"NOR": 41,
"PIA": 45
}
}
}
constructor_weekend_summary.json)Race-by-race points for all constructors:
{
"1": {
"raceName": "Australia",
"constructors": {
"MCL": 71,
"FER": 36,
"MER": 67,
"RBR": 19
}
}
}
extraction_summary.json)Overall statistics and metadata:
{
"extractedAt": "2025-08-10T20:20:31.427Z",
"totalDrivers": 21,
"totalConstructors": 10,
"teamSwapDrivers": 2,
"totalRaces": 309,
"averagePercentagePicked": 23,
"averageConstructorPercentagePicked": 20,
"drivers": [
{
"abbreviation": "NOR",
"name": "landonorris",
"team": "McLaren",
"position": 1,
"value": "31.4M",
"seasonTotal": 500,
"percentagePicked": 23,
"racesFound": 15,
"teamSwap": false,
"teams": []
}
],
"constructors": [
{
"abbreviation": "MCL",
"name": "mclaren",
"position": 1,
"value": "34.2M",
"seasonTotal": 1215,
"percentagePicked": 40,
"racesFound": 15
}
]
}
team_summary.json)Grouped data by team:
{
"McLaren": {
"drivers": [
{
"abbreviation": "NOR",
"name": "landonorris",
"points": 500,
"percentagePicked": 23,
"value": "31.4M",
"position": 1
},
{
"abbreviation": "PIA",
"name": "oscarpiastri",
"points": 489,
"percentagePicked": 40,
"value": "26.4M",
"position": 2
}
],
"totalPoints": 989,
"averagePercentagePicked": 32
}
}
percentage_picked_ranking.json)Drivers ranked by popularity:
{
"HAD": 54,
"BEA": 44,
"PIA": 40,
"SAI": 39,
"ALO": 37,
"HUL": 34,
"ALB": 29,
"BOR": 25,
"OCO": 24,
"NOR": 23
}
constructor_percentage_picked_ranking.json)Constructors ranked by popularity:
{
"MCL": 40,
"RB": 26,
"WIL": 25,
"FER": 21,
"HAS": 20,
"MER": 17,
"AMR": 16,
"SAU": 15,
"RBR": 10,
"ALP": 10
}
Base URL: https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest
Individual Driver Data:
https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest/driver_data/{ABBREVIATION}.json
Constructor Data:
https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest/constructor_data/{ABBREVIATION}.json
Summary Data:
https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest/summary_data/weekend_summary.json
https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest/summary_data/extraction_summary.json
https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest/summary_data/team_summary.json
https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest/summary_data/percentage_picked_ranking.json
const ACTIVE_DRIVERS = [
'NOR', 'PIA', 'VER', 'RUS', 'HAM', 'LEC', 'HUL', 'ANT',
'STR', 'OCO', 'ALB', 'BEA', 'TSU', 'ALO', 'HAD', 'BOR',
'SAI', 'LAW', 'GAS', 'COL', 'DOO'
];
const CONSTRUCTORS = [
'MCL', 'FER', 'MER', 'RBR', 'HAS', 'SAU',
'AMR', 'RB', 'WIL', 'ALP'
];
| Round | Race Name | Type | Sprint Weekend |
|---|---|---|---|
| 1 | Australia | Regular | No |
| 2 | China | Sprint | Yes |
| 3 | Japan | Regular | No |
| 4 | Bahrain | Regular | No |
| 5 | Saudi Arabia | Regular | No |
| 6 | United States | Sprint | Yes |
| 7 | Italy | Regular | No |
| 8 | Monaco | Regular | No |
| 9 | Spain | Regular | No |
| 10 | Canada | Regular | No |
| 11 | Austria | Sprint | Yes |
| 12 | United Kingdom | Regular | No |
| 13 | Belgium | Sprint | Yes |
| 14 | Hungary | Regular | No |
| 15 | Netherlands | Regular | No |
Sprint weekends include additional data:
{
"sprint": {
"position": number,
"qualifyingPosition": number,
"fastestLap": number,
"overtakeBonus": number,
"positionsGained": number,
"positionsLost": number,
"disqualificationPenalty": number
}
}
| Category | Points | Conditions |
|---|---|---|
| Race Position | Variable | 1st: 25pts, 2nd: 20pts, etc. |
| Qualifying Position | Variable | 1st: 10pts, 2nd: 9pts, etc. |
| Driver of the Day | 10 | Awarded by fan vote |
| Fastest Lap | 10 | Must finish in top 10 |
| Overtake Bonus | +3 per position | Net positions gained |
| Position Lost | -2 per position | Net positions lost |
| Sprint Position | Variable | Reduced points scale |
| Sprint Qualifying | Variable | Reduced points scale |
| Disqualification | -20 | Full race/qualifying DSQ |
| Category | Points | Conditions |
|---|---|---|
| Race Position | Variable | Combined driver positions |
| Qualifying | Variable | Combined qualifying positions |
| Fastest Lap | 10 | Team achieves fastest lap |
| Fastest Pit Stop | 10 | Team has fastest pit stop |
| Pit Stop Bonus | 5 | Exceptional pit stop performance |
| Q2/Q3 Bonus | 5/10 | Both cars reach Q2/Q3 |
| World Record | 15 | Breaking track/sector records |
| Overtakes | +1 per overtake | Successful overtaking moves |
// Always check for data availability
if (!driver.races || driver.races.length === 0) {
return 0; // or appropriate default
}
// Handle missing sprint data
const sprintData = race.sprint || null;
if (sprintData) {
// Process sprint data
}
// Handle team swap drivers
if (driver.teamSwap) {
// Use merged data with team context
const raceWithTeam = race.team || driver.team;
}
// Validate required fields
const requiredFields = ['abbreviation', 'seasonTotalPoints', 'races'];
const isValid = requiredFields.every(field =>
driver.hasOwnProperty(field) && driver[field] !== undefined
);
// Validate race data
race.totalPoints = race.totalPoints || 0;
race.round = String(race.round); // Ensure string format
// Average points per race
const avgPoints = driver.seasonTotalPoints / driver.races.length;
// Recent form (last 3 races)
const recentRaces = driver.races.slice(-3);
const recentForm = recentRaces.reduce((sum, race) =>
sum + race.totalPoints, 0) / recentRaces.length;
// Value efficiency
const value = parseFloat(driver.value.replace('M', ''));
const efficiency = driver.seasonTotalPoints / value;
// Consistency (standard deviation)
const mean = avgPoints;
const variance = driver.races.reduce((sum, race) =>
sum + Math.pow(race.totalPoints - mean, 2), 0) / driver.races.length;
const consistency = Math.sqrt(variance);
extractedAt timestamp indicates last update timelatest/ folder always contains most recent datateam field shows current teamteams array shows all teams if team swap occurredteam field for contexttotalPoints: 0isInactive: true// Base URL for all data
const BASE_URL = 'https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest';
// Fetch individual driver
async function fetchDriver(abbreviation) {
const response = await fetch(`${BASE_URL}/driver_data/${abbreviation}.json`);
return response.json();
}
// Fetch all summary data
async function fetchSummaryData() {
const response = await fetch(`${BASE_URL}/summary_data/extraction_summary.json`);
return response.json();
}
// Fetch weekend summary
async function fetchWeekendSummary() {
const response = await fetch(`${BASE_URL}/summary_data/weekend_summary.json`);
return response.json();
}
import requests
import json
BASE_URL = "https://raw.githubusercontent.com/JoshCBruce/fantasy-data/refs/heads/main/latest"
def fetch_driver_data(abbreviation):
url = f"{BASE_URL}/driver_data/{abbreviation}.json"
response = requests.get(url)
return response.json()
def fetch_all_drivers():
drivers = ['NOR', 'PIA', 'VER', 'RUS', 'HAM', 'LEC', 'HUL']
return {abbrev: fetch_driver_data(abbrev) for abbrev in drivers}
# Calculate team totals
def calculate_team_performance():
summary = requests.get(f"{BASE_URL}/summary_data/team_summary.json").json()
return {team: data['totalPoints'] for team, data in summary.items()}
{ABBREVIATION}.jsonLast Updated: August 11, 2025
Documentation Version: 3.1
Data Repository: https://github.com/JoshCBruce/fantasy-data