This guide explains how to access the OpenF1 API as an authenticated user. Authentication removes rate limits, provides access to both historical and real-time data, and enables live data streaming through MQTT or WebSocket.
The following sections will walk you through these features and how to make use of them.
Don’t have an account yet? Apply by completing this form.
To access real-time data, you'll need to obtain an OAuth2 access token. This token proves your identity to the API.
You can get an access token by sending a POST request to the
https://api.openf1.org/token
endpoint with your
username and password.
curl -X POST "https://api.openf1.org/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=YOUR_USERNAME&password=YOUR_PASSWORD"
import requests
token_url = "https://api.openf1.org/token"
payload = {
"username": "YOUR_USERNAME",
"password": "YOUR_PASSWORD"
}
headers = {
"Content-Type": "application/x-www-form-urlencoded"
}
response = requests.post(token_url, data=payload, headers=headers)
if response.status_code == 200:
token_data = response.json()
print(f"Access token: {token_data.get('access_token')}")
print(f"Expires in: {token_data.get('expires_in')} seconds")
else:
print(f"Error obtaining token: {response.status_code} - {response.text}")
async function getAccessToken() {
const tokenUrl = "https://api.openf1.org/token";
const params = new URLSearchParams();
params.append("username", "YOUR_USERNAME");
params.append("password", "YOUR_PASSWORD");
try {
const response = await fetch(tokenUrl, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: params,
});
if (response.ok) {
const tokenData = await response.json();
console.log("Access token:", tokenData.access_token);
console.log("Expires in:", tokenData.expires_in, "seconds");
return tokenData.access_token;
} else {
console.error("Error obtaining token:", response.status, await response.text());
return null;
}
} catch (error) {
console.error("Network error or other issue:", error);
return null;
}
}
// Example usage:
// getAccessToken().then(token => {
// if (token) {
// // Use the token
// }
// });
A successful request will return a JSON object containing your access token and its expiry time:
{
"expires_in": "3600",
"access_token": "YOUR_ACCESS_TOKEN",
"token_type": "bearer"
}
Important: Tokens expire after 1 hour. Your application should be designed to handle token expiry gracefully by requesting a new one.
To access real-time data, you must include your access token in
the
Authorization
header as a Bearer token.
# Replace YOUR_ACCESS_TOKEN with the token you obtained
curl -X 'GET' \
'https://api.openf1.org/v1/sessions?year=2024' \
-H 'accept: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN'
import requests
# Assume 'access_token' is a variable holding your obtained token
access_token = "YOUR_ACCESS_TOKEN"
api_url = "https://api.openf1.org/v1/sessions?year=2024" # Example
headers = {
"accept": "application/json",
"Authorization": f"Bearer {access_token}"
}
response = requests.get(api_url, headers=headers)
if response.status_code == 200:
data = response.json()
print(data)
else:
print(f"Error fetching data: {response.status_code} - {response.text}")
async function fetchDataWithToken(accessToken) {
const apiUrl = "https://api.openf1.org/v1/sessions?year=2024"; // Example
try {
const response = await fetch(apiUrl, {
method: "GET",
headers: {
"accept": "application/json",
"Authorization": `Bearer ${accessToken}`,
},
});
if (response.ok) {
const data = await response.json();
console.log(data);
return data;
} else {
console.error("Error fetching data:", response.status, await response.text());
return null;
}
} catch (error) {
console.error("Network error or other issue:", error);
return null;
}
}
// Example usage:
// getAccessToken().then(token => {
// if (token) {
// fetchDataWithToken(token);
// }
// });
For the most efficient access to real-time data, we offer MQTT and Websocket connections. These methods push data to your application as soon as it's available, eliminating the need for constant polling of the REST API.
This is the recommended method for accessing live data.
mqtt.openf1.org
8883
wss://mqtt.openf1.org:8084/mqtt
Both MQTT and Websocket connections use the OAuth2 access token as the password for authentication. The username can typically be any non-empty string, or your registered email if preferred/required by your client library for token-based auth.
Topics for MQTT/Websockets directly correspond to the REST API endpoint paths. For example:
v1/sessions
v1/laps
v1/location
You can subscribe to specific topics or use wildcards (e.g.,
#
to subscribe to all topics if your client library
supports it).
Messages received via MQTT/Websockets are JSON objects, mirroring the data from the corresponding REST API endpoint. However, they include two additional fields:
_id
(integer): A unique, ever-increasing identifier
assigned to each message. It can be used to sort messages
chronologically.
_key
(string): An identifier for the document.
Messages of the same topic with the same _key
represent
different versions or updates to the same underlying data object. This is
particularly useful for topics like v1/laps
where
lap information (like sector duration) is updated in real-time.
v1/location
){
"meeting_key": 1257,
"session_key": 10007,
"driver_number": 31,
"date": "2025-04-11T11:21:16.603025+00:00",
"x": 0,
"y": 0,
"z": 0,
"_key": "1744370476603_31",
"_id": 1747235800206
}
import paho.mqtt.client as mqtt
import ssl
# Assume 'access_token' is a variable holding your obtained token
access_token = "YOUR_ACCESS_TOKEN"
mqtt_broker = "mqtt.openf1.org"
mqtt_port = 8883
# Optional: Provide a username. Can be an email or any non-empty string.
mqtt_username = "your_username_or_email@example.com"
def on_connect(client, userdata, flags, rc, properties=None):
if rc == 0:
print("Connected to OpenF1 MQTT broker")
client.subscribe("v1/location")
client.subscribe("v1/laps")
# client.subscribe("#") # Subscribe to all topics
else:
print(f"Failed to connect, return code {rc}")
def on_message(client, userdata, msg):
print(f"Received message on topic '{msg.topic}': {msg.payload.decode()}")
# Example: data = json.loads(msg.payload.decode())
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.username_pw_set(username=mqtt_username, password=access_token)
client.tls_set(cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLS_CLIENT)
client.on_connect = on_connect
client.on_message = on_message
try:
client.connect(mqtt_broker, mqtt_port, 60)
client.loop_forever() # Starts a blocking network loop
except Exception as e:
print(f"Connection error: {e}")
This example uses the popular mqtt
library (MQTT.js),
which works in both Node.js and browsers.
// In Node.js: npm install mqtt
// In Browser: <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
// Assume 'accessToken' is a variable holding your obtained token
const accessToken = "YOUR_ACCESS_TOKEN";
const websocketUrl = "wss://mqtt.openf1.org:8084/mqtt";
const options = {
username: "your_username_or_email@example.com", // Optional, can be any string
password: accessToken // Access token is used as the password
};
const client = mqtt.connect(websocketUrl, options);
client.on('connect', function () {
console.log('Connected to OpenF1 via Websockets');
client.subscribe('v1/location', function (err) {
if (!err) {
console.log('Subscribed to v1/location');
} else {
console.error('Subscription error for v1/location:', err);
}
});
client.subscribe('v1/laps', function (err) {
if (!err) {
console.log('Subscribed to v1/laps');
} else {
console.error('Subscription error for v1/laps:', err);
}
});
// client.subscribe('#'); // Subscribe to all topics
});
client.on('message', function (topic, message) {
console.log(`Received on ${topic}: ${message.toString()}`);
// const data = JSON.parse(message.toString());
// Process data
});
client.on('error', function (error) {
console.error('MQTT Connection Error:', error);
});
client.on('close', function () {
console.log('MQTT Connection closed');
});
client.on('offline', function() {
console.log('MQTT Client is offline');
});
client.on('reconnect', function() {
console.log('MQTT Client is attempting to reconnect');
});
Understanding when to use each method will help you build more efficient and responsive applications.
Please prioritize MQTT or Websockets for any application needing live F1 data. They are significantly more efficient and provide data as soon as it's available.
The most important security consideration is the handling of your API credentials (username and password used to obtain the OAuth2 token) and the access token itself.
The process of obtaining the OAuth2 access token (exchanging your username and password) MUST be implemented in your backend application code. Never embed your direct username and password into client-side applications (like JavaScript running in a user's browser or in a desktop application that can be easily decompiled).
If your backend needs to make authenticated calls, store the access token securely.
If your architecture involves your backend providing a token to a client application (e.g., a single-page web app) for direct OpenF1 API calls:
localStorage
for sensitive tokens due
to XSS risks. HttpOnly, Secure cookies are better if
applicable for web).
Do not embed access tokens directly into your client-side source code if it's publicly accessible. For client applications, the ideal pattern is for your application to communicate with *your* backend, and your backend then makes authenticated requests to the OpenF1 API.