A play-by-play feed for your analytics stack
Analysts, data teams, media research and sports-tech products.
Keep one WebSocket subscribed to event_play and event_final and append every play to your warehouse. After each final, pull the full play list and box score over REST to reconcile. Schedules give you the game universe for a season.
Updated 2026-11-04. 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.
Coverage
Play-by-play: NFL, college football, NBA, MLB, NHL and 18 soccer competitions (soccer plays are match events: passes, shots, fouls, cards). Win probability series: NFL, college football and MLB. Box scores with player stats: NFL, college football, NBA and MLB. Verified on the dates shown on the endpoint pages.
Stream plays as they happen
Subscribe once per league. Every event_play message carries the game id, so you can append to a plays table keyed by game and play id. Opt in to event_play_corrected to replace plays the source later revises.
Node.js: append plays to your store
// Server-side only: your API key never ships to browsers or apps.
const res = await fetch('https://www.realtimesportsapi.com/api/websocket/auth', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.RSA_API_KEY}` }
});
const { data } = await res.json(); // data.url, data.token (valid 1 hour)
const ws = new WebSocket(`${data.url}?token=${data.token}`);
ws.onopen = () => {
for (const event of ['event_play', 'event_play_corrected', 'event_final'])
ws.send(JSON.stringify({ type: 'subscribe', event, filters: { sport: 'football', league: 'nfl' } }));
};
ws.onmessage = async (e) => {
const msg = JSON.parse(e.data);
if (msg.type === 'event_play' || msg.type === 'event_play_corrected') await upsertPlay(msg.data); // your warehouse
if (msg.type === 'event_final') await reconcile(msg.data.eventId);
};Reconcile and backfill over REST
After a final, one call returns every play and one returns the box score. For a season backfill, list games with the schedule endpoint and pull each completed game the same way.
Python: pull one completed game
import os, requests
BASE = "https://www.realtimesportsapi.com/api/v1/sports/football/leagues/nfl"
H = {"Authorization": f"Bearer {os.environ['RSA_API_KEY']}"}
def game(event_id):
plays = requests.get(f"{BASE}/events/{event_id}/plays", headers=H, timeout=20).json()["data"]
box = requests.get(f"{BASE}/events/{event_id}/boxscore", headers=H, timeout=20).json()["data"]
wp = requests.get(f"{BASE}/events/{event_id}/winprobability", headers=H, timeout=20).json()["data"]
return plays, box, wpRate and volume
Growth allows 10 requests per second and Pro 20, so a backfill of a few hundred games takes minutes. Responses include X-RateLimit-* headers; over a limit you get HTTP 429 with Retry-After.
Endpoints used
POST /websocket/authGET /sports/{sport}/leagues/{league}/events/{eventId}/playsGET /sports/{sport}/leagues/{league}/events/{eventId}/boxscoreGET /sports/{sport}/leagues/{league}/events/{eventId}/winprobabilityGET /sports/{sport}/leagues/{league}/seasons/{season}/schedule
Full reference: docs · OpenAPI · what each endpoint returns, by league
Plans
| 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 tracking or advanced (expected points) data?
- No. The feed is play-by-play, box scores, win probability for NFL, college football and MLB, schedules, rosters and injuries. Build advanced metrics on top of the plays.
- How far back does the data go?
- Completed games in the current data window are available over REST; there is no bulk historical archive download. Stream the current season to build your own history.
- Can I export to CSV?
- The API returns JSON. Schedule pages on this site offer JSON and CSV downloads for fixtures; for plays, write the JSON to your own tables.