Why this is hard
The problem with cricket data
Cricket is a per-innings game scored in a per-match world. Almost every free cricket source gives you a result and a total, which is precisely the resolution at which cricket stops being interesting — the question is never who won, it is how the innings was built.
- A total tells you nothing about tempo. 160 off 20 overs built on 5 boundaries is a different innings from the same 160 built on 14, and only ball-and-boundary detail separates them.
- Strike rate needs balls faced, not just runs — a column most scraped sources drop because it is inside the scorecard table rather than the result header.
- Cricket has three formats with different arithmetic. A T20 strike rate and a Test strike rate are not comparable, so any real dashboard has to know which competition an innings came from.
- Scorecard scraping is per-match by construction. Building a career view means fetching hundreds of pages and reconciling player names across them.
Path 1 · recommended
Have your AI agent build it
Our MCP server is live. Point any MCP client — Claude Code, Claude Desktop, Cursor, or your own agent — at it, and the model can read our data directly while it writes your app. You describe the dashboard; it queries, shapes and renders it.
1. Connect the MCP server
Add the server in your MCP client and sign in with your Big Balls account. Your client registers itself and handles the token exchange — there is no key to copy.
{
"mcpServers": {
"bigballs-sports-data": {
"url": "https://mcp.bigballsdata.com/mcp"
}
}
}2. Tools your agent gets
get_matchesLive, upcoming or historical matches for a sport or league.
get_player_statsPer-player career or per-season totals and per-game rates.
get_coverageMachine-readable map of what we hold and what we do not.
3. Ask for what you want
Paste this at your agent. It is written to make the model check coverage before it designs anything, which is what stops it inventing a field we do not serve.
Build me a cricket batting-analysis dashboard.
Use the Big Balls Sports Data MCP server. Start with get_coverage for
cricket so you know what is actually held before you design anything.
Then, for a competition I pick from GET /v1/cricket/series, pull recent
finished matches and their scorecards, and build a table of batting
innings: player, runs, balls, strike rate, fours, sixes, and which
competition the innings came from.
Rank by strike rate with a minimum-balls filter so a 12-ball cameo does
not top the table. Group the output by format — T20, ODI and Test
strike rates are not comparable.What the agent cannot reach
The MCP server exposes five read tools and none of them is cricket-scorecard-specific: the scorecard, series and live-state endpoints are REST-only today. An agent can discover coverage, matches and player stats through MCP, then call the REST endpoints below directly for the innings detail. Treat the agentic path as the scaffolding and the REST calls as the data.
Path 2 · hand-coded
Build it yourself
Four calls, no key juggling, no name reconciliation. Every response below was captured from production on 2026-08-16 and trimmed only for length.
- 01
Pick a competition
Cricket is organised by competition, not by league table. Start here — this endpoint derives its list from matches we actually hold, so a competition with zero games can never appear.
List the competitions we holdbashcurl -s "https://api.bigballsdata.com/v1/cricket/series" \ -H "x-api-key: $BBS_KEY" | jq '.data[:3]'Real response, trimmed
jsonjson[ { "id": "ace09e03-…", "name": "ODI Cricket", "match_count": 3213, "first_match": "2002-06-27T00:00:00.000Z", "latest_match": "2026-12-07T11:30:00.000Z" }, { "id": "0742154d-…", "name": "IPL", "match_count": 1263, "first_match": "2008-04-18T00:00:00.000Z", "latest_match": "2026-05-31T14:00:00.000Z" }, { "id": "f9c523c8-…", "name": "Test Cricket", "match_count": 917, "first_match": "2001-12-19T00:00:00.000Z", "latest_match": "2026-11-23T08:00:00.000Z" } ] - 02
Fetch recent matches
Filter the match list to your competition. Results come back most-recent-first, so the first page is the current form window.
Recent matches in a competitionbashcurl -s "https://api.bigballsdata.com/v1/cricket/matches?series=IPL&limit=5" \ -H "x-api-key: $BBS_KEY" | jq '.data[0] | {id, league, home: .home.name, away: .away.name, status, score}'Real response, trimmed
jsonjson{ "id": "6b2e6ed1-…", "league": "T20I Cricket", "home": "Trent Rockets", "away": "Manchester Super Giants", "status": "finished", "score": { "home": 158, "away": 162 } } - 03
Pull the scorecard
This is the layer that makes a cricket app worth building: per-innings batting and bowling with balls faced, boundaries and strike rate already computed.
Per-innings batting and bowlingbashcurl -s "https://api.bigballsdata.com/v1/cricket/matches/$MATCH_ID/scorecard" \ -H "x-api-key: $BBS_KEY" | jq '.data.innings[0].batting[0]'Real response, trimmed
jsonjson{ "innings_number": 1, "player_id": "3d0212ca-8a81-5ff3-a72a-aeb7e501fd5a", "player_name": "LG Pretorius", "runs": 52, "balls": 28, "fours": 5, "sixes": 3, "strike_rate": "185.71" } - 04
Rank the innings
Sort by strike rate with a minimum-balls floor, and keep the competition on every row so you never compare a T20 innings against a Test one.
Build the tabletypescripttype Innings = { player_name: string; runs: number; balls: number; fours: number; sixes: number; strike_rate: string | null; }; const res = await fetch( `https://api.bigballsdata.com/v1/cricket/matches/${matchId}/scorecard`, { headers: { 'x-api-key': process.env.BBS_KEY! } }, ); const { data, meta } = await res.json(); // meta.available is false when we hold no innings for this match — show that, // never an empty table that reads as "nobody scored". if (!meta.available) return { rows: [], note: meta.note }; const rows = data.innings .flatMap((i: { batting: Innings[] }) => i.batting) .filter((b: Innings) => b.balls >= 10) .map((b: Innings) => ({ ...b, boundaryPct: Math.round(((b.fours * 4 + b.sixes * 6) / b.runs) * 100), })) .sort((a, b) => Number(b.strike_rate ?? 0) - Number(a.strike_rate ?? 0));
Reference
Every endpoint this tutorial uses
All on the gateway at api.bigballsdata.com. Verified against production on 2026-08-16.
| Method | Path | Returns | Why you need it | Plan |
|---|---|---|---|---|
| GET | /v1/cricket/series | 765 competitions with match counts and date ranges | The entry point. Derived from matches we hold, so it cannot advertise a competition with no games. | Free |
| GET | /v1/cricket/matches | Cricket matches, most-recent-first, filterable by series and date | Gets you the match ids the scorecard endpoint needs. | Free |
| GET | /v1/cricket/matches/{id}/scorecard | Per-innings batting and bowling — runs, balls, fours, sixes, strike rate, dismissal | The spine of this tutorial. 421,886 batting and 293,453 bowling rows across 22,898 finished matches. | Free |
| GET | /v1/cricket/matches/{id}/state | Live innings state — overs, runs, wickets, target, run rates | Turns the dashboard live during a match, and says so honestly when it cannot.Recorded only while a match is in progress. Cricket is between fixtures here — the next scheduled match is 2026-11-15 — so this returns available: false today. That is the correct answer, not an outage. | Free |
| GET | /v1/cricket/players/{id} | Player profile aggregated from real scorecard rows | Turns a player_id from a scorecard into a career view without name matching. | Free |
| GET | /v1/teams/{id}/form | Recent results with scores, opponents and W/L per competition | The modelled layer — rolling team form, computed rather than collected. | Solo |
Pricing, honestly
Where the free tier stops
Everything above runs on a free key: every competition, every scorecard, the full 24-year archive. What the free tier does not give you is the computed layer — the numbers we derive rather than collect. For cricket that layer is team form.
Free key
// Free key — GET /v1/teams/:id/form
{
"error": { "code": "forbidden",
"message": "Access to team form requires the Solo plan or higher." },
"suggested_fix": "Solo unlocks rolling form across recent results, computed per team. …/pricing"
}Solo
// Solo — GET /v1/teams/:id/form
{
"date": "2026-08-16T17:00:00.000Z",
"home": "Trent Rockets",
"away": "Manchester Super Giants",
"home_score": 158,
"away_score": 162,
"result": "L",
"competition": "T20I Cricket"
}- Rolling team form — recent results with scores, opponent and competition, already sequenced. The column that turns a scorecard browser into an analysis tool.
- Solo is $19/month and also lifts the free tier’s 1,000 requests/day to 10,000 — which matters here, because a scorecard-per-match build is request-hungry by nature.
- Honest scope: cricket teams have no Elo rating and cricket players are not tiered yet, so those Solo endpoints return nulls for this sport. They are not part of this build and are not sold as if they were.
More tutorials
Other build guides
Known gaps
What is not here yet
Stated plainly, because finding out mid-build is worse than knowing now.
- No Elo ratings or model win probabilities for cricket teams — /v1/teams/:id/elo returns a null rating for this sport.
- No player tiers for cricket — the tier endpoint answers with reason: "sport not yet tiered".
- Ball-by-ball commentary is not offered at all. The innings-level scorecard is the finest resolution we hold.
- Live innings state exists and is wired, but cricket is between fixtures until 2026-11-15, so it reports available: false today.
Questions
- How far back does the cricket data go?
- Twenty-four years, and it varies by competition: Test cricket to 2001, ODI to 2002, IPL to 2008. GET /v1/cricket/series returns first_match and latest_match per competition so you can check the range before you build against it, rather than discovering the edge in production.
- Is the scorecard data actually complete, or just recent matches?
- 421,886 batting innings and 293,453 bowling spells across 22,898 finished matches. It is the deepest layer we hold for cricket. Matches we do not have innings for return meta.available: false rather than an empty innings array, so your code can tell "no data" from "no runs".
- Can I build a fantasy cricket app on this?
- Partly, and it is worth being direct about the limit. The per-innings scoring data is there and is deep enough to compute fantasy points yourself. What is not there is the modelled layer other fantasy builds lean on — cricket has no Elo ratings and no player tiers today. If you want the projection layer handed to you rather than derived, basketball and hockey are further along.
- Why is live match state empty?
- Because no cricket match is in progress. Innings state is recorded only while a match is being played, and the next scheduled fixture in our data is 2026-11-15. The endpoint reports available: false with a note rather than returning a zeroed-out innings, so an empty response is never mistaken for a 0/0 score.
- Do I need the MCP server, or can I just call the REST API?
- Either, but for cricket specifically the REST API is the complete surface. The MCP server exposes five read tools and none of them is cricket-scorecard-specific, so an agent can scaffold from coverage and matches but will call the REST scorecard endpoint for the innings detail.