Application source for nflmeta.org — a curated NFL reference database and public API.
A team page carries the season record, offensive, defensive and special-teams splits, the venue, the current coaching tenure, and every Pro Bowl selection — all of it served by the same endpoints the API exposes.
The developer reference documents 171 OpenAPI operations across 24 endpoint groups, and the evaluation pages are readable without an account.
Coverage is not uniform across the league's history, and it is worth knowing which parts reach back how far before building against it:
| Data | From |
|---|---|
| Rosters, franchise and team-name history | 1920 |
| Draft picks | 1965 |
| Games, schedules, standings, playoffs | 1966 |
| Player season and career statistics | 1966 |
| Punting season stats | 1966 |
| Defensive snap counts | 2012 |
| Advanced splits (air yards, YAC, coverage) | 2018 |
| Kicking season stats | 2025 |
Statistics before 1966 are not held at all, so a career spanning the boundary is reported only from 1966 on. The advanced splits start later than the core stats for the same reason, so a career crossing 2012 or 2018 is reported from that boundary on for those fields only.
The Next.js application and the published API contract: route handlers, data access, the public site, the TypeScript and Python SDK packages, and the MCP server.
It is not a runnable copy of NFLMeta. The database and the pipeline that assembles and curates it are the product, and neither is included here. There are no data files and no import scripts.
The schema is included, so you can stand the application up against an empty database and see it work:
createdb nflmeta
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f sql/schema.sqlThat gives you every table the application queries and no rows. Pages render, endpoints answer, and everything comes back empty.
The data is available through the public API rather than as a download:
- Docs: https://nflmeta.org/api-docs
- Contract:
docs/openapi.yaml - Keys: https://nflmeta.org/sign-up
curl -H "X-NFLMeta-Key: $NFLMETA_API_KEY" \
"https://nflmeta.org/api/v1/teams/KC/roster"Every response carries rate-limit headers and, where relevant, a data_status
block describing when that slice was last refreshed.
Page size and how far a result set can be paged are both plan-dependent:
| Plan | Max page size | Result window |
|---|---|---|
| Free | 100 | 1,000 |
| Builder | 250 | 10,000 |
| Pro | 500 | 50,000 |
| Team | 1,000 | unrestricted |
Paging past the window returns 400 invalid_request. Narrow the query with
filters — ask for one team's roster rather than every row — or move to a plan
with a larger window.
The window bounds one result set; it does not bound how many result sets a key may ask for. The control that does is a monthly row allowance, counted separately from the request quota, where every record in a response counts including the single record a detail endpoint returns:
| Plan | Requests / month | Rows / month | Per minute |
|---|---|---|---|
| Free | 5,000 | 25,000 | 20 |
| Builder | 75,000 | 250,000 | 120 |
| Pro | 250,000 | 2,500,000 | 500 |
| Team | 1,000,000 | unrestricted | 1,500 |
Exhausting either the request quota or the row allowance returns
429 rate_limit_exceeded. Remaining budget is reported on every response
through X-Monthly-Quota-Remaining and, where a row allowance applies,
X-Monthly-Row-Remaining. Current figures are on
https://nflmeta.org/pricing, which reads them from the running
configuration.
The API sends no CORS headers, so it cannot be called from browser JavaScript.
X-NFLMeta-Key is a secret and a browser would expose it. Call the API from
your own backend and have your frontend call that.
- TypeScript:
sdk/typescript - Python:
sdk/python
Both wrap the resource families, handle the X-NFLMeta-Key header, parse
rate-limit metadata, and expose a raw get(path, { query }) escape hatch for
routes added after the SDK was cut. Both are published: @nflmeta/sdk on npm and nflmeta on PyPI. Install them
rather than building from the source tree.
npm install @nflmeta/sdk
pip install nflmeta # requires Python 3.10 or newernpm install
npm run dev.env.example lists the environment the application expects. Apply
sql/schema.sql first; database-backed routes need those tables to exist.
npm run build # production build
npm run lint
npm run test:e2e # Playwright
npm run sdk:test
npm run mcp:testThe source in this repository is provided for reference. The NFL data served by nflmeta.org is not covered by it and is not licensed for redistribution or bulk extraction; see the API terms at https://nflmeta.org/terms.


