Project 4: Pull Live OPR & EPA Data with Python
Use The Blue Alliance and Statbotics APIs to fetch OPR and EPA for every team at your event and merge it with your hand-scouted data.
Sign in to track progress, earn XP, and save lessons.
Hand scouting and public analytics are complementary: your data captures reliability and intent; OPR/EPA capture aggregate scoring across the whole event. This project pulls both with a few lines of Python.
OPR from The Blue Alliance. OPR (Offensive Power Rating) uses linear algebra to estimate each team's average point contribution. TBA exposes it per-event. Get a free read API key from your TBA account page, then:
import requests
HEADERS = {"X-TBA-Auth-Key": "YOUR_TBA_READ_KEY"}
EVENT = "2026wabon" # event key: year + event code
oprs = requests.get(
f"https://www.thebluealliance.com/api/v3/event/{EVENT}/oprs",
headers=HEADERS
).json()
# oprs["oprs"] is {team_key: opr_value}, e.g. {"frc254": 78.3, ...}
for team, opr in sorted(oprs["oprs"].items(), key=lambda kv: -kv[1])[:8]:
print(team, round(opr, 1))
That prints the top eight teams by OPR — a fast first cut at "who scores a lot." Remember OPR is a prediction, not ground truth; it can be distorted by who a team played with, so it supplements but never replaces real scouting.
EPA from Statbotics. EPA (Expected Points Added) is an Elo-derived model expressed in point units, and it separates into auto, teleop, and endgame component EPAs plus ranking-point EPAs — which map cleanly onto REBUILT's phases. Statbotics offers a REST API and a Python package:
import statbotics
sb = statbotics.Statbotics()
row = sb.get_team_event(254, "2026wabon")
# row is a dict of EPA stats for that team at that event.
# Inspect the keys to find the component fields, then pull what you need:
print(row.keys())
The exact field names for the auto/teleop/endgame components are documented in the Statbotics REST/Python docs — print row.keys() once and read off the components, since the schema evolves between Statbotics versions. With those values you can ask sharper questions than "who's good": Which teams have high endgame EPA? (great TOWER climbers, relevant to the TRAVERSAL ranking point). Which teams have high auto EPA? (they help win the early HUB-active windows).
Merge with your scouting. Build a table keyed by team number with columns: your avg teleop fuel, your died count, TBA OPR, and the Statbotics auto/teleop/endgame EPA components. The magic is in the disagreements. A team with high OPR/EPA but a high died-count in your data is a reliability risk the public stats can't see. A team with mediocre OPR but rock-solid reliability and a strong climb may be an underrated second-pick. Use the analytics to rank, then use your scouting to break ties and catch risks.
Key takeaways
- TBA's /event/{key}/oprs endpoint returns per-team OPR keyed under an 'oprs' object; it predicts scoring but is sensitive to alliance partners.
- Statbotics EPA is in point units and splits into auto/teleop/endgame components; print row.keys() to read the exact field names for your version.
- The decisive insight comes from disagreements: high public rating + high died-count in your data = a hidden reliability risk.
Lesson quiz
RequiredAnswer all 3 questions correctly to complete this lesson.
1.When pulling data from The Blue Alliance API v3 in Python, how do you authenticate each request?
2.Using the Statbotics Python package, which snippet correctly retrieves team 254's EPA data?
3.How is a team's Statbotics EPA (Expected Points Added) most directly interpreted?
Answer every question to submit.