NFL play-by-play API
Every play of an NFL game, live or final, in order, with the play text, type, clock, period and score after the play. Page through a full game, or have each new play pushed to you.
Data is aggregated from public sources and is typically 20-30 seconds behind live play (about 1 second after our source). There is no SLA.
Endpoint
- GET/api/v1/sports/football/leagues/nfl/events/{eventId}/plays
Live NFL example
Request
curl -H "Authorization: Bearer $RSA_API_KEY" \
"https://www.realtimesportsapi.com/api/v1/sports/football/leagues/nfl/events/401873037/plays?limit=3"Response captured from live data at 2026-11-07 13:48 UTC (refreshed every few minutes). Long arrays are trimmed; meta.rateLimit values are illustrative for a Free key. Plays from Jacksonville Jaguars at Baltimore Ravens.
Response
{
"success": true,
"data": [
{
"id": "4018730371",
"sequenceNumber": "100",
"text": "GAME",
"shortText": "Game",
"alternativeText": "GAME",
"type": {
"id": "70",
"text": "Coin Toss"
},
"period": 1,
"clock": {
"value": 900,
"displayValue": "15:00"
},
"homeScore": 0,
"awayScore": 0,
"scoringPlay": false,
"scoreValue": 0,
"situation": {
"down": 0,
"distance": 0,
"yardLine": 0,
"yardsToEndzone": 0
},
"endSituation": {
"down": 0,
"distance": 0,
"yardLine": 0,
"yardsToEndzone": 65
},
"yardsGained": 0,
"athletes": [],
"priority": false,
"modified": "2026-11-06T04:24Z"
},
{
"id": "40187303741",
"sequenceNumber": "4100",
"text": "J.Moody kicks 65 yards from BLT 35 to JAX 0. J.Cameron pushed ob at JAX 23 for 23 yards (J.Higgins).",
"shortText": "Jake Moody 65 Yd Kickoff Josh Cameron 23 Yd Kickoff Return",
"alternativeText": "J.Moody kicks 65 yards from BLT 35 to JAX 0. J.Cameron pushed ob at JAX 23 for 23 yards (J.Higgins).",
"type": {
"id": "53",
"text": "Kickoff",
"abbreviation": "K"
},
"period": 1,
"clock": {
"value": 900,
"displayValue": "15:00"
},
"wallClock": "2026-11-06T01:16:48Z",
"homeScore": 0,
"awayScore": 0,
"scoringPlay": false,
"scoreValue": 0,
"situation": {
"down": 0,
"distance": 0,
"yardLine": 35,
"yardsToEndzone": 65
},
"endSituation": {
"down": 1,
"distance": 10,
"yardLine": 77,
"yardsToEndzone": 77
},
"yardsGained": 23,
"athletes": [
{
"id": "4372066",
"name": "Jake Moody",
"displayName": "Jake Moody",
"shortName": "J. Moody",
"position": "PK",
"team": {
"id": "33"
},
"role": "kicker",
"type": "kicker",
"order": 1
},
{
"id": "4879194",
"name": "Josh Cameron",
"displayName": "Josh Cameron",
"shortName": "J. Cameron",
"position": "WR",
"team": {
"id": "30"
},
"role": "returner",
"type": "returner",
"order": 2
},
{
"id": "4565350",
"name": "Jay Higgins IV",
"displayName": "Jay Higgins IV",
"shortName": "J. Higgins IV",
"position": "LB",
"team": {
"id": "33"
},
"role": "tackler",
"type": "tackler",
"order": 3
}
],
"priority": false,
"modified": "2026-11-06T04:24Z"
},
{
"id": "40187303769",
"sequenceNumber": "6900",
"text": "(Shotgun) T.Lawrence pass short right to T.Koziol to JAX 27 for 4 yards (T.Simpson).",
"shortText": "Trevor Lawrence Pass Complete for 4 Yds to Tanner Koziol",
"alternativeText": "(Shotgun) T.Lawrence pass short right to T.Koziol to JAX 27 for 4 yards (T.Simpson).",
"type": {
"id": "24",
"text": "Pass Reception",
"abbreviation": "REC"
},
"period": 1,
"clock": {
"value": 894,
"displayValue": "14:54"
},
"wallClock": "2026-11-06T01:17:29Z",
"homeScore": 0,
"awayScore": 0,
"scoringPlay": false,
"scoreValue": 0,
"situation": {
"down": 1,
"distance": 10,
"yardLine": 77,
"yardsToEndzone": 77,
"downDistanceText": "1st & 10 at JAX 23",
"possessionText": "JAX 23"
},
"endSituation": {
"down": 2,
"distance": 6,
"yardLine": 73,
"yardsToEndzone": 73
},
"yardsGained": 4,
"athletes": [
{
"id": "4360310",
"name": "Trevor Lawrence",
"displayName": "Trevor Lawrence",
"shortName": "T. Lawrence",
"position": "QB",
"team": {
"id": "30"
},
"role": "passer",
"type": "passer",
"order": 1
},
{
"id": "4917427",
"name": "Tanner Koziol",
"displayName": "Tanner Koziol",
"shortName": "T. Koziol",
"position": "TE",
"team": {
"id": "30"
},
"role": "receiver",
"type": "receiver",
"order": 2
},
{
"id": "4430831",
"name": "Trenton Simpson",
"displayName": "Trenton Simpson",
"shortName": "T. Simpson",
"position": "LB",
"team": {
"id": "33"
},
"role": "tackler",
"type": "tackler",
"order": 3
}
],
"priority": false,
"modified": "2026-11-06T04:24Z"
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 3,
"total": 167,
"totalPages": 56,
"hasNextPage": true,
"hasPreviousPage": false
},
"rateLimit": {
"limit": 125,
"remaining": 124,
"reset": 1796083200000
}
}
}Code samples
curl
curl -H "Authorization: Bearer $RSA_API_KEY" \
"https://www.realtimesportsapi.com/api/v1/sports/football/leagues/nfl/events/401873037/plays?limit=3"JavaScript (fetch)
const res = await fetch("https://www.realtimesportsapi.com/api/v1/sports/football/leagues/nfl/events/401873037/plays?limit=3", {
headers: { Authorization: `Bearer ${process.env.RSA_API_KEY}` }
});
const { success, data, meta } = await res.json();
console.log(data, meta.rateLimit);Python (requests)
import os, requests
res = requests.get(
"https://www.realtimesportsapi.com/api/v1/sports/football/leagues/nfl/events/401873037/plays?limit=3",
headers={"Authorization": f"Bearer {os.environ['RSA_API_KEY']}"},
timeout=10,
)
body = res.json()
print(body["data"])MCP prompt (Claude, Cursor, ChatGPT)
Using the Realtime Sports MCP server (https://www.realtimesportsapi.com/api/mcp), call get_plays with sport "football" and league "nfl" and pick a finished game from get_events and summarize its scoring plays for NFL.Connect the hosted MCP server first: setup guide. Each tool call counts as one API call.
Each request above is 1 call. Free covers 125 calls a month after a 1,000-call first month, at 1 request/second. Starter is $29/month for 10,000 calls (about 333 a day) plus webhooks and WebSocket, so you stop polling for changes; 7-day free trial. Compare plans
Fields
| Field | Type | Notes |
|---|---|---|
| id | string | |
| sequenceNumber | string | |
| text | string | |
| shortText | string | |
| alternativeText | string | |
| type | object | |
| period | integer | |
| clock | object | |
| wallClock | string | |
| homeScore | integer | |
| awayScore | integer | |
| scoringPlay | boolean | |
| scoreValue | integer | |
| scoringType | string | |
| situation | object | |
| endSituation | object | |
| yardsGained | integer | |
| teamId | string | |
| athletes | PlayAthlete[] | |
| priority | boolean | |
| modified | string |
Rate limits and pricing
| Plan | Price | Calls | Rate | WebSocket | Webhooks |
|---|---|---|---|---|---|
| Free | $0 | 125/mo (1,000 first 30 days) | 1/s | 500 msgs/mo | No |
| Starter | $29/mo ($290/yr) | 10,000/mo | 5/s | Shares monthly pool | Shares monthly pool |
| Growth | $49/mo ($490/yr) | 25,000/mo | 10/s | Shares monthly pool | Shares monthly pool |
| Pro | $99/mo ($990/yr) | 50,000/mo | 20/s | 100,000 msgs/mo | 25,000/mo |
| Business | $179/mo ($1,790/yr) | 150,000/mo | 40/s | 300,000 msgs/mo | 75,000/mo |
| Scale | $299/mo ($2,990/yr) | 500,000/mo | 100/s | 500,000 msgs/mo | 100,000/mo |
Every successful REST call counts as one call. Over the limit you get HTTP 429 with a Retry-After header. No SLA. Full pricing.
FAQ
- Is there a free NFL play-by-play API?
- Yes. A free key (no card) includes every endpoint and league: 1,000 calls in the first 30 days, then 125 a month at 1 request per second. Paid plans start at $29/month for 10,000 calls and add webhooks and WebSocket.
- Can I get NFL plays pushed instead of polling?
- On paid plans, each new play is also pushed to you: webhooks send event.play and the WebSocket stream sends event_play, so you don't have to poll the plays endpoint during a game.
- How far behind live is the play-by-play?
- Data typically runs 20-30 seconds behind live play, so it suits apps, alerts, dashboards and bots, not in-play betting.