# FanGraphs Baseball Statistics Scraper (`automation-lab/fangraphs-baseball-statistics-scraper`) Actor

Export public FanGraphs MLB batting and pitching leaderboards with player and team IDs, WAR, standard statistics, and advanced metrics.

- **URL**: https://apify.com/automation-lab/fangraphs-baseball-statistics-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Sports
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.29 / 1,000 item extracteds

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

## FanGraphs Baseball Statistics Scraper

Export public **FanGraphs baseball statistics** as structured player-season records. The Actor reads FanGraphs major-league batting and pitching leaderboards and returns player and team identifiers, season, standard statistics, WAR, rate metrics, and the complete scalar metric payload exposed by the selected leaderboard group.

Use it to refresh sabermetric research tables, prepare fantasy-baseball inputs, compare seasons, support scouting analysis, or feed reproducible data pipelines. It uses FanGraphs' public JSON leaderboard over a US residential proxy; it does not access member-only material, projections, playoff odds, or prospect rankings.

### What can you extract?

- batting or pitching player-season rows;
- FanGraphs player ID and MLBAM ID when exposed;
- FanGraphs team ID and team abbreviation;
- season, age, games, plate appearances, or innings pitched;
- WAR, AVG, OBP, SLG, OPS, ERA, WHIP, FIP, strikeout rate, and walk rate;
- the complete scalar source response in `stats` for less common advanced metrics;
- source URL and extraction timestamp for provenance.

### Who is it for?

**Sabermetric researchers** can create repeatable season snapshots. **Fantasy analysts** can refresh model features without copying tables. **Scouts and sports-data teams** can compare player cohorts. **Developers** can send normalized JSON to a warehouse, spreadsheet, notebook, or scheduled automation.

For official game, schedule, roster, or standings records, use [MLB StatsAPI Baseball Data Scraper](https://apify.com/automation-lab/mlb-statsapi-baseball-data-scraper). This Actor is specifically for FanGraphs leaderboard metrics.

### Input parameters

| Field | Description | Default |
|---|---|---|
| `statTypes` | `batting`, `pitching`, or both | `['batting']` |
| `statGroup` | `standard` or `advanced` FanGraphs leaderboard group | `standard` |
| `seasons` | MLB season years from 1871 through the current year | previous year |
| `teamIds` | Optional FanGraphs team IDs | all teams |
| `playerName` | Optional case-insensitive name substring | no filter |
| `qualifiedOnly` | Apply FanGraphs' qualification threshold | `false` |
| `maxItems` | Maximum rows across all requested combinations | `100` |
| `proxyConfiguration` | Apify residential US proxy configuration | configured automatically |

FanGraphs currently requires a US residential proxy. Disabling Apify Proxy causes the run to fail clearly rather than silently returning an empty dataset.

### Getting started

1. Open the Actor in Apify Console.
2. Choose batting, pitching, or both.
3. Select `standard` or `advanced` and enter one or more seasons.
4. Optionally add team IDs, a player-name filter, or qualification filtering.
5. Set `maxItems` and click **Start**.
6. Download results from the Dataset tab as JSON, CSV, Excel, XML, or RSS.

### Example input

```json
{
  "statTypes": ["batting", "pitching"],
  "statGroup": "standard",
  "seasons": [2024],
  "qualifiedOnly": true,
  "maxItems": 50
}
```

### Output example

```json
{
  "recordType": "playerSeason",
  "statType": "batting",
  "statGroup": "standard",
  "season": 2024,
  "playerId": 12345,
  "mlbamId": 654321,
  "playerName": "Sample Player",
  "teamId": 9,
  "team": "NYY",
  "games": 150,
  "war": 5.4,
  "battingAverage": 0.285,
  "onBasePercentage": 0.375,
  "sluggingPercentage": 0.51,
  "ops": 0.885,
  "stats": { "HR": 30, "wRC+": 132, "WAR": 5.4 },
  "sourceUrl": "https://www.fangraphs.com/api/leaders/major-league/data?...",
  "scrapedAt": "2025-01-15T12:00:00.000Z"
}
```

Fields that do not apply to the selected row type are omitted. `stats` preserves source metric names, including punctuation such as `K%` and `wRC+`.

### How much does it cost to export FanGraphs baseball statistics?

Pricing has two parts: a **$0.005 start fee** and per-result pricing. At the BRONZE rate of **$0.00048 per player-season row**, 25 rows cost about **$0.017**, 100 rows about **$0.053**, and 1,000 rows about **$0.485**. Your active Apify plan tier may have a lower per-row price; Console shows the applicable rate before a run.

Only useful rows saved to the dataset are charged as `item` events. Invalid, duplicate, filtered-out, or failed rows are not charged as items. Proxy and platform usage are covered by pay-per-event pricing.

### Pagination, filters, and limits

The Actor requests up to 200 leaderboard rows per page and follows pagination until `maxItems` or source exhaustion. A single team ID is sent to FanGraphs; multiple team IDs are consistently filtered from source rows. Player-name filtering is also applied before saving.

`maxItems` applies to the combined result across seasons and stat types.

### Recurring research workflows

Schedule daily, weekly, or end-of-season runs and compare datasets by `playerId`, `season`, and `statType`. Send results to Google Sheets for fantasy review, to a database for longitudinal analysis, or to a model pipeline for feature refreshes. Keep `sourceUrl` and `scrapedAt` to document provenance and collection time.

### API usage with cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/automation-lab~fangraphs-baseball-statistics-scraper/runs?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"statTypes":["batting"],"seasons":[2024],"qualifiedOnly":true,"maxItems":25}'
```

### API usage with JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/fangraphs-baseball-statistics-scraper').call({
  statTypes: ['pitching'], seasons: [2024], qualifiedOnly: true, maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API usage with Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_APIFY_TOKEN')
run = client.actor('automation-lab/fangraphs-baseball-statistics-scraper').call(
    run_input={'statTypes': ['batting', 'pitching'], 'seasons': [2024], 'maxItems': 100}
)
items = client.dataset(run['defaultDatasetId']).list_items().items
```

### Use through MCP

Add the Apify MCP server in Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/fangraphs-baseball-statistics-scraper"
```

#### Claude Desktop, Cursor, and VS Code setup

Use this equivalent MCP JSON configuration in Claude Desktop, Cursor, or VS Code:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/fangraphs-baseball-statistics-scraper"
    }
  }
}
```

Example prompt: “Export qualified 2024 FanGraphs pitching rows and summarize the top ten pitchers by WAR and FIP.”

### Reliability and failure behavior

Requests use browser-like headers, US residential proxy sessions, strict JSON validation, and at most three attempts. A retry changes proxy identity for a Cloudflare challenge, timeout, rate limit, or transient server error. Invalid input and deterministic upstream errors are not retried blindly. If all attempts fail, the Actor exits non-zero and logs a concise cause.

### Limitations

- Public major-league leaderboards only.
- No projections, playoff odds, prospect rankings, minor-league/member-only pages, or login support.
- FanGraphs can add, rename, or remove fields; headline normalized fields remain stable while `stats` mirrors current scalar source keys.
- Historic availability and qualification depend on FanGraphs.
- Naturally empty filters produce an empty dataset.

### Legality and responsible use

FanGraphs data may be subject to source terms and database rights. Collect only public data you are authorized to use, keep request volume reasonable, and comply with applicable law and contractual obligations. Do not use the Actor to circumvent accounts or redistribute restricted content.

### Troubleshooting

**The run says residential proxy is required.** Restore the default proxy configuration with Apify Proxy, group `RESIDENTIAL`, and country `US`.

**I received zero rows.** Check the season, team IDs, name filter, and qualification setting. Try removing optional filters to distinguish a naturally empty cohort from an input mistake.

**A field is missing.** Some metrics only apply to batting or pitching and some source values are null. Inspect `stats` for the complete scalar payload returned by FanGraphs.

### FAQ

#### Does it use an official FanGraphs API?

It uses the public JSON endpoint loaded by FanGraphs' major-league leaderboard. FanGraphs does not promise this as a versioned developer API, so changes may require maintenance.

#### Can I export both batting and pitching?

Yes. Select both values in `statTypes`; `maxItems` is shared across the combined output.

#### Can I search one player?

Use `playerName` for a case-insensitive substring and one or more seasons. Results still come from public leaderboard rows.

#### Can I schedule updates?

Yes. Use Apify schedules and integrations to rerun the same input and deliver each fresh dataset to your destination.

### Related Automation Lab Actors

- [MLB StatsAPI Baseball Data Scraper](https://apify.com/automation-lab/mlb-statsapi-baseball-data-scraper) for official schedules, games, rosters, standings, and records.
- [FantasyPros NFL Projections & Rankings](https://apify.com/automation-lab/fantasypros-nfl-projections-rankings) for an analogous fantasy-data workflow in football.

# Actor input Schema

## `statTypes` (type: `array`):

Choose batting, pitching, or both leaderboard types.

## `statGroup` (type: `string`):

Standard returns the broad leaderboard payload; advanced requests the FanGraphs advanced leaderboard group.

## `seasons` (type: `array`):

One or more four-digit MLB season years.

## `teamIds` (type: `array`):

Restrict rows to one or more positive FanGraphs team IDs. Leave empty for all teams.

## `playerName` (type: `string`):

Case-insensitive player-name filter applied to returned rows.

## `qualifiedOnly` (type: `boolean`):

Return only players meeting FanGraphs' qualification threshold for the selected season.

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

Maximum total player-season rows saved across all requested seasons and statistic types.

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

FanGraphs requires Apify Proxy with the RESIDENTIAL group and US country. The default is configured automatically.

## Actor input object example

```json
{
  "statTypes": [
    "batting"
  ],
  "statGroup": "standard",
  "seasons": [
    2024
  ],
  "teamIds": [],
  "qualifiedOnly": false,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Default dataset containing batting and pitching player-season records with headline and complete source statistics.

# 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 = {
    "statTypes": [
        "batting"
    ],
    "statGroup": "standard",
    "seasons": [
        2024
    ],
    "qualifiedOnly": false,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/fangraphs-baseball-statistics-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 = {
    "statTypes": ["batting"],
    "statGroup": "standard",
    "seasons": [2024],
    "qualifiedOnly": False,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/fangraphs-baseball-statistics-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 '{
  "statTypes": [
    "batting"
  ],
  "statGroup": "standard",
  "seasons": [
    2024
  ],
  "qualifiedOnly": false,
  "maxItems": 20
}' |
apify call automation-lab/fangraphs-baseball-statistics-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/fangraphs-baseball-statistics-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/ejhf6BWkWMRSYGtU8/builds/HNDBJj350u53z7nFg/openapi.json
