
Xctf Data
- 355 installs
- 201 repo stars
- Updated August 5, 2026
- machina-sports/sports-skills
Study cross-country and track-and-field results, meets, and athlete histories to validate niche endurance-sports product ideas and data completeness.
About
XCTF-data skill covers cross-country and track-and-field meet results, athlete records, and endurance-sport statistics for ideation research—assessing coverage depth before building niche running or collegiate athletics products.
- cross-country
- track and field
- meet results
- athlete history
- niche sports data
Xctf Data by the numbers
- 355 all-time installs (skills.sh)
- +6 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #538 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/machina-sports/sports-skills --skill xctf-dataAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 355 |
|---|---|
| repo stars | ★ 201 |
| Last updated | August 5, 2026 |
| Repository | machina-sports/sports-skills ↗ |
What it does
Study cross-country and track-and-field results, meets, and athlete histories to validate niche endurance-sports product ideas and data completeness.
Files
XC/TF Data (TFRRS — NCAA Cross Country & Track and Field)
Before writing queries, consult references/api-reference.md for parameters, URL conventions, and return shapes.
Setup
Before first use, check if the CLI is available:
which sports-skills || pip install sports-skillsIf pip install fails, install from GitHub:
pip install git+https://github.com/machina-sports/sports-skills.gitRequires Python 3.10+. No API keys required. All data comes from TFRRS public pages and The Stride Report RSS feed.
Quick Start
CLI (preferred):
sports-skills xctf get_athlete_profile --athlete_id=9230145 --school=BYU --name=Jane_Hedengren
sports-skills xctf get_news --limit=5Python SDK:
from sports_skills import xctf
profile = xctf.get_athlete_profile(
athlete_id="9230145",
school="BYU",
name="Jane_Hedengren",
)CRITICAL: Before Any Query
All three parameters are required and must match the athlete's TFRRS URL exactly:
https://www.tfrrs.org/athletes/{athlete_id}/{school}/{name}.htmlathlete_id— numeric ID (e.g.9230145)school— school slug with underscores, not spaces (e.g.BYU)name— athlete name slug (e.g.Jane_Hedengren)
Do NOT guess slugs. Find them by navigating to the athlete on tfrrs.org and copying the URL.
Commands
| Command | Description |
|---|---|
search_athlete | Search the current team roster by name; returns athlete_id, school, and name slugs for use with get_athlete_profile. Searches both genders automatically. Current athletes only — graduated athletes require a direct TFRRS URL |
get_athlete_profile | Athlete name, school, eligibility, all PRs, and full season-by-season meet results |
get_team_roster | Full XC and/or TF roster for a team |
get_meet_results | All event results and team scores from a TFRRS meet |
get_news | Recent XC/TF articles from The Stride Report (thestridereport.com) |
See references/api-reference.md for full parameter details and return shapes.
Examples
Example 1: Look up a current athlete's PRs User says: "What are Jane Hedengren's PRs?" Actions: 1. Call search_athlete(name="Jane Hedengren", school="UT_college_f_BYU") Result: data.matches contains entries with athlete_id, school, name slugs 2. Call get_athlete_profile(athlete_id="9230145", school="BYU", name="Jane_Hedengren") Result: data.prs contains all personal records by event (e.g. {"1500": "4:10.24", "5000": "14:44.79", "6K (XC)": "18:29.6", ...})
Example 2: Get a runner's cross country season User says: "Show me Jane Hedengren's 2025 XC season results" Actions: 1. Call search_athlete(name="Jane Hedengren", school="UT_college_f_BYU") 2. Call get_athlete_profile with the matched athlete params 3. Filter data.meets for entries whose date falls in the fall of 2025 (Sep–Nov 2025) Result: List of meets with dates, events, marks, and places
Example 3: Graduated or transferred athlete User says: "What are Katelyn Vuong's PRs from UC Davis?" Actions: 1. Call search_athlete(name="Katelyn Vuong", school="CA_college_f_UC_Davis") Result: data.matches is empty — athlete has graduated 2. Tell the user: "Katelyn Vuong is not on UC Davis's current roster. Please find her profile URL on tfrrs.org (e.g. search 'Katelyn Vuong UC Davis tfrrs') and share it." 3. User provides: https://www.tfrrs.org/athletes/7899206/UC_Davis/Katelyn_Vuong.html 4. Extract params from the URL and call get_athlete_profile(athlete_id="7899206", school="UC_Davis", name="Katelyn_Vuong") Note: TFRRS creates separate profiles for XC and TF. If both exist, fetch both IDs for complete PRs.
Example 4: Get a team's current roster User says: "Show me the UC Davis women's XC roster" Actions: 1. Call get_team_roster(school="CA_college_f_UC_Davis", sport="xc") Result: List of athletes with name, year, and profile slugs
Example 5: Get results from a meet User says: "Show me the results from the Stanford Invitational" Actions: 1. Find the meet on tfrrs.org and copy the meet_id and slug from the URL (e.g. tfrrs.org/results/95890/Stanford_Invitational) 2. Call get_meet_results(meet_id="95890", slug="Stanford_Invitational") Result: All event results and team scores from the meet
Example 6: Get the latest XC/TF news User says: "What's the latest college track news?" Actions: 1. Call get_news(limit=10) Result: Recent articles from The Stride Report with title, date, summary, and link
Commands that DO NOT exist — never call these
- ~~
get_team_rankings~~ — does not exist. Useget_athlete_profilefor individual data. - ~~
search_athletes~~ — does not exist. The correct command issearch_athlete(no trailing 's'). - ~~
fetch_news~~ — does not exist. The correct command isget_news.
If a command is not listed in the Commands table above, it does not exist.
Error Handling
When a command fails, do not surface raw errors to the user. Instead: 1. For get_athlete_profile: confirm athlete_id, school, and name match the TFRRS URL exactly (case-sensitive) 2. For search_athlete: verify the team slug is correct by checking the team's TFRRS page URL 3. For get_meet_results: verify the meet_id and slug match the meet's TFRRS URL exactly 4. For get_team_roster: verify the school slug is correct 5. For get_news: if the feed fails, inform the user that The Stride Report may be temporarily unavailable 6. Report failure with a clean message only after exhausting alternatives
Troubleshooting
`sports-skills` command not found Run pip install sports-skills or install from GitHub (see Setup above).
HTTP 404 on athlete profile The school or name slug does not match the TFRRS URL exactly. Slugs are case-sensitive and use underscores. Copy directly from tfrrs.org.
`prs` returns empty dict The athlete's profile page may be very new or structured differently. Check the URL directly on tfrrs.org.
`search_athlete` returns empty matches The athlete is likely graduated or transferred. See Example 3 above for how to handle this.
`get_meet_results` returns no events The meet_id or slug may be incorrect. Copy both directly from the meet's TFRRS URL.
`get_news` fails or returns no articles The Stride Report RSS feed may be temporarily unavailable. Try again later.
Connection errors or timeouts TFRRS may be temporarily unavailable. Requests are throttled to 1 per second automatically — wait a moment and retry.
XC/TF Data — API Reference
Data source: tfrrs.org (Track & Field Results Reporting System)
---
URL Convention
All athlete data is fetched from a single URL pattern:
https://www.tfrrs.org/athletes/{athlete_id}/{school}/{name}.html| Component | Description | Example |
|---|---|---|
athlete_id | Numeric TFRRS ID | 9230145 |
school | School name slug (underscores, Title_Case) | BYU |
name | Athlete name slug (underscores, Title_Case) | Jane_Hedengren |
Slugs are case-sensitive and must match the TFRRS URL exactly. Find them by navigating to the athlete's profile on tfrrs.org.
---
search_athlete
sports-skills xctf search_athlete --name=<name> --school=<team_slug>Searches the current XC and TF team roster pages for athletes matching the given name.
Note: Only covers athletes on the current-season roster. Graduated or transferred athletes will not appear — useget_athlete_profiledirectly with theirathlete_idfrom their TFRRS profile URL.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Athlete name to search for (e.g. "Jane Hedengren") |
school | string | Yes | TFRRS team slug from the team page URL (e.g. "UT_college_f_BYU") |
The team page URL pattern is:
https://www.tfrrs.org/teams/{xc|tf}/{school}.htmlNote: the team slug (e.g. CA_college_f_UC_Davis) differs from the athlete profile school slug (e.g. UC_Davis). The matches results include the athlete profile school slug ready to pass to get_athlete_profile.
Return shape
{
"status": true,
"message": "",
"data": {
"matches": [
{
"athlete_id": "9230145",
"school": "BYU",
"name": "Jane_Hedengren",
"sport": "xc",
"url": "https://www.tfrrs.org/athletes/9230145/BYU/Jane_Hedengren.html"
},
{
"athlete_id": "9230145",
"school": "BYU",
"name": "Jane_Hedengren",
"sport": "tf",
"url": "https://www.tfrrs.org/athletes/9230145/BYU/Jane_Hedengren.html"
}
]
}
}Field notes
| Field | Notes |
|---|---|
matches | Empty list if no athletes match the name on the current roster. |
matches[].sport | "xc" or "tf" — an athlete may appear in both if listed on both rosters. |
matches[].athlete_id | Use this directly as athlete_id in get_athlete_profile. |
matches[].school | Athlete profile school slug (e.g. BYU) — use as school in get_athlete_profile. |
matches[].name | Athlete name slug (e.g. Jane_Hedengren) — use as name in get_athlete_profile. |
Error response
{
"status": false,
"message": "HTTP 404: Not Found",
"data": null
}Common causes: incorrect team slug. Verify the slug from the team's TFRRS page URL.
---
get_athlete_profile
sports-skills xctf get_athlete_profile --athlete_id=<id> --school=<school> --name=<name>Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
athlete_id | string | Yes | Numeric TFRRS athlete ID |
school | string | Yes | School slug as it appears in the TFRRS URL |
name | string | Yes | Athlete name slug as it appears in the TFRRS URL |
Return shape
{
"status": true,
"message": "",
"data": {
"athlete_id": "9230145",
"url": "https://www.tfrrs.org/athletes/9230145/BYU/Jane_Hedengren.html",
"name": "Jane Hedengren",
"school": "BYU",
"eligibility": "FR-1",
"prs": {
"1500": "4:10.24",
"MILE": "4:22.22",
"3000": "8:34.98",
"5000": "14:44.79",
"10,000": "30:46.80",
"6K (XC)": "18:29.6"
},
"meets": [
{
"meet": "Big 12 Outdoor Track & Field Championships",
"date": "May 14-16, 2026",
"results": [
{ "event": "1500", "mark": "4:10.24", "place": "3rd (F)" },
{ "event": "5000", "mark": "15:26.94", "place": "1st (F)" }
]
},
{
"meet": "NCAA Division I Indoor Track & Field Championships",
"date": "Mar 13-14, 2026",
"results": [
{ "event": "3000", "mark": "8:36.61", "place": "1st (F)" },
{ "event": "5000", "mark": "15:00.12", "place": "1st (F)" }
]
},
{
"meet": "NCAA Division I Cross Country Championships",
"date": "Nov 22, 2025",
"results": [
{ "event": "6k", "mark": "18:38.9", "place": "2nd" }
]
}
]
}
}Field notes
| Field | Notes |
|---|---|
school | Short school abbreviation as shown on TFRRS (e.g. CBU, not the full name) |
eligibility | Year-in-school code: FR-1, SO-2, JR-3, SR-4, or a graduate/transfer variant |
prs | All-time personal records from the summary table at the top of the profile. Keys are event names exactly as TFRRS labels them. |
meets | Flat list of all meets, ordered most recent first. |
meets[].date | Date string as it appears on TFRRS — may be a single date ("Mar 13, 2026") or a range ("May 9-11, 2024"). |
meets[].results | Each result has event and mark. place is included when available (e.g. "1st (F)" = 1st in final, "3rd (P)" = 3rd in prelim). |
Error response
{
"status": false,
"message": "HTTP 404: Not Found",
"data": null
}Common causes: incorrect school or name slug, athlete profile not yet on TFRRS.
---
---
get_news
sports-skills xctf get_news
sports-skills xctf get_news --limit=5Fetches recent articles from The Stride Report RSS feed (thestridereport.com/blog-feed.xml).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | int | No | Max number of articles to return. Omit for all available. |
Return shape
{
"status": true,
"message": "",
"data": {
"source": "The Stride Report",
"count": 10,
"articles": [
{
"title": "First Thoughts: McFarland Runs 3:33...",
"link": "https://www.thestridereport.com/post/first-thoughts-...",
"date": "Sun, 19 Apr 2026 00:27:30 GMT",
"summary": "Look, there was A LOT of chaos that took place this weekend...",
"categories": ["D1", "OUTDOORS"],
"author": "Admin (Garrett Zatlin)",
"image": "https://static.wixstatic.com/media/..."
}
]
}
}Field notes
| Field | Notes |
|---|---|
articles[].categories | List of topic tags from the feed (e.g. ["D1", "OUTDOORS"], ["XC"]). May be empty. |
articles[].image | URL of the article's lead image from the RSS enclosure. Empty string if none. |
articles[].summary | Short excerpt — typically truncated with "...". Not the full article body. |
articles[].date | RFC 822 timestamp string as published in the feed. |
---
Notes on TFRRS data
- Relay results appear as events like
4x800orDMRwith a split/relay time. - DNF / DNS marks appear as the mark value when no time was recorded.
- Wind readings may appear alongside marks (e.g.
2:10.30 (-0.3)) — these are included in the raw mark string. - XC distances vary by meet and division: common values are
5k,6k,8k(women),10k(men). - Requests are throttled to 1 per second and cached for 5 minutes to be respectful of the TFRRS server.
#!/bin/bash
# Validates parameters before executing xctf-data commands
if ! command -v sports-skills &>/dev/null; then
echo "ERROR: sports-skills CLI not found. Run: pip install sports-skills"
exit 1
fi
if [[ "$*" == *"get_athlete_profile"* ]]; then
if [[ "$*" != *"--athlete_id="* ]]; then
echo "ERROR: get_athlete_profile requires --athlete_id"
exit 1
fi
if [[ "$*" != *"--school="* ]]; then
echo "ERROR: get_athlete_profile requires --school"
exit 1
fi
if [[ "$*" != *"--name="* ]]; then
echo "ERROR: get_athlete_profile requires --name"
exit 1
fi
fi
if [[ "$*" == *"search_athlete"* ]]; then
if [[ "$*" != *"--name="* ]]; then
echo "ERROR: search_athlete requires --name"
exit 1
fi
if [[ "$*" != *"--school="* ]]; then
echo "ERROR: search_athlete requires --school"
exit 1
fi
fi
if [[ "$*" == *"get_meet_results"* ]]; then
if [[ "$*" != *"--meet_id="* ]]; then
echo "ERROR: get_meet_results requires --meet_id"
exit 1
fi
if [[ "$*" != *"--slug="* ]]; then
echo "ERROR: get_meet_results requires --slug"
exit 1
fi
fi
if [[ "$*" == *"get_team_roster"* ]]; then
if [[ "$*" != *"--school="* ]]; then
echo "ERROR: get_team_roster requires --school"
exit 1
fi
fi
echo "OK"