American Football Stats API: How to Get NFL and College Data Into WordPress
Every guide to building a football site starts in the wrong place. They open with themes, show you a nice scoreboard layout, and pick a plugin by the end of the first screen. Then you install it and discover the real job: something has to put 285 NFL games, 32 team records and roughly 17,000 player stat lines into your database, every week, without you typing them. That job belongs to an American football stats API, and picking the wrong one is where these projects die.
That’s the part I want to talk about. Not the theme – the theme is the easy half, and I’ve already written about choosing your first WordPress theme.
I spent a day testing the data sources before touching WordPress at all, and I’d tell anyone starting a football site to do the same. Some of what I found contradicts what’s written about these feeds, including on the vendors’ own pages.
Where does American football data actually come from?
There is no free official NFL feed. The league doesn’t publish one, and neither does the NCAA. Every football stats site you’ve ever used is buying data from a middleman, pulling it from a community dataset, or reading an endpoint that was never meant to be public.
For American football specifically, that gives you five realistic routes. Three are free.
What each American football stats API actually covers
I tested all of these. Here’s the honest scorecard:
| Route | Cost | NFL player stats | College player stats | Other leagues | Documented |
|---|---|---|---|---|---|
| ESPN app endpoints | Free, no key | Yes, full | Yes, full | UFL yes; CFL and XFL dead | No |
| nflverse CSV releases | Free, no key | Yes, bulk download | No | No | Yes |
| CollegeFootballData | Free, key required | No | Yes | No | Yes |
| American football only, paid | $9.99/mo | Yes | Yes | Scores only | Yes |
| Eight sports incl. football, paid | $19.99/mo | Yes | Yes | Scores only | Yes |
Now the detail, because the table hides the interesting parts.
The free option nobody advertises
ESPN’s app endpoints are open. You can paste this into your browser address bar right now and get real JSON back:
https://site.api.espn.com/apis/site/v2/sports/football/college-football/scoreboard?dates=20250830
That returned 62 college football games for a single Saturday when I tried it, in a 938 KB response. The NFL equivalent returned 13 games for a Sunday in 113 KB.
Scores are the easy part though. The real question is player stats, and this is where I expected to hit a wall. I took a finished game – Texas at Ohio State, game ID 401752677 – and asked for its summary:
https://site.api.espn.com/apis/site/v2/sports/football/college-football/summary?event=401752677
398 KB came back with a full box score. Ten stat categories per team: passing, rushing, receiving, fumbles, defensive, interceptions, kick returns, punt returns, kicking, punting. Twenty defensive players listed for one team alone. That’s a complete college football box score for free, with no account.
So why does anyone pay? Three reasons, and they’re good ones. ESPN publishes no documentation, promises nothing, and can change or remove any of it tomorrow without telling you. There’s no rate limit published, which means there’s also no rate limit you’re allowed to rely on.
The third reason is the one people skip. ESPN’s terms don’t grant you permission to republish this data. A hobby site and a commercial one are in very different positions there, and that’s a question for you, not for me.
The free route that isn’t an API at all
nflverse is the one I’d have wanted to know about first, and it works nothing like the others. There’s no API and no key – it publishes finished datasets as CSV files on GitHub, and you download them.
I pulled the 2025 weekly player stats file. It came back as 8.3 MB containing 19,422 rows and 150 columns per row, covering the regular season and the playoffs. Completions, attempts, passing yards, air yards, sacks suffered, fumbles lost – the kind of depth you’d normally be paying for.
For a WordPress site this is a genuinely different proposition. A CSV import is far less code than a scheduled API loop, and there’s no rate limit to design around because there are no requests. The tradeoff is timing: a dataset that refreshes on the maintainers’ schedule is fine for a season archive or a stats reference, and useless if you want a live scoreboard on Sunday afternoon.
It’s NFL only. No college, no CFL.
The free college-only option
CollegeFootballData does for college what nflverse does for the NFL, except it is a proper API. You register for a free key, and requests without one are refused – I tried, and got a 401 telling me exactly that.
It’s documented, it’s purpose-built for college football, and it goes far deeper than scores into recruiting, rankings and advanced analytics. If college is your whole site, start here rather than with a paid multi-sport feed you’ll use 5% of.
What $10-20 a month buys
The paid options I looked at sit at two price points. One provider charges $9.99 a month for American football alone, including college, with a 15,000 requests per day ceiling. Another charges $19.99 a month for eight sports at once with unlimited requests, throttled to 6 per second.
Both have a free tier at 50 requests a day. That number sounds usable until you do the arithmetic further down. It isn’t – it’s a tasting menu, not a starter plan.
What you’re buying at that price isn’t more football data than ESPN gives away. I got a fuller UFL box score from the free endpoint than from the paid one. You’re buying documentation, a stable contract, and someone to email when a field changes shape without warning.
For a weekend project that’s easy to abandon, free is genuinely fine. For a site you intend to run for three seasons, paying twenty dollars so a schema change becomes somebody else’s problem is the cheapest insurance you’ll buy all year.
Always test a finished game, not next Sunday’s
This is the single mistake I’d most like to save you from, because it cost me a wrong answer before I caught it.
When you’re checking whether a feed carries player stats for your league, the natural thing is to grab the next fixture and request its stats. Don’t. An unplayed game has no box score, so the API correctly returns nothing – usually HTTP 204, “no content.” That response is byte-for-byte identical to what you’d get from a league the provider doesn’t cover at all.
So the test tells you nothing, and it tells you nothing in a way that looks exactly like a definite answer. I nearly wrote off a league on that basis.
Pick a game that finished. Check the game’s status field says the game is over before you trust anything you learn from it. Then run your coverage test, and the answer means something.
A 200 OK doesn’t mean the league is still covered
Here’s the second trap, and it’s nastier because the response looks perfect.
I asked ESPN’s CFL endpoint for its current scoreboard. HTTP 200, valid JSON, one game listed. Except the game was the 2022 Grey Cup – Toronto at Winnipeg, played in November 2022.
Every 2025 and 2026 date I tried came back with zero games. And when I asked for the box score of the one game it did list, the server returned 502 three times in a row.
The XFL endpoint tells the same story frozen at May 2023, which is roughly when that league merged into the UFL.
Nothing in any of those responses said “this league is no longer maintained.” The status code was 200. The JSON parsed. If I’d wired that up on a Monday and only checked that data arrived, I’d have shipped a CFL page that quietly served three-year-old results forever.
Check the dates in the response, not just the status code. Ask for a game from last week and confirm you get last week’s game back.
The coverage map isn’t what the internet says
I want to flag something specific, because it’s the reason I’d tell you to test rather than read.
Every written source I could find on the paid feeds said American football player stats meant the NFL and nothing else. College was listed as scores-only. That was true in April 2026. It isn’t true now – I probed a finished college game on a paid provider and got a full lineup response with 40 and 32 players on the two teams, across all three NCAA divisions those feeds carry: FBS, FCS and interdivisional.
The coverage had expanded and the documentation hadn’t caught up. Meanwhile the smaller leagues went the other way. The CFL, the UFL and the European League of Football all returned 204 for both lineups and statistics on that same paid provider – scores, schedules, standings and scoring summaries, but no player data at all.
And in a genuinely funny twist, ESPN’s free endpoint gave me a complete UFL box score, 10 stat categories per team, for a finished 2026 game the paid feed had no player data for. Free beat paid, for that one league, on the day I checked.
The lesson isn’t “use the free one.” It’s that nobody’s coverage table is reliable, including the vendor’s own, and the check takes four minutes.
How many API calls does an NFL season really cost?
This is the number that decides your plan, and almost nobody publishes it.
A full NFL season is 285 games including the playoffs. Importing it – fixtures, results, box scores, standings refreshes – lands around 1,200 to 1,400 requests. That’s the whole season. It fits comfortably inside a $10 plan, and it would take you 24 days on a 50-per-day free tier, assuming you never made a mistake and never re-ran anything.
College is the one that surprises people. FBS alone plays roughly three times the NFL’s schedule, and if you want FCS too you’re multiplying again. Your bill scales with games played, not with how much you care about the league – which is worth remembering before you tick every division on the import screen.
Where a football stats site stores its data in WordPress
Assume you’ve got the data. Now it has to go somewhere, and this is where WordPress-specific judgement starts to matter.
The tempting move is to make every game a post, or a custom post type. It works beautifully for 20 games. At 285 NFL games, each with two teams and roughly 60 player stat lines, you’re looking at tens of thousands of rows in wp_postmeta – and wp_postmeta is the slowest table in WordPress to query in the ways a stats site needs to query it. Sorting quarterbacks by passing yards is a trivial database question and an awful postmeta question.
Anything built for this job seriously will use its own database tables. If you’re evaluating a plugin, that’s a fair thing to ask about, and the answer tells you a lot about whether it was built for 20 games or 2,000.
Storage is worth a thought too. One college football box score was 398 KB of JSON, and that nflverse season file was 8.3 MB. Decide early whether you’re keeping raw payloads or only the fields you actually display.
Never call the API when someone loads the page
If you take one engineering rule from this article, take this one.
I timed ESPN’s NFL scoreboard endpoint eight times. Median response: 0.100 seconds. Fastest 0.067, slowest 0.569.
That slowest number is the one that matters. If your page fetches live data while a visitor waits, your page is now as slow as the API’s worst day – half a second of blank screen, added to everything your site already does. And that’s before the feed has a real outage, which on a Sunday afternoon is exactly when it will. If your site is already sluggish, my notes on why your WordPress site is slow apply here too.
The right shape is boring: a scheduled job fetches the data, stores it in your own tables, and the page reads only from your database. Visitors never wait on somebody else’s server.
One WordPress-specific catch. WP-Cron isn’t a real scheduler – it only runs when somebody visits your site. A new football site with no traffic in August will simply not update, and you’ll assume the feed broke.
Set DISABLE_WP_CRON to true and drive it from a real system cron job at your host. Most decent hosts have a one-click setting for it.
Which plugin should you actually use?
The last two sections describe a job: own the tables, own the scheduled import, and keep the API away from your visitors’ page loads. You can do that work yourself or pay someone to have already done it. Here’s who’s doing it.
SportsPress is the biggest name in WordPress sports plugins, and it’s a genuinely good league manager if you run the competition yourself. Its import path is CSV – you go to Tools, pick an importer, and hand it a file. There’s no API connection at all, so for a pro or college league you’re still the data entry, just via a spreadsheet first.
JoomSport does connect to an API. The integration is with Statorium, and it sits in the paid edition rather than the free plugin, with American football on the supported list. Whether Statorium carries the exact league and the player-level detail you want is the same question this whole article is about – probe a finished game before you pay for anything.
Sports API Hub is ours. It imports from both providers I tested here, stores everything in its own tables, and owns the scheduling. The cost that isn’t on the pricing page: you need the plugin and an API subscription on top of it, because the free 50-requests-a-day tier won’t import a season.
Or no plugin at all. If you only want the NFL and you don’t need live scores, the nflverse CSVs are free, complete, and a plain import job. No subscription, no API key, nothing to renew. For a season-archive site that’s genuinely the right answer, and I’d rather you spent nothing than spent something you didn’t need.
None of these decides the question the rest of this article is about. Whatever you pick still sits on top of a data source, and the source is what determines whether your league has box scores at all. Check that first.
So what would I actually do?
Test first, in the browser, before you spend anything. Pick the exact league you care about, find a game that finished last week, and ask two questions: does the score come back, and does a player box score come back? Then check the dates in the response are recent.
If you only want the NFL and you don’t need live scores, look hard at the nflverse CSVs before you pay anyone. If college is your site, start with CollegeFootballData. If you want live in-game updates across the NFL and college at once, that’s when the $10-20 a month starts earning its keep.
That single check would have caught every trap in this article. It’s the difference between a football stats site and a site that displays the 2022 Grey Cup forever.
Frequently asked questions
Is there a free NFL stats API?
There’s no official free one from the NFL. ESPN’s undocumented app endpoints return NFL scores and box scores without a key, and nflverse publishes full season player stats as free CSV downloads. Neither comes with a guarantee, and ESPN’s terms don’t grant republishing rights, so read them if your site is commercial.
Can I build a college football stats site?
Yes, and it got easier during 2026. Full NCAA box scores are available from ESPN’s free endpoints, from the free CollegeFootballData API, and from the paid providers across FBS, FCS and interdivisional games. Guides published before mid-2026 mostly say college is scores-only, and they’re now out of date.
Does any API cover the CFL, UFL or XFL properly?
Only partly, and this is the weakest spot in American football data. The paid feeds I tested return 204 for CFL, UFL and European League of Football player stats – scores and standings only. ESPN carries a full UFL box score for free, but its CFL feed has been frozen since the 2022 Grey Cup and its XFL feed since May 2023.
Why does my football API return 204 with no data?
Almost always because you asked about a game that hasn’t been played. A 204 on an upcoming fixture is normal and means nothing about coverage. Re-run the same request against a game that finished before concluding the league isn’t supported.
How much does an American football API cost?
Between $10 and $20 a month at the entry tiers I looked at, for football alone or a multi-sport bundle. Free tiers around 50 requests a day exist but won’t import a season – the NFL alone is 1,200 to 1,400 requests.
Do I need a plugin, or can I do this myself?
Either works, and the data questions in this article apply the same way to both. If you write it yourself you own the cron job, the tables and the parsing. If you use a plugin you’re paying someone to own those, which is usually the better trade – just check it stores data in its own tables rather than in wp_postmeta, and read my notes on updating plugins without breaking your site before you depend on one.