TFRRS APItfrrs.org ↗
Access college track and field and cross country data from TFRRS: athlete performances, personal bests, meet results, event standings, and team rosters.
What is the TFRRS API?
The TFRRS API exposes college track and field and cross country data across 5 endpoints, covering athlete search, performance history, meet results, per-event standings, and team rosters. The get_athlete_results endpoint returns every indexed competition result for a given athlete alongside personal bests, while get_event_results gives place-by-place standings with marks and team affiliations for any indexed meet event.
curl -X GET 'https://api.parse.bot/scraper/1b66c7cb-769a-4301-82ff-8d308afee7ad/search_athlete?query=Emma+Coburn' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace tfrrs-org-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""
TFRRS Track and Field Results API Client
Practical usage example for extracting college track and field results.
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from typing import Optional, Dict, List, Any
class ParseClient:
"""Client for interacting with the TFRRS Track and Field Results API via Parse."""
def __init__(self, api_key: Optional[str] = None):
"""
Initialize the Parse API client.
Args:
api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
"""
self.base_url = "https://api.parse.bot"
self.scraper_id = "1b66c7cb-769a-4301-82ff-8d308afee7ad"
self.api_key = api_key or os.getenv("PARSE_API_KEY")
if not self.api_key:
raise ValueError("API key must be provided or set in PARSE_API_KEY environment variable")
def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
"""
Make a request to the Parse API.
Args:
endpoint: The API endpoint name
method: HTTP method (GET or POST)
**params: Query/body parameters
Returns:
Response data from the API
"""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
if method.upper() == "GET":
response = requests.get(url, headers=headers, params=params)
else: # POST
response = requests.post(url, headers=headers, json=params)
response.raise_for_status()
return response.json()
def search_athlete(self, query: str) -> Dict[str, Any]:
"""
Search for college athletes by name on TFRRS.
Args:
query: Athlete name to search for
Returns:
Dictionary with athletes array containing matching athletes
"""
return self._call("search_athlete", method="GET", query=query)
def get_athlete_results(self, athlete_id: str) -> Dict[str, Any]:
"""
Get detailed performance results for a specific college athlete.
Args:
athlete_id: Numeric athlete ID from TFRRS
Returns:
Dictionary with athlete details, personal bests, and performance history
"""
return self._call("get_athlete_results", method="GET", athlete_id=athlete_id)
def get_meet_results(self, meet_id: str) -> Dict[str, Any]:
"""
Get basic information and event listings for a specific college meet.
Args:
meet_id: Numeric meet ID from TFRRS
Returns:
Dictionary with meet info, events list, and partial athlete list
"""
return self._call("get_meet_results", method="GET", meet_id=meet_id)
def get_event_results(self, event_url: str) -> Dict[str, Any]:
"""
Get results for a specific event within a meet.
Args:
event_url: Full URL of the event results page
Returns:
Dictionary with results array containing placements and marks
"""
return self._call("get_event_results", method="GET", event_url=event_url)
def get_team_roster(self, team_url: str) -> Dict[str, Any]:
"""
Get the roster of athletes for a specific college team.
Args:
team_url: Path or full URL of the team page
Returns:
Dictionary with team name and roster of athletes
"""
return self._call("get_team_roster", method="GET", team_url=team_url)
def main():
"""
Practical workflow example: Find an athlete, get their results, and analyze their performance.
"""
# Initialize the client
client = ParseClient()
print("=" * 60)
print("TFRRS Track and Field Results - Analysis Example")
print("=" * 60)
# Step 1: Search for an athlete
print("\n[Step 1] Searching for athlete: 'Graham Blanks'")
search_response = client.search_athlete("Graham Blanks")
if "data" in search_response and search_response["data"]["athletes"]:
athletes = search_response["data"]["athletes"]
print(f"Found {len(athletes)} athlete(s)")
# Step 2: Get details for the first matching athlete
athlete = athletes[0]
athlete_id = athlete["athlete_id"]
print(f"\n[Step 2] Getting results for {athlete['name']} (ID: {athlete_id})")
athlete_results = client.get_athlete_results(athlete_id)
# Extract and display athlete information
if "data" in athlete_results:
athlete_data = athlete_results["data"]
print(f"\nAthlete: {athlete_data['name']}")
print(f"Team: {athlete_data['team']}")
if athlete_data.get("year"):
print(f"Year: {athlete_data['year']}")
# Step 3: Display personal bests
print(f"\nPersonal Bests:")
if athlete_data.get("personal_bests"):
for pb in athlete_data["personal_bests"]:
print(f" {pb['event']:20s}: {pb['mark']}")
else:
print(" No personal bests available")
# Step 4: Display recent performances
print(f"\nRecent Performances (last 10):")
performances = athlete_data.get("performances", [])
for perf in performances[:10]:
event_type = "XC" if perf.get("is_xc") else "Track/Field"
print(f" {perf['meet_date']:20s} | {perf['event']:10s} | {perf['mark']:12s} | Place: {perf['place']:5s} | {event_type}")
# Step 5: Get team roster to see teammates
print(f"\n[Step 3] Getting team roster for {athlete_data['team']}")
team_name = athlete_data['team']
state_code = "MA" # Harvard is in Massachusetts
team_url = f"/teams/tf/{state_code}_college_m_{team_name.lower()}.html"
try:
roster_response = client.get_team_roster(team_url)
if "data" in roster_response:
roster_data = roster_response["data"]
print(f"\n{roster_data['team_name']} Roster ({len(roster_data['roster'])} athletes):")
for i, teammate in enumerate(roster_data["roster"][:5], 1):
print(f" {i}. {teammate['name']} (ID: {teammate['athlete_id']})")
if len(roster_data["roster"]) > 5:
print(f" ... and {len(roster_data['roster']) - 5} more athletes")
except Exception as e:
print(f"Note: Could not retrieve team roster: {e}")
else:
print("No athletes found matching the search query")
print("\n" + "=" * 60)
print("Analysis complete!")
print("=" * 60)
if __name__ == "__main__":
main()Search for college athletes by name on TFRRS. Returns matching athletes from the NCAA/NAIA/NJCAA database. Only athletes registered in TFRRS (current or recent college athletes) will return results; professional or post-collegiate athletes not in the system will return an empty array.
| Param | Type | Description |
|---|---|---|
| queryrequired | string | Athlete name to search for (e.g., 'Emma Coburn') |
{
"type": "object",
"fields": {
"athletes": "array of athlete objects with athlete_id, name, and url"
},
"sample": {
"data": {
"athletes": [
{
"url": "https://tfrrs.org/athletes/7919013/Harvard/Graham_Blanks.html",
"name": "Blanks, Graham",
"athlete_id": "7919013"
}
]
},
"status": "success"
}
}About the TFRRS API
Athlete Search and Performance History
The search_athlete endpoint accepts a name string and returns an array of matching athlete objects, each with an athlete_id, name, and url. That athlete_id feeds directly into get_athlete_results, which returns the athlete's full name, current team, eligibility year (e.g., SR-4), a performances array, and a personal_bests array. Each performance object carries meet_name, meet_date, event, mark, mark_seconds (numeric, useful for sorting), place, and boolean flags is_xc and is_track_field to distinguish cross country from track and field results. Coverage is limited to NCAA, NAIA, and NJCAA athletes currently or recently indexed in TFRRS; post-collegiate athletes will not appear.
Meet and Event Results
get_meet_results takes a numeric meet_id and returns the meet's official name, an events array with name and URL for each result page, and an athletes_found array capped at 50 entries. To get full standings for a specific event, pass the url from that events array to get_event_results, which returns a results array where each object includes place, athlete_name, athlete_id, team, and mark. Only college-level meets indexed by TFRRS will have a populated events list; high school or non-indexed meets may return incomplete data.
Team Rosters
get_team_roster accepts a team page path following the pattern /teams/tf/{STATE}_college_{m|f}_{School}.html. It returns the team_name and a roster array of athlete objects with athlete_id and name. Those IDs can then be passed to get_athlete_results to pull performance history for every athlete on a squad. The endpoint covers both men's and women's rosters depending on the path supplied.
The TFRRS API is a managed, monitored endpoint for tfrrs.org — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when tfrrs.org changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official tfrrs.org API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Track a college athlete's season progression by sorting their
performancesarray bymeet_dateandmark_seconds. - Build a conference rankings table by pulling
get_event_resultsfor each event across multiple meets and aggregating marks by team. - Compare personal bests across all athletes on a roster using
get_team_rosterIDs piped intoget_athlete_results. - Identify top performers at a specific meet by iterating
get_meet_resultsevents and collecting first-place finishers fromget_event_results. - Filter an athlete's history to cross country only using the
is_xcboolean on each performance object. - Automate recruiting research by querying
search_athletefor prospects and retrieving their full mark history and personal bests.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does TFRRS have an official public developer API?+
What does `get_athlete_results` return beyond just times and distances?+
meet_name, meet_date, place, and a numeric mark_seconds field in addition to the formatted mark. Boolean fields is_xc and is_track_field let you filter results to a single discipline without string parsing. The personal_bests array is a separate condensed view with one best mark per event.Does the API cover high school athletes or post-collegiate professionals?+
Is historical meet data available, or only current-season results?+
get_athlete_results endpoint returns all indexed historical performances for an athlete, not just the current season. For meets, get_meet_results works with any numeric meet_id that TFRRS has indexed, regardless of season. Meets that were never indexed by TFRRS — including many high school invitationals — will return incomplete or empty event lists.Can I retrieve full team-level season statistics, like scoring summaries or dual-meet records?+
get_team_roster and individual performance history via get_athlete_results, but does not expose aggregated team scoring, season win-loss records, or dual-meet summaries. You can fork it on Parse and revise it to add an endpoint targeting TFRRS team season summary pages.