What Is nfl_data_py?
nfl_data_py is an open-source Python package that loads NFL data published by the nflverse community project, including play by play, weekly player statistics, schedules, rosters, and identifier mappings, directly into pandas DataFrames. It downloads prebuilt data files rather than querying a live API, so freshness follows the project's publishing schedule.
What it provides
The package is a set of import functions, each returning a pandas DataFrame for the seasons you request. The most commonly used are:
Play by play. Loaded with import_pbp_data, one row per play for the selected seasons. This is the table most analysis is built on. It includes game situation, play description, participants, yardage, and a set of model-derived columns such as expected points added and win probability, which come from the nflverse models.
Weekly player data. Loaded with import_weekly_data, aggregating player statistics by week. Convenient for usage and production questions without aggregating play by play yourself.
Schedules. Loaded with import_schedules, with game dates, teams, scores, and additional game context.
Identifier mappings. A table linking player identifiers used by different data providers and websites. This is one of the most valuable and least discussed parts of the package, because joining NFL data to any other source depends on it.
There are further loaders for rosters, snap counts, injuries, depth charts, and aggregated tracking statistics, with coverage years that vary by table. Check the documentation for each before assuming history goes back as far as play by play does.
A first load
After installing the package, import nfl_data_py as nfl followed by pbp = nfl.import_pbp_data([2023, 2024]) returns a DataFrame for two seasons. Play by play tables are wide, with several hundred columns, so it is worth selecting the columns you need early. Save the result to Parquet so you do not download it again.
How to use it responsibly
Understand where the data comes from. The package downloads files that nflverse builds and publishes. It is a community project, not an official league service, and its definitions follow its own documentation. Read the data dictionary for any column you rely on.
Treat model-derived columns as estimates. Expected points added and win probability are outputs of models trained by the project. They are very useful and they change when those models are updated. An analysis rerun on a later release can give different numbers without any play having changed.
Save what you load, with the date. Because published files can be rebuilt and corrected, keep your own copy of the data an analysis used, recorded with the retrieval date. That is the only way to reproduce a result later.
Know the freshness. During the season, published files update on the project's schedule rather than in real time. For anything that needs live data, this is the wrong tool. For historical and weekly analysis, it is usually the right one.
Check coverage per table. Different loaders cover different seasons. Participation, injury, and tracking-derived tables typically have shorter histories than play by play.
Joining to odds data
Odds come from a different kind of provider with its own team and game identifiers. Build the join once, on team abbreviations normalised to a single convention plus game date, verify it against the schedule table, and keep the mapping as a maintained file rather than rebuilding it inside every analysis.
Its status and alternatives
Open-source data packages evolve. The nflverse project has released nflreadpy, a newer Python package for loading the same family of data, and has pointed users toward it for new work. Before starting a project, check the repository of each package for its current maintenance status and follow whichever the project currently recommends. The underlying data is the same family either way, so the concepts on this page carry over.
The R ecosystem around nflverse is the origin of much of this data and remains the most complete home for it. Python users benefit from reading its documentation too, since column definitions are shared.
For comparison with other ways of getting NFL data: official league sources provide limited public programmatic access, commercial providers offer supported APIs with live data at a cost, and reference websites provide browsable history with terms that usually restrict automated collection. Community packages like this one sit in a useful middle position: free, cleaned, well documented, not live, and not officially supported.
This page describes a data tool and is not betting advice.
When to choose something else
Choose a supported commercial source when you need live in-game data, contractual uptime, or clear commercial usage terms. Choose the community packages for research, historical modelling, learning, and weekly analysis, where their cleaning and documentation save a great deal of work.
Frequently asked questions
- What is nfl_data_py?
- An open-source Python package that loads NFL data published by the nflverse community project into pandas DataFrames. It covers play by play, weekly player statistics, schedules, rosters, identifier mappings, and more. It downloads prebuilt files rather than querying a live official API.
- Is nfl_data_py real time?
- No. It downloads data files that nflverse builds and publishes, so freshness follows the project's publishing schedule rather than live game events. It suits historical and weekly analysis. Live in-game work needs a real-time source, typically a commercial provider. Keep dated copies of anything loaded, since published files can be rebuilt.
- What is the difference between nfl_data_py and nflreadpy?
- Both load data from the nflverse project. nflreadpy is the newer package, and nflverse has pointed users toward it for new work. Check each repository for current maintenance status before starting a project and follow the current recommendation. The underlying data and column definitions are the same family either way.
- Are expected points columns in nflverse play by play reliable?
- They are well-regarded model estimates, not observed facts. They come from models trained by the project and can change when those models are updated, so record which data release an analysis used and treat those columns as inputs with provenance.