# StatMuse Sports Stats Scraper (NBA, NFL, MLB, NHL & More) (`confidential_gnat/statmuse-sports-scraper`) Actor

Scrapes StatMuse (statmuse.com) answers to natural-language sports questions plus player game logs and team pages for NBA, NFL, MLB, NHL, WNBA, college football, soccer and golf. Returns the answer sentence and stat tables as flat rows. Optional cache skips past-season queries.

- **URL**: https://apify.com/confidential_gnat/statmuse-sports-scraper.md
- **Developed by:** [ActorFlow](https://apify.com/confidential_gnat) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 results

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## StatMuse Sports Stats Scraper (statmuse.com) - NBA, NFL, MLB, NHL & More

**Scrape sports stats from StatMuse (statmuse.com)** by asking plain-English questions or pasting a StatMuse page URL. Get the one-sentence answer and the full **stat table** as flat rows: player game logs, leaderboards, team records, head-to-heads and **betting stats such as against-the-spread records** for the NBA, NFL, MLB, NHL, WNBA, college football, soccer and PGA golf. Export the **sports data** as JSON, CSV or Excel, or call the scraper as a **StatMuse API**.

![StatMuse sports scraper cover: a LeBron James last 10 games question returned as a JSON stat record from statmuse.com](https://i.postimg.cc/vBQkGrP1/Gemini-Generated-Image-kfyattkfyattkfya.jpg)

**Target website:** [statmuse.com](https://www.statmuse.com)

> **Terms of service caution:** StatMuse's Terms of Service prohibit automated data mining and scraping and license the site for non-commercial use only. This actor reads only public pages that need no login, but **you** are responsible for checking the StatMuse terms and getting any permission you need before you scrape, store or reuse its data, especially commercially. StatMuse also sells official data access.

### ✨ Features of this StatMuse sports stats scraper

- **Natural-language query scraping** — ask "Celtics against the spread record" or "most points in a game 2024-25" and get the answer sentence plus the result table
- **Player game logs and team pages** — paste a player game log (any season) or a team season page URL
- **Eight sports** — NBA, NFL, MLB, NHL, WNBA, college football, soccer (FC) and PGA golf
- **Flat rows or whole tables** — one record per table row with every stat as its own column, or one record per table with nested columns and rows
- **Entity ids** — player, game and team-season ids from StatMuse on every row, to join with other data
- **Only new history (cache)** — a cache project name skips queries and pages about finished past seasons you already have
- **Proxy support** — optional Apify Proxy configuration
- **No browser required** — plain HTTP requests make runs fast and cheap

### 🚀 How to scrape StatMuse stats in 5 steps

1. [Sign up](https://apify.com/sign-up) for a free Apify account — includes **$5 monthly credit**.
2. Open the actor page and click **Try for free**.
3. Keep the prefilled StatMuse URL, or type your questions in the search section and pick the sport.
4. Click **Start** and wait for the run to complete.
5. Download results from the **Output** tab in JSON, CSV, or Excel format.

You can also run this actor via the [Apify API](https://docs.apify.com/api/v2) or integrate it directly into your workflows using [Zapier](https://zapier.com/apps/apify), [Make](https://www.make.com/), or [n8n](https://n8n.io/).

### 💰 StatMuse scraper pricing

This actor uses **pay-per-result** billing: you pay for each record saved to the dataset.

- New Apify accounts include **$5 of free monthly credit**.
- It works with plain HTTP requests instead of a headless browser, so it costs significantly less to run than browser-based scrapers.
- Proxies are off by default, which keeps runs as cheap as possible.
- **Max items** is counted per question or URL and defaults to 5. A result table holds up to 50 rows, so set it to what you need.
- Set a **Cache project name** on scheduled runs: past-season history you already scraped is skipped and not charged.

### 🔧 StatMuse scraper input configuration

![StatMuse scraper input form with page URLs, cache project name, max items, questions, sport, one record per table row and include answer sentence fields marked 1 to 7](https://i.postimg.cc/g044qfDb/image.png)

The numbers in the screenshot mark the fields of the input form:

1. **StatMuse page URLs** (`startUrls`): question, player game log or team page URLs.
2. **Cache project name** (`cacheProjectName`): reuse the same name on scheduled runs to skip past-season queries already scraped.
3. **Max items** (`maxItems`): maximum records per question or start URL.
4. **Questions** (`queries`): plain-English sports questions, one per line.
5. **Sport for questions** (`sport`): the StatMuse section the questions are asked in, such as NBA, NFL or soccer.
6. **One record per table row** (`flattenTable`): on gives flat rows, off gives one record per table.
7. **Include answer sentence** (`includeAnswerText`): adds StatMuse's one-sentence answer to each record.

| Field | Type | Required | Default | Description |
| ----- | ---- | -------- | ------- | ----------- |
| `startUrls` | array | — | `[]` (prefilled with LeBron James last 10 games) | StatMuse question, player game log or team pages. |
| `cacheProjectName` | string | — | — | Same name on each run = skip past-season queries and pages already scraped. Never applies to "this season", last N games or leaderboards. Records get `changeType: new`. |
| `maxItems` | integer | — | `5` | Maximum records per question or start URL (a table row, or a whole table in whole table mode). |
| `queries` | array | — | `[]` | Plain-English questions, for example `Celtics against the spread record`. |
| `sport` | string | — | `nba` | Sport section the questions are asked in: `nba`, `nfl`, `mlb`, `nhl`, `wnba`, `cfb`, `fc` (soccer), `pga`. |
| `flattenTable` | boolean | — | `true` | One record per table row. Off = one record per table with nested `columns` and `rows`. |
| `includeAnswerText` | boolean | — | `true` | Add StatMuse's answer sentence to each record. |
| `proxyConfiguration` | object | — | `{"useApifyProxy": false}` | Optional Apify Proxy settings. |

**Supported URL types:**

- Questions: `https://www.statmuse.com/nba/ask/lebron-james-last-10-games`, `https://www.statmuse.com/nba/ask?q=celtics+against+the+spread+record`, `https://www.statmuse.com/fc/ask/messi-goals-2022`
- Player game logs: `https://www.statmuse.com/nba/player/lebron-james-1780/game-log?seasonYear=2024` (a plain player page is read as its current game log)
- Team pages: `https://www.statmuse.com/nba/team/los-angeles-lakers-15/2025`

The questions, sport, table mode and answer text fields sit in the collapsible **Search by questions and filters** section and are never applied to start URLs. The proxy setting is in its own **Proxy** section.

### 📦 StatMuse scraper output data

Each record is a flat JSON object with `id`, `query`, `sport`, `answer`, `sourceUrl`, `tableName`, `tableIndex`, `rowIndex`, the stat columns of that table as camelCase fields (for example `name`, `date`, `tm`, `opp`, `pts`, `reb`, `ast`, `fgPct`, `threePm`), `entities` (type, id, display name and StatMuse path for players, games and teams) and `scrapedAt`, plus `changeType` when caching. In whole table mode records have `id`, `query`, `sport`, `answer`, `sourceUrl`, `tableName`, `tableIndex`, `rowCount`, `columns`, `rows` and `scrapedAt`. The column set follows how StatMuse interprets each question, so it differs between queries. Missing values are `null`. The dataset has 1 view, **Overview**, a table of the answer and the first columns of each row.

**Output at a glance:**

| Date | Team | Opp. | Min | Pts | Reb | Ast |
| ---- | ---- | ---- | --- | --- | --- | --- |
| 2026-04-18 | LAL | HOU | 38 | 19 | 8 | 13 |
| 2026-04-21 | LAL | HOU | 39 | 28 | 8 | 7 |
| 2026-04-24 | LAL | HOU | 45 | 29 | 13 | 6 |
| 2026-04-26 | LAL | HOU | 33 | 10 | 4 | 9 |
| 2026-04-29 | LAL | HOU | 39 | 25 | 3 | 7 |

**Sample output (raw JSON):**

```json
{
	"id": "nba-6fcb2cf200b2",
	"query": "lebron james last 10 games",
	"sport": "nba",
	"answer": "LeBron James has averaged 23.2 points, 7.3 assists and 6.7 rebounds in 10 games in his last 10 games.",
	"sourceUrl": "https://www.statmuse.com/nba/ask/lebron-james-last-10-games",
	"tableName": null,
	"tableIndex": 0,
	"rowIndex": 0,
	"name": "LeBron James",
	"date": "2026-04-18T00:00:00",
	"tm": "LAL",
	"alignment": "vs",
	"opp": "HOU",
	"min": 38.4333,
	"pts": 19,
	"reb": 8,
	"ast": 13,
	"stl": 2,
	"blk": 1,
	"fgm": 9,
	"fga": 15,
	"fgPct": 0.6,
	"threePm": 1,
	"threePa": 2,
	"threePPct": 0.5,
	"ftm": 0,
	"fta": 2,
	"ftPct": 0,
	"tsPct": 0.5982,
	"oreb": 0,
	"dreb": 8,
	"tov": 2,
	"pf": 3,
	"plusMinus": 11,
	"entities": {
		"name": {
			"type": "player",
			"id": "1780",
			"display": "LeBron James",
			"path": "nba/players/1780"
		},
		"date": {
			"type": "game",
			"id": "78454",
			"display": "4/18/2026 HOU @ LAL",
			"path": "nba/games/78454"
		},
		"tm": {
			"type": "teamSeason",
			"id": "15/2026",
			"display": "2025-26 Los Angeles Lakers",
			"path": "nba/teams/15/2026"
		},
		"opp": {
			"type": "teamSeason",
			"id": "37/2026",
			"display": "2025-26 Houston Rockets",
			"path": "nba/teams/37/2026"
		}
	},
	"scrapedAt": "2026-10-18T05:20:59.354Z"
}
```

### 🐍 How to scrape StatMuse with Python, JavaScript or the API

Run the actor programmatically with the official Apify clients. Replace `<YOUR_API_TOKEN>` with the token from your [Apify Console](https://console.apify.com/account/integrations).

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run = client.actor("confidential_gnat/statmuse-sports-scraper").call(run_input={
    "queries": ["celtics against the spread record"],
    "sport": "nba",
    "maxItems": 20,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

**JavaScript** (`npm install apify-client`):

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

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });

const run = await client.actor('confidential_gnat/statmuse-sports-scraper').call({
    queries: ['celtics against the spread record'],
    sport: 'nba',
    maxItems: 20,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**cURL** — start a run and wait for the dataset:

```bash
curl -X POST "https://api.apify.com/v2/acts/confidential_gnat~statmuse-sports-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"queries": ["celtics against the spread record"], "sport": "nba", "maxItems": 20}'
```

### 💡 What you can use StatMuse sports stats data for

- Player and team research datasets: game logs, last-N splits, season totals and head-to-heads in one table
- Betting research on against-the-spread and over/under records per team and game
- Fantasy sports and DFS models that need historical stat lines by player and season
- Sports newsletters, bots and dashboards that answer questions with a sentence and a table
- Analytics notebooks that join StatMuse player, game and team ids with other sports data

Analysts, bettors, fantasy players, journalists and sports-data teams typically use this data, subject to the StatMuse terms noted above.

### ⚠️ StatMuse scraper limitations

- **Terms of service** — StatMuse prohibits scraping and limits use to non-commercial purposes. Read its terms before using this actor or the data; the responsibility is yours.
- **50 rows per query** — a result table holds at most 50 rows and the site has no pagination. Split a question by season or by last N games to get more.
- **Columns vary** — StatMuse picks its own interpretation of each question, so tables and columns differ between questions. A question it cannot understand returns no records and a warning in the log.
- **Offseason "this season"** — StatMuse answers "this season" with last season when the new one has not started.
- **No live odds** — only betting statistics such as against-the-spread and over/under results, not current sportsbook lines.
- **Unsupported pages** — single game pages, scores and standings are not read; use questions or game logs instead.
- **Fresh data** — answers are cached by the site for about a minute; past-season history never changes, so use the cache project name for it.

### ❓ StatMuse scraper FAQ

#### Can I scrape StatMuse legally?

The actor only collects data that StatMuse shows to logged-out visitors, with no login or paywalled content. Scraping publicly available data is generally considered lawful (see *hiQ Labs v. LinkedIn*), but the StatMuse Terms of Service explicitly prohibit automated scraping and commercial use, so review them and your local laws before using the data.

#### What data does the StatMuse scraper return?

The answer sentence, the question as StatMuse understood it, and every row of the result tables: for example player, date, team, opponent, points, rebounds, assists and shooting splits for a game log, plus StatMuse ids for players, games and team seasons.

#### How many rows can I scrape from one StatMuse question?

**Max items** applies per question or start URL and defaults to 5. A single result table holds up to 50 rows, and game log pages are split into one table per month or phase of the season.

#### Do I need a proxy to scrape statmuse.com?

No. The proxy setting defaults to off and the site answers normal requests, from datacenter proxies too. Turn on Apify Proxy only if you get blocked.

#### How do I scrape StatMuse with Python?

Use the Python example above with `apify-client`, then iterate over the dataset items and read the stat fields of each row.

#### Can I run this StatMuse scraper on a schedule?

Yes, use Apify Schedules. Set the same **Cache project name** on every run so questions and pages about finished past seasons are not fetched or charged again. Current-season questions, last-N games and leaderboards are always fetched fresh.

#### What output formats are supported?

JSON, CSV, Excel, XML and RSS, either from the **Output** tab or through the Apify API.

#### Why did my question return no records?

StatMuse answers HTTP 422 "I didn't understand your question" for questions it cannot parse, or for a player asked in the wrong sport. Rephrase the question in StatMuse style, check the **Sport for questions** field, and look at the run log for the warning.

### 🔗 Other actors you may find useful for sports and betting data

| Scraper | Description |
| ------- | ----------- |
| [🏈 Action Network Odds & Public Betting Scraper](https://apify.com/confidential_gnat/action-network-odds-scraper) | Sportsbook odds, public betting splits, opening lines and line movement. |
| [📈 Kalshi Markets Scraper](https://apify.com/confidential_gnat/kalshi-markets-scraper) | Prediction market prices, implied probability, spread and volume. |
| [🎟️ Gametime Events Website Scraper](https://apify.com/confidential_gnat/gametime-events-scraper) | Event, venue and ticket offer data from Gametime. |
| [📅 Facebook Events Scraper](https://apify.com/confidential_gnat/facebook-events-scraper) | Public Facebook events by keyword, location and date, without login. |
| [📰 Google News AI Scraper](https://apify.com/confidential_gnat/google-news-ai-scraper) | Google News search with optional article text and AI summaries. |

### 💬 Support & contact

If you encounter any issues or have questions, please [open an issue](https://apify.com/confidential_gnat/statmuse-sports-scraper/issues/open).

You can also find more of our actors on the [Actor Flow](https://apify.com/confidential_gnat) page.

# Actor input Schema

## `startUrls` (type: `array`):

StatMuse question, player game log or team pages, for example https://www.statmuse.com/nba/ask/lebron-james-last-10-games, https://www.statmuse.com/nba/ask?q=celtics+against+the+spread+record, https://www.statmuse.com/nba/player/lebron-james-1780/game-log?seasonYear=2024 or https://www.statmuse.com/nba/team/los-angeles-lakers-15/2025. A plain player page is read as its current game log. Leave empty to use the questions below.

## `cacheProjectName` (type: `string`):

Use the same name on each scheduled run to skip history you already have. Only queries and pages about a finished past season are cached (for example 'most points in a game 2024-25'); 'this season', last N games, leaderboards and current pages are always scraped. Cached ones are skipped and not charged; new records get changeType: new.

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

Maximum records per question or start URL. In table row mode a record is one table row (a result table holds up to 50 rows); in whole table mode a record is one table.

## `queries` (type: `array`):

Plain-English sports questions, one per line, for example 'Celtics against the spread record', 'most points in a game 2024-25' or 'Mahomes passing yards 2024'. Each question is asked in the sport selected below.

## `sport` (type: `string`):

Which StatMuse sport section the questions are asked in. Soccer is /fc. Defaults to NBA.

## `flattenTable` (type: `boolean`):

On: every table row becomes a flat record with its stats as columns (best for CSV and spreadsheets). Off: one record per table with its columns and rows nested.

## `includeAnswerText` (type: `boolean`):

Add StatMuse's one-sentence answer to every record. Turn off to make records smaller.

## `proxyConfiguration` (type: `object`):

This website works without a proxy. Enable Apify Proxy only if you get blocked.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.statmuse.com/nba/ask/lebron-james-last-10-games"
    }
  ],
  "maxItems": 5,
  "sport": "nba",
  "flattenTable": true,
  "includeAnswerText": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://www.statmuse.com/nba/ask/lebron-james-last-10-games"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("confidential_gnat/statmuse-sports-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 = {
    "startUrls": [{ "url": "https://www.statmuse.com/nba/ask/lebron-james-last-10-games" }],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("confidential_gnat/statmuse-sports-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 '{
  "startUrls": [
    {
      "url": "https://www.statmuse.com/nba/ask/lebron-james-last-10-games"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call confidential_gnat/statmuse-sports-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,confidential_gnat/statmuse-sports-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/96uuzczry2WOUkyyk/builds/hNwpxua99x91hYdOQ/openapi.json
