# Basketball Scraper: Box Scores, Play-by-Play & Odds (`punkrecordsdata/basketball-match-stats-scraper`) Actor

Get basketball results, per-quarter team stats, player box scores, play-by-play, odds, rosters and standings for any team. Export to CSV, Excel, JSON, XML.

- **URL**: https://apify.com/punkrecordsdata/basketball-match-stats-scraper.md
- **Developed by:** [PunkRecordsData](https://apify.com/punkrecordsdata) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.20 / 1,000 match records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

<p align="center">
  <img src="https://api.apify.com/v2/key-value-stores/AAm3a1h3Z9nYfrvh9/records/banner" alt="PunkRecordsData" width="100%" />
</p>

## 🏀 Basketball Stats Scraper: Box Scores, Play-by-Play & Standings, PunkRecordsData

> 🚀 **Every NBA/EuroLeague team's games, full player box scores, play-by-play, betting odds, rosters and standings, in one run.** Real basketball intelligence with no login, no API key.

Scrape basketball data straight from Sofascore's own live API: game results with score by quarter, team stats broken out by full game and each individual quarter, a full per-player box score (points, rebounds, assists, shooting splits, plus-minus, efficiency rating), the point-margin-over-time curve for the whole game, every real scoring play, bookmaker odds, a team's full season roster, and conference/division standings. Give it a team name and pull their recent and upcoming games, or feed in match IDs directly.

Built for the [Apify platform](https://apify.com): schedule a run to track a team's games as they finish, or feed player box scores straight into a fantasy or performance-analysis model.

### 📋 What the Basketball Stats Scraper does

Give it a team name (like "Los Angeles Lakers") and it returns one row per game: opponent, tournament, round, score by quarter, and status. Turn on **Team statistics** for scoring/rebounds/shooting stats broken out by the full game AND each individual quarter. Turn on **Player box scores** for every player's full stat line, **Lineups** for starters vs bench, **Head-to-head record**, **Betting odds**, **Score margin graph** for the point-differential curve minute by minute, **Play-by-play** for every real scoring play, **Team roster** for the full season squad, and **Standings** for the conference/division table, each computed once per unique team or tournament, not once per game.

> 💡 **Why it matters:** most basketball scrapers on the market return a flat list of scores and stop there. This one also pulls player-level box scores, play-by-play and a score-margin graph, real depth most competitors don't expose, in the same run.

### 📊 Output

Real sample fields from a verified run against "Los Angeles Lakers", one of three record types identified by `recordType`.

**`match-record`** (primary, one row per game):

```json
{
  "homeTeam": "Orlando Magic",
  "awayTeam": "Los Angeles Lakers",
  "homeScore": 104,
  "awayScore": 105,
  "scoreByQuarter": [
    { "quarter": 1, "homePoints": 30, "awayPoints": 37 },
    { "quarter": 2, "homePoints": 35, "awayPoints": 25 }
  ],
  "statistics": [{ "period": "1Q", "group": "Scoring", "stat": "3 pointers", "home": "4/11 (36%)", "away": "3/9 (33%)" }],
  "boxScore": [{ "playerName": "Paolo Banchero", "points": 16, "rebounds": 5, "assists": 6, "plusMinus": -18, "rating": 7.1 }],
  "h2hRecord": { "homeWins": 4, "awayWins": 6 },
  "scoreGraph": [{ "minute": 1, "margin": -6 }]
}
```

**`roster-record`** (one row per unique player on a team's season roster):

```json
{ "teamName": "Orlando Magic", "playerName": "Desmond Bane", "position": "G", "heightCm": 196, "weightKg": 98, "country": "USA" }
```

**`standings-record`** (one row per team in a league table):

```json
{ "tournamentName": "NBA", "teamName": "Detroit Pistons", "position": 1, "wins": 60, "losses": 22, "percentage": 0.732 }
```

Every extra you don't enable returns `"Not Requested"` instead of an empty field, and data a game genuinely doesn't have returns `"N/A"`. You always know why a field is empty, never guess.

### ✨ Why choose this Actor

- **Player box scores, not just the final score.** Full per-player stat lines (points, rebounds, assists, shooting splits, plus-minus, efficiency rating), something most flat score-only scrapers don't touch.
- **Play-by-play included.** Every real scoring play in the game, with player, time and running score, verified real on an NBA fixture (115+ plays per game).
- **A score-margin graph.** The point-differential curve for the whole game, minute by minute, a genuinely distinct data shape no flat-score competitor exposes.
- **10 real data types, one run.** Match result, per-quarter statistics, box scores, lineups, head-to-head, odds, score graph, play-by-play, roster and standings, no need to run several different scrapers.
- **No login, no API key.** Nothing to expire or get rate-limited on your account.

### 📈 How it compares to alternatives

Measured against the closest published basketball actors on the Apify Store:

| Actor | Primary price | Billable events |
|---|---|---|
| Generic multi-sport scrapers (highest volume, 800-3,900 runs/30d) | $1.00-2.00/1k | 1 (flat score list) |
| Specialized basketball API actor (richest competitor, different source) | $15.00/1k | 14, several from a deeper stats source |
| **This Actor** | See Store pricing | **10** (match, statistics, box score, lineups, h2h, odds, score graph, play-by-play, roster, standings), all raw Sofascore source data |

### 🚀 How to use

1. Create a free [Apify account](https://console.apify.com). New accounts get $5 in free credit.
2. Open the Basketball Stats Scraper and enter a team name (e.g. "Los Angeles Lakers") or a Sofascore match ID.
3. Toggle on the extras you need: statistics, box scores, lineups, h2h, odds, score graph, play-by-play, roster, standings.
4. Click **Start** and wait for the run to finish.
5. Download your data as CSV, Excel, JSON or XML, or pull it via the API.

### 💼 Business use cases

**Fantasy sports & DFS tools**
Pull player box scores and rosters to power projections, lineup optimizers or fantasy scoring.

**Sports betting & odds comparison**
Track bookmaker odds alongside real box scores and score-margin curves for model backtesting.

**Sports media & content**
Feed live scores, box scores and standings into a live-blog, recap generator or stats widget.

**Performance analysis & scouting**
Use per-quarter team stats and play-by-play to study team tendencies and player performance trends.

### 🔌 Automating Basketball Stats Scraper

Connect this Actor to **Make**, **Zapier**, **Slack** or **Airbyte** to push new game results or box scores into a spreadsheet, database or channel automatically. Schedule a run after each game night to catch box scores as soon as they're final.

### 🌟 Beyond business use cases

**Research:** sports-analytics and biomechanics research using real box score and play-by-play data.
**Personal projects:** track your favorite team's games, box scores and standings automatically.
**Non-profit:** youth-sports or amateur-league stats tracking using the same Sofascore data model.
**Experimentation:** train win-probability or player-performance prediction models against real game data.

### 🤖 Ask an AI assistant about this scraper

Paste this Actor's Store page into ChatGPT, Claude or Perplexity and ask: "Does this basketball scraper include player box scores and play-by-play, or just final scores?" The README and input schema are structured so AI assistants can answer accurately from the page alone.

### ❓ Frequently Asked Questions

**Does this only return final scores, or also player stats?**
All 10: match result, per-quarter team statistics, player box scores, lineups, head-to-head, odds, score-margin graph, play-by-play, roster and standings, each an optional toggle.

**Which leagues does this cover?**
Any basketball league Sofascore covers, including NBA, EuroLeague and others. Coverage depth (statistics, box scores) depends on what Sofascore itself publishes for that league; major leagues like the NBA have the richest data.

**Do I need a team name, or can I use a specific game?**
Either works. A team name pulls that team's recent and upcoming games; a specific Sofascore match ID fetches just that game, bypassing search.

**Do I need an API key for Sofascore?**
No. Every field comes from Sofascore's own public API; no login, session or API key required anywhere.

**What's in the score-margin graph?**
A point value per minute of game time representing the score differential (positive means the home team was ahead), reconstructing the flow of the game without needing the full play-by-play.

**How is the roster billed if the same team appears in multiple games in one run?**
Once. `roster-record` is computed and billed once per unique team encountered in the run, never re-billed for every game that team appears in.

**How is standings billed the same way?**
Once per unique tournament/season combination in the run, not once per game.

**What happens if a team name doesn't resolve?**
The Actor logs a warning and skips it rather than failing the whole run. Use the team's full common name (e.g. "Los Angeles Lakers", not "Lakers").

**How fresh is the data?**
As fresh as Sofascore itself, scores and stats typically update within minutes of a real-world play.

**Why does play-by-play sometimes show "N/A" for the quarter?**
Sofascore's own incident feed labels quarter-end markers but not every individual scoring play with its quarter; where that label is genuinely absent from the source, this Actor reports it honestly instead of guessing.

### 🔌 Integrate with any app

Every run's output is available as CSV, Excel, JSON or XML, or through Apify's API and client libraries for Python and JavaScript.

### 🔗 Recommended Actors

Browse the rest of the [PunkRecordsData](https://apify.com/punkrecordsdata) catalog, including Tennis Match Stats Scraper and Sofascore Match Stats Scraper (football), for more sports data covering other Sofascore sports.

> 💡 **Pro Tip:** browse the complete [PunkRecordsData collection](https://apify.com/punkrecordsdata).

**🆘 Need Help?** contact.punkrecordsdata@gmail.com

> **⚠️ Disclaimer:** This is an independent tool, not affiliated with, endorsed by, or sponsored by Sofascore, the NBA, or any league or team. It collects only publicly available data.

# Actor input Schema

## `teamNames` (type: `array`):

NBA/EuroLeague/other team names to look up (e.g. "Los Angeles Lakers"). Resolved to the team's Sofascore id via search, then recent and upcoming games are collected.

## `eventIds` (type: `array`):

Specific Sofascore match IDs to fetch directly, bypassing team search. Find an ID in a Sofascore match URL, e.g. sofascore.com/.../id:12345678.

## `liveOnly` (type: `boolean`):

Ignore Team names / Match IDs and instead fetch every basketball game currently live.

## `maxItems` (type: `integer`):

Free users: limited to 10 items (preview). Paid users: optional, max 1,000,000. Shared across all record types.

## `includeStatistics` (type: `boolean`):

Team-level scoring/rebounds/etc. stats, broken out for the full game AND each individual quarter.

## `includeBoxScore` (type: `boolean`):

Full per-player stat line for the game: points, rebounds, assists, steals, blocks, shooting splits, plus-minus, efficiency rating.

## `includeLineups` (type: `boolean`):

Starters vs bench, position and jersey number for both teams in this specific game.

## `includeH2h` (type: `boolean`):

Historical wins/losses between the two teams.

## `includeOdds` (type: `boolean`):

Bookmaker odds for the game result market. Informational data only, not betting advice.

## `includeScoreGraph` (type: `boolean`):

The point-margin-over-time curve for the whole game, minute by minute.

## `includePlayByPlay` (type: `boolean`):

Every real scoring play in the game (1/2/3-pointers and free throws), with player, time and running score.

## `includeRoster` (type: `boolean`):

The team's full season roster: every player, position, height, weight, jersey number. Computed once per unique team in the run, not once per game.

## `includeStandings` (type: `boolean`):

The league table for the team's competition. Computed once per unique tournament/season in the run, not once per game.

## Actor input object example

```json
{
  "teamNames": [
    "Los Angeles Lakers"
  ],
  "liveOnly": false,
  "maxItems": 10,
  "includeStatistics": true,
  "includeBoxScore": false,
  "includeLineups": false,
  "includeH2h": false,
  "includeOdds": false,
  "includeScoreGraph": false,
  "includePlayByPlay": false,
  "includeRoster": false,
  "includeStandings": false
}
```

# Actor output Schema

## `overview` (type: `string`):

Key fields: teams, tournament, score, date

## `fullData` (type: `string`):

Complete dataset with every field, including nested statistics, box scores, play-by-play, roster and standings records

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "teamNames": [
        "Los Angeles Lakers"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("punkrecordsdata/basketball-match-stats-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "teamNames": ["Los Angeles Lakers"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("punkrecordsdata/basketball-match-stats-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "teamNames": [
    "Los Angeles Lakers"
  ],
  "maxItems": 10
}' |
apify call punkrecordsdata/basketball-match-stats-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,punkrecordsdata/basketball-match-stats-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/47h5RrA1aOvaFekc8/builds/kEKCzGE4p3abOIKKp/openapi.json
