ncaapyscraper
Rosters, coaches and schedules for every sport at almost 1,000 NCAA schools, from Division I down to Division III. Use it from the command line or from Python, and you get clean JSON back.
pip install ncaapyscraper
import ncaapyscraper as nps
nps.get_roster("duke", "football")
nps.get_schedule("alabama", "mens-basketball")
Don't want to run anything? A fresh copy of all of it is published every week, see Download the data.
Download the data
Every Monday a GitHub Action scrapes every supported school and publishes the result under Releases.
- ncaapyscraper-data.zip has one JSON file per school plus
index.json - index.json on its own lists every school with its conference, division and file name
Bios are left out of the weekly data to keep it small. Run it yourself if you need them.
Command line
One school, everything
ncaapyscraper duke
A few schools, by key or by website
ncaapyscraper alabama navy goduke.com
Football only
ncaapyscraper ohio_state --sport football
Basketball schedules for the whole SEC (basketball matches men's and women's)
ncaapyscraper --conference sec --sport basketball --schedules
Every FCS school, athletes only
ncaapyscraper --division fcs --players
Women's soccer rosters across Division III, no bios
ncaapyscraper --division 3 --sport womens-soccer --players --no-bios
Find a school's key, or see what's in a conference
ncaapyscraper --list -c "big sky"
ncaapyscraper --conferences
Each school is saved to output/<key>.json. Pick another folder with -o.
| Flag | What it does |
|---|---|
-l, --list |
List supported schools. Combine with -c or -d |
--conferences |
List conferences |
-a, --all |
Every supported school |
-c, --conference |
Every school in a conference. Short names work: sec, acc, big10, big12, ivy, mwc, a10... or any part of the name |
-d, --division |
1, 2, 3, fbs or fcs |
-s, --sport |
Only these sports, e.g. football, mens-basketball, golf. Repeat it or use commas |
-g, --gender |
men or women. Co-ed teams (track, swimming, rifle) stay in, their athletes get filtered |
--players |
Athletes only |
--coaches |
Coaches and staff only |
--schedules |
Schedules only |
--no-bios |
Leave out bios, files get a lot smaller |
--compact |
JSON without indentation |
-o, --output |
Output folder, default output |
-p, --parallel |
Schools to scrape at once, default 4 |
-v, --verbose |
Log every request |
--players, --coaches and --schedules can be combined. Without any of them you get all three.
Python
The get_ functions return plain lists of dicts, one row per player, coach or game, with school, sport and season on every row.
import ncaapyscraper as nps
roster = nps.get_roster("duke", "football")
coaches = nps.get_coaches("navy", "football")
games = nps.get_schedule("stanford", "basketball") # men's and women's
school = nps.get_school("villanova", sports=["football"], data=["players", "schedules"])
nps.list_schools("sec") # or division="fbs", 1, 2, 3
Straight into pandas
import pandas as pd
df = pd.DataFrame(nps.get_roster("texas", "baseball"))
They work in Jupyter too.
For lots of schools at once there's an async version. It keeps every school's site to a few requests at a time, and yields each school as it finishes.
import asyncio
import ncaapyscraper as nps
async def main():
keys = [school["key"] for school in nps.list_schools("ivy")]
async for key, result in nps.fetch_schools(keys, sports="football", parallel=8):
if isinstance(result, Exception):
print(key, "failed", result)
continue
print(key, sum(len(sport["players"]) for sport in result["sports"]))
asyncio.run(main())
fetch_school, fetch_roster, fetch_coaches and fetch_schedule are the async versions of the get_ functions.
A school that isn't on the list yet? Pass a dict instead of a key.
nps.get_school({"name": "Boise State University", "site": "broncosports.com", "platform": "sidearm"})
JSON response
One file (or dict) per school, grouped by sport. Missing values are null.
{
"key": "duke",
"school": "Duke University",
"conference": "Atlantic Coast Conference",
"division": 1,
"subdivision": "FBS",
"state": "NC",
"site": "https://goduke.com",
"platform": "sidearm",
"scraped_at": "2026-11-05T07:29:39Z",
"sports": [
{
"sport": "Football",
"gender": "men",
"season": "2026",
"players": [
{
"name": "Jordan Smith",
"first_name": "Jordan",
"last_name": "Smith",
"shirt_no": "24",
"position": "RB",
"height": "5-10",
"weight": 205,
"player_class": "Senior",
"hometown": "Charlotte, N.C.",
"highschool": "Myers Park",
"previous_school": "East Carolina",
"major": "Economics",
"gender": "men",
"image_url": "https://goduke.com/images/2026/7/27/smith_jordan.jpg",
"profile_url": "https://goduke.com/sports/football/roster/jordan-smith/24470",
"bio": null
}
],
"coaches": [
{
"name": "Chris Allen",
"first_name": "Chris",
"last_name": "Allen",
"title": "Head Coach",
"image_url": "https://goduke.com/images/2024/3/6/allen_chris.jpg",
"profile_url": "https://goduke.com/sports/football/roster/coaches/chris-allen/5388",
"bio": "Chris Allen was named head coach in December 2023..."
}
],
"schedule": [
{
"date": "2026-09-05",
"time": "5:00 PM",
"datetime_utc": "2026-09-05T21:00:00Z",
"opponent": "Tulane",
"home_away": "home",
"location": "Durham, N.C.",
"venue": "Brooks Field at Wallace Wade Stadium",
"is_conference": false,
"result": "W",
"score": "17-3",
"tournament": null,
"tv": "ACC Network",
"image_url": "https://goduke.com/images/logos/Tulane-Wave.png"
}
]
}
]
}
coachesincludes support staff,titletells you who's whodateandtimeare the school's local time.datetime_utcis filled for schools on the SIDEARM API and WMTscoreis always the school's score first,resultisW,LorTgenderon a player only matters for co-ed teams like track and swimmingsubdivisionisFBS,FCSornull- How much detail you get depends on what the school puts on its site. Bios, majors and weights are often missing for smaller schools
- With
--players,--coachesor--schedulesyou only get those keys in each sport
Supported schools
Every NCAA school whose athletics site runs on SIDEARM Sports or WMT Digital, which is most of them. The full list with keys is in docs/schools.md, or run ncaapyscraper --list.
Schools on other platforms (PrestoSports and custom builds) aren't covered yet.
Docs
The docs folder is an unofficial reference for the APIs and pages these sites use, handy even if you write your own scraper.
Adding a new school
NAIA, junior colleges and anything else on the same platforms work too.
- Find the school's athletics website
- Open these in the browser, the first one that shows JSON tells you the platform
https://<site>/api/v2/Sports→sidearmhttps://<site>/website-api/sports→wmthttps://<site>/services/adaptive_components.ashx?type=main-navigation&count=10&start=0&extra=%7B%7D→sidearm_legacy
- Try it straight away by passing a dict to
get_school(see Python) - To add it for everyone, add a row to ncaapyscraper/schools.csv and open a PR
key,name,conference,division,subdivision,state,site,platform
my_school,My School University,My Conference,3,,OH,myschoolathletics.com,sidearm_legacy
Development
- Clone the repo and go into the folder
- Run
python3 -m venv envandsource env/bin/activate - Run
pip install -e ".[dev]" - Run
pytest
Needs Python 3.10+.
License
MIT
Metadata
Release files for ncaapyscraper 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ncaapyscraper-0.1.0.tar.gz | 52.4 kB | With provenance | Details for ncaapyscraper-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ncaapyscraper-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for ncaapyscraper-0.1.0-py3-none-any.whl |
Total release size: 109.5 kB
Release files / ncaapyscraper-0.1.0.tar.gz
| Download URL | ncaapyscraper-0.1.0.tar.gz |
|---|---|
| Size | 52.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bb181fd9af73971b57cc5b05b515cfa085b5ff848ebf99dd8e04f00a1fa49ebc
|
|
BLAKE2b-256 checksum How to use checksums |
5f148a5a1387636ea5ab2cae4081994c4508b7ff444e65b32ed86b99144da512
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logRelease files / ncaapyscraper-0.1.0-py3-none-any.whl
| Download URL | ncaapyscraper-0.1.0-py3-none-any.whl |
|---|---|
| Size | 57.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0ebc0c93e39ec39053a4cf416cd53dc36ff3a862d1aed2ad2ef82166a9478965
|
|
BLAKE2b-256 checksum How to use checksums |
9ae011591c8174b828008c4ba91908a51ffae215623509de39cb0809535b3eea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logSecurity for ncaapyscraper 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for ncaapyscraper-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.