# FanDuel Odds API | Live Lines, Player Props & Scores (`zen-studio/fanduel-odds`) Actor

Scrape the complete FanDuel odds board for any game: moneyline, spread, totals, every inning and quarter, and the full player prop set. 25 sports, three odds formats, previous line on every selection, live scores for in-play games. Batch export or always-on REST API.

- **URL**: https://apify.com/zen-studio/fanduel-odds.md
- **Developed by:** [Zen Studio](https://apify.com/zen-studio) (community)
- **Categories:** Automation, Developer tools, Integrations
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 games

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## FanDuel Odds Scraper | Live Lines, Player Props & In-Play Scores (2026)

<blockquote style="border-left:4px solid #4C945E;background:#F0FDF4;padding:12px 16px;margin:12px 0">
<span style="font-size:16px;font-weight:700;color:#1C1917">A full MLB game is 159 markets and 1,100 priced bet options:</span> <span style="font-size:15px;color:#57534E">moneyline, spread, totals, every inning and quarter, and the complete player prop board, in three odds formats with the previous line on every selection.</span>
</blockquote>

<a href="https://console.apify.com/actors/oLjv3CSV3BhHm5dGN/input"><img src="https://api.apify.com/v2/key-value-stores/pJ7iaZsTFhR3k9tjV/records/fanduel-odds-hero.png" alt="FanDuel odds scraper: every market and player prop for a game, with moneyline, spread, totals, three odds formats and line movement, as structured JSON" style="max-width:100%"></a>

<blockquote style="border-left:4px solid #E7E5E4;padding:8px 14px;margin:12px 0">
<span style="font-size:14px;color:#57534E">⚡ One request returns the whole board. FanDuel splits a game across ten to sixteen tabs; pulling only the default tab yields 9 of 151 markets on an NFL game and no player props at all.</span>
</blockquote>

<table>
<tr>
<td colspan="4" style="padding:10px 14px;background:#4C945E;border:none;border-radius:4px 4px 0 0">
<span style="color:#FAFAF9;font-size:14px;font-weight:700;letter-spacing:0.5px">Zen Studio Sports Betting</span>
<span style="color:#E8F5E9;font-size:13px">&nbsp;&nbsp;&bull;&nbsp;&nbsp;Real-time odds across every major sportsbook</span>
</td>
</tr>
<tr>
<td style="padding:12px 16px;border:1px solid #E7E5E4;border-radius:0 0 0 4px;background:#D3EDD9;border-right:none;border-top:none;vertical-align:top;width:25%">
<img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-oLjv3CSV3BhHm5dGN-62o7r64lQq-fanduel-odds-api-logo.png" width="24" height="24" style="vertical-align:middle"> &nbsp;<a href="https://apify.com/zen-studio/fanduel-odds" style="color:#4C945E;text-decoration:none;font-weight:700;font-size:14px">FanDuel Odds</a><br>
<span style="color:#4C945E;font-size:12px;font-weight:600">&#10148; You are here</span>
</td>
<td style="padding:12px 16px;border:1px solid #E7E5E4;background:#E8F5E9;border-right:none;border-top:none;vertical-align:top;width:25%">
<img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-W8rOXiLSj8wrgF96k-PQehXxTEV5-draftkings-real-time-api-logo.png" width="24" height="24" style="vertical-align:middle"> &nbsp;<a href="https://apify.com/zen-studio/draftkings-odds" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:14px">DraftKings Odds</a><br>
<span style="color:#78716C;font-size:12px">Lines, props, SGP</span>
</td>
<td style="padding:12px 16px;border:1px solid #E7E5E4;background:#E8F5E9;border-right:none;border-top:none;vertical-align:top;width:25%">
<img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-TjShOnNguT17e9hfQ-ntCswWAqze-betmgm-real-time-api-logo-padded.png" width="24" height="24" style="vertical-align:middle"> &nbsp;<a href="https://apify.com/zen-studio/betmgm-odds" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:14px">BetMGM Odds</a><br>
<span style="color:#78716C;font-size:12px">Lines, props, futures</span>
</td>
<td style="padding:12px 16px;border:1px solid #E7E5E4;border-radius:0 0 4px 0;background:#E8F5E9;border-top:none;vertical-align:top;width:25%">
<img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-l6JP3yaLczAdUaiSf-yDHq17ycGp-bet365-icon_lc6m4t.png" width="24" height="24" style="vertical-align:middle"> &nbsp;<a href="https://apify.com/zen-studio/bet365-real-time-odds" style="color:#1C1917;text-decoration:none;font-weight:700;font-size:14px">Bet365 Odds</a><br>
<span style="color:#78716C;font-size:12px">Live and pre-match</span>
</td>
</tr>
</table>

#### Copy to your AI assistant

```
zen-studio/fanduel-odds on Apify. Batch: ApifyClient("TOKEN").actor("zen-studio/fanduel-odds").call(run_input={"sport":"baseball","maxEvents":10}), then client.dataset(run["defaultDatasetId"]).list_items().items. Always-on API: https://zen-studio--fanduel-odds.apify.actor?token=TOKEN with GET /sports, /competitions, /events, /live, /events/{eventId}, /events/{eventId}/odds; get IDs from the list endpoints before the detail ones. Full spec: GET https://api.apify.com/v2/acts/zen-studio~fanduel-odds/builds/default (Bearer TOKEN) → inputSchema, actorDefinition.storages.dataset, actorDefinition.webServerSchema, readme. Token: https://console.apify.com/account/integrations
```

### Key Features

- **The complete board, not the headline markets**: every tab FanDuel shows on a game page is merged into one result. A live NFL game returns about 150 markets, a soccer match about 214.
- **Player props included**: passing, rushing and receiving yards, touchdown scorers, strikeouts, total bases, hits, RBIs, goals, assists, shots, cards and corners, each flagged with `isPlayerProp` and a player headshot.
- **Line movement on every selection**: `previousDecimalOdds` and `previousAmericanOdds` ship with the current price, so drift is a subtraction rather than a second run.
- **Real fixtures only**: FanDuel's computer-played leagues (eBasketball, eSoccer) are filtered out by default and flagged with `isSimulated` when you ask for them.
- **Free tier**: 5 runs, one complete game board each, no credit card.

### How to Scrape FanDuel Odds

1. Open the **Input** tab and pick a sport from the dropdown.
2. Set **Number of games** to the size of the slate you want.
3. Press **Start** and wait; a game takes a few seconds.
4. Open **Storage** and download the dataset as JSON, CSV, Excel or XML.

Every game exports its full board, one row per bet option.

#### Basic: one league's slate

```json
{
    "sport": "basketball",
    "league": "NBA",
    "maxEvents": 10
}
```

Partial league names work, so `NHL`, `MLB`, `NFL` and `Premier League` all match. Leave `league` out for every league in the sport.

#### One game, every market it has

```json
{
    "sport": "baseball",
    "maxEvents": 1
}
```

#### A full slate across the popular sports

```json
{
    "sport": "ALL",
    "maxEvents": 100
}
```

`ALL` works through American football, basketball, baseball, ice hockey, soccer, tennis, MMA and golf in that order until it reaches your game limit.

#### Include the computer-played leagues

```json
{
    "sport": "soccer",
    "maxEvents": 20,
    "includeSimulated": true
}
```

### Input Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `sport` | string | `basketball` | Sport to pull. `ALL` walks the eight most popular in order. |
| `league` | string | *all leagues* | Narrow to one league; partial names match (`NHL`, `Premier League`). |
| `maxEvents` | integer | `10` | Number of games, 1 to 500. Each returns its complete board. |
| `includeSimulated` | boolean | `false` | Include FanDuel's computer-played leagues (eBasketball, eSoccer, eFootball). |

### What Data Can You Extract from FanDuel?

Every row is one bet option, so a single game produces 800 to 1,300 rows.

- **Game**: sport, league, league region, name, start time, live flag, home and away teams, simulated flag
- **Market**: name, type, status, same-game-parlay eligibility, betting type, runner and winner counts
- **Selection**: name, abbreviation, team logo, player headshot, player-prop flag, side, handicap, status
- **Odds**: decimal, fractional and American, plus the previous decimal and American price
- **Identifiers**: game, market, selection and league IDs, and the capture timestamp

`decimalOdds` is the exact value rather than FanDuel's rounded display price, so `-138` comes back as `1.72463768115942`. Round it yourself if you are showing it to people; keep it if you are computing edge.

#### Output Example

Two rows from a real MLB export: a team selection with its logo, and a player prop with the player's headshot.

```json
[
    {
        "sport": "Baseball",
        "sportSlug": "baseball",
        "league": "MLB",
        "leagueId": "2926d8429ed53300",
        "leagueRegion": "USA",
        "isSimulated": false,
        "event": "Chicago Cubs (K Gausman) @ Arizona Diamondbacks (M Kelly)",
        "eventId": "d88a7e1ed6edb5a7",
        "startDate": "2026-08-25T01:41:00.000Z",
        "isLive": false,
        "homeTeam": "Arizona Diamondbacks",
        "awayTeam": "Chicago Cubs",
        "market": "4th Inning Result",
        "marketType": "4TH_INNING_RESULT",
        "marketId": "37c22a7209b7d630",
        "marketStatus": "OPEN",
        "sgmMarket": true,
        "bettingType": "ODDS",
        "numberOfRunners": 3,
        "numberOfWinners": 1,
        "selection": "Chicago Cubs",
        "selectionId": "504c77ec8bbec3f5",
        "selectionStatus": "ACTIVE",
        "isPlayerProp": false,
        "side": null,
        "nameAbbr": "CHI Cubs",
        "logo": "https://assets.sportsbook.fanduel.com/images/team/mlb/chicago_cubs.png",
        "secondaryLogo": null,
        "handicap": 0,
        "decimalOdds": 3.5,
        "fractionalOdds": "25/10",
        "americanOdds": 250,
        "previousDecimalOdds": 3.4,
        "previousAmericanOdds": 240,
        "timestamp": "2026-08-24T15:22:10.233534+00:00"
    },
    {
        "sport": "Baseball",
        "sportSlug": "baseball",
        "league": "MLB",
        "leagueId": "2926d8429ed53300",
        "leagueRegion": "USA",
        "isSimulated": false,
        "event": "Chicago Cubs (K Gausman) @ Arizona Diamondbacks (M Kelly)",
        "eventId": "d88a7e1ed6edb5a7",
        "startDate": "2026-08-25T01:41:00.000Z",
        "isLive": false,
        "homeTeam": "Arizona Diamondbacks",
        "awayTeam": "Chicago Cubs",
        "market": "To Record 5+ Total Bases",
        "marketType": "TO_RECORD_5+_TOTAL_BASES",
        "marketId": "c322273951ed882c",
        "marketStatus": "OPEN",
        "sgmMarket": true,
        "bettingType": "ODDS",
        "numberOfRunners": 18,
        "numberOfWinners": 1,
        "selection": "Pete Crow-Armstrong",
        "selectionId": "c879d9ac41822ae6",
        "selectionStatus": "ACTIVE",
        "isPlayerProp": true,
        "side": null,
        "nameAbbr": null,
        "logo": "https://fdx-api.sportsbook.fanduel.com/images/headshots/mlb/2025/e9734861-bc3f-4157-88eb-007b1ed65984/120x120.png",
        "secondaryLogo": "https://assets.sportsbook.fanduel.com/images/team/mlb/chicago_cubs.png",
        "handicap": 0,
        "decimalOdds": 5.4,
        "fractionalOdds": "44/10",
        "americanOdds": 440,
        "previousDecimalOdds": 5.2,
        "previousAmericanOdds": 420,
        "timestamp": "2026-08-24T15:22:10.233534+00:00"
    }
]
```

### Always-On REST API

The same data is available as a hosted API that stays warm. Open the **Standby** tab for your URL, then call it with your Apify token.

#### Endpoints

| Endpoint | Price | Returns |
|----------|-------|---------|
| `/sports` | free | The 25 sports and their slugs |
| `/competitions?sport=SLUG` | $0.005 | Leagues with name, region and market count |
| `/events?sport=SLUG` | $0.005 | Games with name, league, start time and market count |
| `/live?sport=SLUG` | $0.005 | In-play games with per-sport live detail |
| `/events/{eventId}` | $0.05 | One game's complete board |
| `/events/{eventId}/odds` | $0.05 | The same board, prices only, for polling |

#### Find a league, then a game, then its board

```bash
curl "https://zen-studio--fanduel-odds.apify.actor/competitions?sport=baseball&token=YOUR_APIFY_TOKEN"
```

```bash
curl "https://zen-studio--fanduel-odds.apify.actor/events?sport=baseball&token=YOUR_APIFY_TOKEN"
```

```bash
curl "https://zen-studio--fanduel-odds.apify.actor/events/d88a7e1ed6edb5a7?token=YOUR_APIFY_TOKEN"
```

#### Leagues

```json
{
    "success": true,
    "sport": "baseball",
    "count": 3,
    "competitions": [
        {
            "competitionId": "2926d8429ed53300",
            "name": "MLB",
            "region": "USA",
            "isSimulated": false,
            "marketCount": 1762
        },
        {
            "competitionId": "23ce837210fc2ab7",
            "name": "Japan - Baseball",
            "region": "JPN",
            "isSimulated": false,
            "marketCount": 36
        }
    ]
}
```

#### Games

```json
{
    "success": true,
    "count": 21,
    "simulatedHidden": 0,
    "events": [
        {
            "eventId": "e4590d23b98a146a",
            "name": "Tampa Bay Rays (D Rasmussen) @ Detroit Tigers (F Valdez)",
            "sport": "Baseball",
            "league": "MLB",
            "leagueId": "2926d8429ed53300",
            "isSimulated": false,
            "startDate": "2026-08-24T22:41:00.000Z",
            "marketCount": 177,
            "isLive": false
        },
        {
            "eventId": "d849ad0380b54774",
            "name": "Boston Red Sox (R Suarez) @ Miami Marlins (S Alcantara)",
            "sport": "Baseball",
            "league": "MLB",
            "leagueId": "2926d8429ed53300",
            "isSimulated": false,
            "startDate": "2026-08-24T22:41:00.000Z",
            "marketCount": 180,
            "isLive": false
        }
    ]
}
```

`marketCount` is what FanDuel lists for the game. `simulatedHidden` tells you how many computer-played fixtures were filtered out.

#### One game's board

Three markets from a real response: the moneyline with both team logos, a player prop with the player's headshot, and a total with `OVER` and `UNDER` labelled.

```json
{
    "success": true,
    "event": {
        "eventId": "d88a7e1ed6edb5a7",
        "name": "Chicago Cubs (K Gausman) @ Arizona Diamondbacks (M Kelly)",
        "sport": "Baseball",
        "sportSlug": "baseball",
        "league": "MLB",
        "leagueId": "2926d8429ed53300",
        "leagueRegion": "USA",
        "isSimulated": false,
        "startDate": "2026-08-25T01:41:00.000Z",
        "isLive": false,
        "videoAvailable": true,
        "primaryMarketId": "2f23cd1c21d30ca8",
        "awayTeam": "Chicago Cubs",
        "homeTeam": "Arizona Diamondbacks"
    },
    "markets": [
        {
            "marketId": "e546214a2e8993cd",
            "marketName": "Moneyline",
            "marketType": "MONEY_LINE",
            "marketStatus": "OPEN",
            "sgmMarket": true,
            "sortPriority": 10,
            "bettingType": "ODDS",
            "marketTime": "2026-08-25T01:41:00.000Z",
            "isLive": false,
            "canGoLive": true,
            "eachWayAvailable": false,
            "numberOfRunners": 2,
            "numberOfActiveRunners": 2,
            "numberOfWinners": 1,
            "selections": [
                {
                    "selectionId": "504c77ec8bbec3f5",
                    "runnerName": "Chicago Cubs",
                    "nameAbbr": "CHI Cubs",
                    "logo": "https://assets.sportsbook.fanduel.com/images/team/mlb/chicago_cubs.png",
                    "secondaryLogo": null,
                    "isPlayerProp": false,
                    "side": "AWAY",
                    "sortPriority": 1,
                    "handicap": 0,
                    "runnerStatus": "ACTIVE",
                    "decimalOdds": 1.72463768115942,
                    "fractionalOdds": "100/138",
                    "americanOdds": -138,
                    "previousDecimalOdds": 1.735294117647059,
                    "previousAmericanOdds": -136
                },
                {
                    "selectionId": "a2f14986d62aaa25",
                    "runnerName": "Arizona Diamondbacks",
                    "nameAbbr": "ARI Diamondbacks",
                    "logo": "https://assets.sportsbook.fanduel.com/images/team/mlb/arizona_diamondbacks.png",
                    "secondaryLogo": null,
                    "isPlayerProp": false,
                    "side": "HOME",
                    "sortPriority": 2,
                    "handicap": 0,
                    "runnerStatus": "ACTIVE",
                    "decimalOdds": 2.28,
                    "fractionalOdds": "128/100",
                    "americanOdds": 128,
                    "previousDecimalOdds": 2.26,
                    "previousAmericanOdds": 126
                }
            ]
        },
        {
            "marketId": "c322273951ed882c",
            "marketName": "To Record 5+ Total Bases",
            "marketType": "TO_RECORD_5+_TOTAL_BASES",
            "marketStatus": "OPEN",
            "sgmMarket": true,
            "sortPriority": 1764,
            "bettingType": "ODDS",
            "marketTime": "2026-08-25T01:41:00.000Z",
            "isLive": false,
            "canGoLive": true,
            "eachWayAvailable": false,
            "numberOfRunners": 18,
            "numberOfActiveRunners": 18,
            "numberOfWinners": 1,
            "selections": [
                {
                    "selectionId": "c879d9ac41822ae6",
                    "runnerName": "Pete Crow-Armstrong",
                    "nameAbbr": null,
                    "logo": "https://fdx-api.sportsbook.fanduel.com/images/headshots/mlb/2025/e9734861-bc3f-4157-88eb-007b1ed65984/120x120.png",
                    "secondaryLogo": "https://assets.sportsbook.fanduel.com/images/team/mlb/chicago_cubs.png",
                    "isPlayerProp": true,
                    "side": null,
                    "sortPriority": 1,
                    "handicap": 0,
                    "runnerStatus": "ACTIVE",
                    "decimalOdds": 5.4,
                    "fractionalOdds": "44/10",
                    "americanOdds": 440,
                    "previousDecimalOdds": 5.2,
                    "previousAmericanOdds": 420
                },
                {
                    "selectionId": "3b8d98990455bb36",
                    "runnerName": "Corbin Carroll",
                    "nameAbbr": null,
                    "logo": "https://fdx-api.sportsbook.fanduel.com/images/headshots/mlb/2025/d06b32aa-b9c4-4e48-ae0f-058e3ebdbbfd/120x120.png",
                    "secondaryLogo": "https://assets.sportsbook.fanduel.com/images/team/mlb/arizona_diamondbacks.png",
                    "isPlayerProp": true,
                    "side": null,
                    "sortPriority": 2,
                    "handicap": 0,
                    "runnerStatus": "ACTIVE",
                    "decimalOdds": 7,
                    "fractionalOdds": "60/10",
                    "americanOdds": 600,
                    "previousDecimalOdds": 7.5,
                    "previousAmericanOdds": 650
                }
            ]
        },
        {
            "marketId": "9ba55eebd4bcaae1",
            "marketName": "Total Runs",
            "marketType": "TOTAL_POINTS_(OVER/UNDER)",
            "marketStatus": "OPEN",
            "sgmMarket": true,
            "sortPriority": 30,
            "bettingType": "MOVING_HANDICAP",
            "marketTime": "2026-08-25T01:41:00.000Z",
            "isLive": false,
            "canGoLive": true,
            "eachWayAvailable": false,
            "numberOfRunners": 2,
            "numberOfActiveRunners": 2,
            "numberOfWinners": 1,
            "selections": [
                {
                    "selectionId": "de578cc91cd9e21b",
                    "runnerName": "Over",
                    "nameAbbr": null,
                    "logo": null,
                    "secondaryLogo": null,
                    "isPlayerProp": false,
                    "side": "OVER",
                    "sortPriority": 1,
                    "handicap": 9,
                    "runnerStatus": "ACTIVE",
                    "decimalOdds": 1.909090909090909,
                    "fractionalOdds": "100/110",
                    "americanOdds": -110,
                    "previousDecimalOdds": 1.952380952380952,
                    "previousAmericanOdds": -105
                },
                {
                    "selectionId": "6f43bd63917f07f5",
                    "runnerName": "Under",
                    "nameAbbr": null,
                    "logo": null,
                    "secondaryLogo": null,
                    "isPlayerProp": false,
                    "side": "UNDER",
                    "sortPriority": 2,
                    "handicap": 9,
                    "runnerStatus": "ACTIVE",
                    "decimalOdds": 1.909090909090909,
                    "fractionalOdds": "100/110",
                    "americanOdds": -110,
                    "previousDecimalOdds": 1.869565217391304,
                    "previousAmericanOdds": -115
                }
            ]
        }
    ]
}
```

#### Prices only, for polling

```json
{
    "success": true,
    "eventId": "d88a7e1ed6edb5a7",
    "marketCount": 159,
    "markets": [
        {
            "marketId": "78035921d4563890",
            "marketStatus": "OPEN",
            "isLive": false,
            "selections": [
                {
                    "selectionId": "f53474bf917098d7",
                    "handicap": 0.0,
                    "runnerStatus": "ACTIVE",
                    "sortPriority": 10,
                    "decimalOdds": 1.066666666666667,
                    "fractionalOdds": "10/150",
                    "americanOdds": -1500,
                    "previousDecimalOdds": 1.071428571428571,
                    "previousAmericanOdds": -1400
                },
                {
                    "selectionId": "cd6c6faeac30d06c",
                    "handicap": 0.0,
                    "runnerStatus": "ACTIVE",
                    "sortPriority": 20,
                    "decimalOdds": 8.9,
                    "fractionalOdds": "79/10",
                    "americanOdds": 790,
                    "previousDecimalOdds": 8.6,
                    "previousAmericanOdds": 760
                }
            ]
        }
    ]
}
```

#### Live scores

Detail varies by sport. Soccer carries cards, corners, booking points and a match timeline; tennis is set by set with the server; basketball and hockey are per period; baseball is a box score; cricket is innings; snooker is frames.

```json
{
    "success": true,
    "count": 1,
    "events": [
        {
            "eventId": "4d2d9b50705e9580",
            "sport": "Tennis",
            "isLive": true,
            "mediaTypes": [],
            "homeScore": 0,
            "awayScore": 0,
            "currentSet": 1,
            "totalSets": 3,
            "serving": "AWAY",
            "homePoints": "15",
            "awayPoints": "30",
            "homeGamesPerSet": [
                2
            ],
            "awayGamesPerSet": [
                0
            ]
        }
    ]
}
```

A score of `0` is returned as `0`, not `null`, so a goalless first half is distinguishable from missing data.

#### Response Format

Every response carries the same envelope, errors included.

| Code | Meaning | What to do |
|------|---------|------------|
| 400 | Invalid parameter | Check the sport slug or the ID |
| 402 | Usage limit reached | Raise the billing limit on Apify |
| 404 | Unknown ID or endpoint | Discover IDs via `/events` or `/competitions` first |
| 405 | Wrong method | Every endpoint is `GET` |
| 502 | Upstream unavailable | Retry in a few seconds |

An empty result is a success, not an error. `/events`, `/competitions` and `/live` return `count: 0` with a `message` explaining why, most often that the sport is between seasons, and nothing is charged for it.

### Advanced Usage

Ready-made configurations for line-movement tracking, arbitrage screening, player-prop modelling and in-play monitoring.

#### Track line movement on tonight's slate

```json
{
    "sport": "football",
    "league": "NFL",
    "maxEvents": 16
}
```

Every selection ships with its previous price, so one run gives you the current line and the last move together.

#### Build a player-prop dataset

```json
{
    "sport": "baseball",
    "league": "MLB",
    "maxEvents": 15
}
```

Filter the export on `isPlayerProp` to keep only player markets. Each carries the player's headshot in `logo` and the team badge in `secondaryLogo`.

#### Compare against another sportsbook

```json
{
    "sport": "basketball",
    "league": "NBA",
    "maxEvents": 12
}
```

Run [DraftKings Odds](https://apify.com/zen-studio/draftkings-odds) or [BetMGM Odds](https://apify.com/zen-studio/betmgm-odds) with the same slate and join on team names and market type.

#### Poll a single game while it is in play

Use the always-on API rather than batch. `/events/{eventId}/odds` returns the same board with the metadata stripped, so responses stay small on a tight loop.

### Pricing

Billed per **game board**, not per request, so the price tracks the data you receive.

| What | Price |
|------|-------|
| One game's complete board | $0.05 |
| List request (leagues, games, live scores) | $0.005 |
| Run start | $0.03 |

A board averages about 1,100 priced bet options, which works out to roughly **$0.045 per 1,000 odds rows**. `/sports` is free, and an empty result is never charged.

Free tier: 5 runs, one complete game board each.

#### Keeping the cost down

- Set `maxEvents` to the slate you actually need; games are billed as you go.
- Browse with `/events` and `/competitions` at $0.005 and pull only the boards you want.
- On the always-on API, the $0.03 start applies per container rather than per request, and a container stays warm for five minutes after the last call. Frequent callers pay it rarely; if you poll on a long interval, batch mode is the cheaper shape.

### FAQ

**What is FanDuel?**
FanDuel is one of the largest sportsbooks in North America, operating in most regulated US states and in Ontario, alongside its daily fantasy product. This Actor covers the sportsbook side: the odds board for every game FanDuel prices, including the full player prop set. For its daily fantasy contests, see [PrizePicks](https://apify.com/zen-studio/prizepicks-player-props) or [Underdog Fantasy](https://apify.com/zen-studio/underdog-player-props), which cover the same market from the DFS angle.

**What markets are included?**
The complete board FanDuel shows on a game page, merged across every tab: moneyline, spread, totals and alternates, period and inning markets, same-game-parlay markets, and the full player prop set. A live NFL game is about 150 markets and 1,100 bet options; an MLB game about 159.

**Does FanDuel have an API?**
Not a public one. FanDuel offers no developer API, no documentation and no keys for its odds board, and its official partner feeds are enterprise agreements rather than something you can sign up for. This Actor gives you the same board as a normal REST response, with stable IDs and three odds formats, and no rate limit beyond your own budget.

**Can I connect this to Google Sheets, Make or Zapier?**
Yes. Every run writes a normal Apify dataset, so the Google Sheets, Make, Zapier and Slack integrations on the Actor's **Integrations** tab work without any extra setup, and a webhook can push each finished run straight to your own endpoint.

**How often should I schedule it?**
For pre-match line movement, hourly on the day of the slate is usually enough; lines move most in the last few hours before a start. For in-play, use the always-on API and poll `/events/{eventId}/odds` rather than scheduling batch runs.

**How fresh are the odds?**
Every run fetches live. There is no cache between you and the board, and each row carries the timestamp it was captured.

**How do I export the data?**
JSON, CSV, Excel, XML or HTML from the run's Storage tab, or through the Apify API. JSON preserves the exact decimal odds; CSV and Excel are flat already, since every row is one bet option.

**Is it legal to scrape FanDuel odds?**
The Actor reads publicly visible odds pages, nothing behind a login and no personal data. You are responsible for complying with FanDuel's terms and with the data protection law that applies to you, including GDPR, CCPA and PIPEDA in Canada. Odds data is factual pricing information, but gambling advertising and data use are separately regulated in many jurisdictions.

**What is the free tier?**
5 runs, one complete game board each, no credit card. That is roughly 1,100 odds rows per run.

**What are simulated leagues?**
FanDuel prices computer-played leagues that use real team names, such as "eBasketball H2H GG League 4x5 Mins". A new one starts every few minutes, so in start-soonest order they crowd out real fixtures. Batch runs, `/events` and `/live` all skip them by default and flag them with `isSimulated`. Genuine esports competitions between human players are not affected.

**Why is `side` null on some selections?**
`side` carries `HOME`, `AWAY`, `OVER` or `UNDER` on the markets where FanDuel provides it, which is mainly the main lines, roughly one selection in eight. Elsewhere it is null and the selection name is the label.

**Do I get suspended lines?**
Yes. An in-play game suspends most of its board between plays, and dropping those would leave you with nothing during the moments that matter most. Every selection comes through with its status, so filter on `selectionStatus` if you only want tradeable prices.

**What are the opaque IDs?**
Game, market, selection and league IDs are 16-character hex strings. They are stable and deterministic, so an ID you stored yesterday still works today. Discover them via `/events` or `/competitions`, then use them on the detail endpoints.

**Can I get historical odds?**
Not as a back catalogue. Each selection carries its previous price, which covers the most recent move. For a longer series, run on a schedule and keep the exports; every row is timestamped.

**How do I get just one league?**
Set `league` to any part of its name: `NHL`, `MLB`, `NBA`, `NFL`, `Premier League`. Matching is a case-insensitive substring, so a short name is usually enough. Out of season the run finishes with an empty dataset and the log lists the leagues that are actually running in that sport, which is the fastest way to find the right spelling.

**Which sports are covered?**
25: American football, basketball, baseball, ice hockey, soccer, tennis, MMA, golf, boxing, cricket, darts, snooker, table tennis, volleyball, handball, rugby union, rugby league, Australian rules, Gaelic games, lacrosse, motor sport, cycling, surfing, politics and special bets. Coverage follows the season, so an out-of-season sport returns an explained empty result rather than an error.

**What is Standby mode?**
An always-on HTTP server. No queue and no cold start while it is warm; Apify keeps it running and routes requests straight to it.

### More Zen Studio scrapers for sports betting

**🏟️ Sportsbook odds**

- <img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-W8rOXiLSj8wrgF96k-PQehXxTEV5-draftkings-real-time-api-logo.png" width="16" height="16" style="vertical-align:middle;border-radius:3px"> **DraftKings**
  - [DraftKings Odds API](https://apify.com/zen-studio/draftkings-odds)
- <img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-TjShOnNguT17e9hfQ-ntCswWAqze-betmgm-real-time-api-logo-padded.png" width="16" height="16" style="vertical-align:middle;border-radius:3px"> **BetMGM**
  - [BetMGM Odds API](https://apify.com/zen-studio/betmgm-odds)
- <img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-l6JP3yaLczAdUaiSf-yDHq17ycGp-bet365-icon_lc6m4t.png" width="16" height="16" style="vertical-align:middle;border-radius:3px"> **Bet365**
  - [Bet365 Real-Time Odds API](https://apify.com/zen-studio/bet365-real-time-odds)
  - [Bet365 Live Scores API](https://apify.com/zen-studio/bet365-live-scores)
  - [Bet365 Sports Data Scraper](https://apify.com/zen-studio/bet365-sports-data)

**🎯 Daily fantasy & player props**

- <img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-4AmgQeem8dEgMEiRF-VGffbe665M-prizepicks-scraper-logo.jpeg" width="16" height="16" style="vertical-align:middle;border-radius:3px"> **PrizePicks**
  - [PrizePicks Player Props Scraper](https://apify.com/zen-studio/prizepicks-player-props)
- <img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-09TtSjF9Uzs5qfvLc-f9HhMKXsLt-underdog-fantasy-picks-api-logo.png" width="16" height="16" style="vertical-align:middle;border-radius:3px"> **Underdog Fantasy**
  - [Underdog Fantasy Player Props API](https://apify.com/zen-studio/underdog-player-props)
- <img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-vZGwNIMCrwkjp76uR-6jWYFxsPSD-sleeper-fantasy-api-logo.jpg" width="16" height="16" style="vertical-align:middle;border-radius:3px"> **Sleeper**
  - [Sleeper Player Props](https://apify.com/zen-studio/sleeper-player-props)
- <img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/NWYsOG96fMDy8ycdf-actor-otCGHYjTnE0YKgVNJ-iYqrcfxJiq-draftkings-pick6-api-logo.png" width="16" height="16" style="vertical-align:middle;border-radius:3px"> **DraftKings Pick6**
  - [DraftKings Pick6 Player Props](https://apify.com/zen-studio/draftkings-pick6-player-props)

### Support

- **Bugs**: Issues tab
- **Features**: Issues tab

### Legal Compliance

Extracts publicly available data. Users must comply with FanDuel's terms and applicable data protection regulations, including GDPR, CCPA and PIPEDA.

***

*Real-time FanDuel Sportsbook odds for 25 sports: the complete board per game, player props included, with line movement and live scores.*

# Actor input Schema

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

Which sport to pull odds for.<br><br><b>All Sports</b> works through the 8 most popular in order (American football, basketball, baseball, ice hockey, soccer, tennis, MMA, golf) until it reaches your game limit.

## `league` (type: `string`):

Narrow to one league. Partial names work: <code>NHL</code>, <code>NBA</code>, <code>MLB</code>, <code>NFL</code>, <code>Premier League</code>.<br><br>Leave empty for every league in the sport. Out of season a league returns nothing, and the log lists what is running instead.

## `maxEvents` (type: `integer`):

How many games to pull, starting with the ones kicking off soonest.<br><br>Each game returns its <b>complete board</b>, typically <b>800 to 1,300 rows</b> (one row per bet option across every market and prop). 10 games is roughly 11,000 rows.

## `includeSimulated` (type: `boolean`):

FanDuel runs computer-played leagues that use real team names (eBasketball, eSoccer, eFootball). They start every few minutes and would otherwise crowd out real fixtures, so they are skipped. Turn this on to include them.

## Actor input object example

```json
{
  "sport": "basketball",
  "league": "NHL",
  "maxEvents": 10,
  "includeSimulated": false
}
```

# Actor output Schema

## `results` (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 = {
    "league": "NHL"
};

// Run the Actor and wait for it to finish
const run = await client.actor("zen-studio/fanduel-odds").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 = { "league": "NHL" }

# Run the Actor and wait for it to finish
run = client.actor("zen-studio/fanduel-odds").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 '{
  "league": "NHL"
}' |
apify call zen-studio/fanduel-odds --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zen-studio/fanduel-odds"
        }
    }
}

```

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/oLjv3CSV3BhHm5dGN/builds/UyCxWeqMRynhnwYCJ/openapi.json
