# Fanduel Odds Scraper (`mrdoe/fanduel-odds-scraper`) Actor

Scrape FanDuel betting odds, sports odds, live and pre-match odds for NFL, NBA, MLB, NHL, soccer and more. Extract moneyline, spreads, run lines, puck lines, over/under and player props with American and decimal prices for odds comparison and analysis.

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

## Pricing

from $2.30 / 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?

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

![Website Preview](./assets/website-preview.png)

### What does FanDuel Odds Scraper do?

FanDuel Odds Scraper collects betting odds from FanDuel Sportsbook and returns them as clean, ready-to-use data — one row per match. Pick a sport (or paste a match URL), press **Start**, and download a dataset with the two teams, league, start time, live status, and **prices for the main markets** — moneyline, spread / run line / puck line, and totals (over/under) — plus a full `markets` array with every other line FanDuel lists for the match. Every price comes in both **American and decimal** formats.

Use it for odds comparison, line shopping, closing-line value analysis, model back-testing, and trading dashboards across US sports and soccer.

### Why use FanDuel Odds Scraper?

- **One of the largest US sportsbooks** – FanDuel's line is a core reference for the American market.
- **Prices you can use immediately** – `odds.moneyline.home`, `odds.total.over`, `odds.spread.line`. No decoding.
- **American and decimal** – both formats on every price.
- **Pre-match and live** – switch between the pre-match board and the in-play feed, or take both.
- **Whole sports in one run** – point it at a sport and it walks the board.
- **Every line kept** – alternate spreads, totals, period and prop markets are all in the `markets` array.
- **Clean, normalised output** – odds as numbers, ISO start times, deduplicated by match.

### What makes this different?

Most FanDuel data online is stale screenshots or partial exports. This Actor returns the live board: the three main markets flattened into named fields (`moneyline`, `spread`, `total`) with home / away / draw / over / under selections and the line already attached, while the complete market list — including alternates and period markets — stays available in `markets`. It also resolves each match's league name and start time, and works for a chosen US state so the lines match what a bettor there actually sees.

### What data can you extract?

| Field                 | Description                                          |
| --------------------- | -------------------------------------------------- |
| `matchId`             | FanDuel event ID                                   |
| `url`                 | Match page URL on sportsbook.fanduel.com           |
| `bookmaker`           | Always `FanDuel`                                   |
| `sport` / `sportId`   | Sport                                              |
| `league` / `leagueId` | Competition                                        |
| `country`             | Country code of the competition                    |
| `home` / `away`       | Team names                                         |
| `startTime`           | Scheduled start (ISO 8601)                         |
| `status` / `isLive`   | `prematch` or `live`                               |
| `odds`                | Tidy main markets — see below                      |
| `markets`             | Every priced market line for the match             |
| `totalMarkets`        | Number of market lines in the row                  |
| `scrapedAt`           | ISO timestamp of collection                        |

**The `odds` object:**

```json
{
    "moneyline": { "home": 1.45, "away": 2.84, "draw": null },
    "spread": { "line": 1.5, "home": 2.04, "away": 1.8 },
    "total": { "line": 7.5, "over": 1.91, "under": 1.91 }
}
```

### How to use FanDuel Odds Scraper

1. Open the Actor.
2. Choose a **Feed** (pre-match / live / both) and one or more **Sports**.
3. Optional — set the **State** whose lines you want (`nj`, `pa`, `mi`, `va`, `oh`, `il`, `co`...).
4. Optional — paste **Match URLs** from sportsbook.fanduel.com for individual matches.
5. Set **Max matches** and press **Start**.
6. Download the dataset as JSON, CSV, Excel, or XML, or use the API.

### Input Parameters

| Parameter            | Type    | Required | Default          | Description                                                                                        |
| -------------------- | ------- | -------- | ---------------- | ------------------------------------------------------------------------------------------------ |
| `mode`               | String  | No       | `prematch`       | `prematch`, `live` (in-play), or `both`.                                                         |
| `sports`             | Array   | No       | `["Soccer"]`     | Sport names (`Soccer`, `NFL`, `NBA`, `MLB`, `NHL`, `MMA`, `Boxing`, `Cricket`, `Rugby Union`) or FanDuel event-type IDs. `["all"]` for every supported sport. Leave empty to use only match URLs. |
| `matchUrls`          | Array   | No       | –                | sportsbook.fanduel.com match page URLs.                                                          |
| `maxMatches`         | Integer | No       | 5                | Maximum matches per sport or run. Raise for a full export (the form prefills 30).                |
| `region`             | String  | No       | `nj`             | Two-letter US state code whose FanDuel lines to read.                                            |
| `includeMarkets`     | Boolean | No       | `true`           | Keep the full `markets` array next to the tidy `odds` object.                                    |
| `useCache`           | Boolean | No       | `false`          | Reuse match records from an earlier run.                                                         |
| `proxyConfiguration` | Object  | No       | US Residential   | FanDuel Sportsbook is US-only, so a US proxy is required and used by default.                    |

### Output Data

```json
{
    "matchId": 36020767,
    "url": "https://sportsbook.fanduel.com/baseball/arizona-diamondbacks-v-philadelphia-phillies-36020767",
    "bookmaker": "FanDuel",
    "sport": "Baseball",
    "sportId": 7511,
    "league": "MLB",
    "leagueId": 11196870,
    "country": "US",
    "home": "Arizona Diamondbacks",
    "away": "Philadelphia Phillies",
    "startTime": "2026-09-02T01:40:00.000Z",
    "status": "prematch",
    "isLive": false,
    "totalMarkets": 98,
    "odds": {
        "moneyline": { "home": 1.45, "away": 2.84 },
        "spread": { "line": 1.5, "home": 2.04, "away": 1.8 },
        "total": { "line": 7.5, "over": 1.91, "under": 1.91 }
    },
    "markets": [
        {
            "market": "Moneyline",
            "marketType": "MONEY_LINE",
            "isAlternate": false,
            "status": "OPEN",
            "prices": [
                { "selection": "home", "line": null, "priceAmerican": -220, "priceDecimal": 1.45 },
                { "selection": "away", "line": null, "priceAmerican": 184, "priceDecimal": 2.84 }
            ]
        }
    ],
    "scrapedAt": "2026-09-02T00:15:00.000Z"
}
```

### Usage Examples

**Today's MLB prices**

- `mode`: `prematch`, `sports`: `["MLB"]`, `maxMatches`: 50

**Live NBA odds**

- `mode`: `live`, `sports`: `["NBA"]`

**Soccer moneylines across leagues**

- `mode`: `prematch`, `sports`: `["Soccer"]`, `maxMatches`: 200

**One match, every line**

- `sports`: `[]`, `matchUrls`: a sportsbook.fanduel.com match URL

### Tips for Best Results

- Set `region` to the state you care about — FanDuel's lines and available markets vary by state.
- Spread and total lines appear closer to game time; matches several days out may show moneyline only.
- American and decimal are both provided — use whichever your model needs.
- For closing-line value work, schedule the Actor near start time and diff the `odds` against an earlier run.

### Known Limitations

- FanDuel Sportsbook operates only in certain US states; a US proxy is required and some sports are seasonal.
- Odds move constantly; a row is a snapshot at collection time.
- Live markets are briefly suspended around scoring events, so some prices can be missing.
- Matches far in the future may carry only the moneyline until FanDuel posts the rest.
- Player-prop markets are included in `markets` when FanDuel exposes them on the match page, but same-game-parlay-only markets may not be.

### Integrations

Connect results to Google Sheets, Make, Zapier, Slack, or your own systems via the Apify API and webhooks. Schedule runs to build an odds history.

### Export Formats

JSON, CSV, Excel, and XML from the Dataset tab or the Apify API.

### Frequently Asked Questions

#### How many matches can I collect?

`maxMatches` applies per sport. Raise it for a full export of a sport's board.

#### Can I target one match?

Yes — paste its **Match URL** from sportsbook.fanduel.com and set `sports` to empty.

#### Why are some odds fields null?

Not every match offers every market — soccer moneylines are 3-way (with `draw`), US sports are 2-way, and spreads/totals may not be posted yet for distant fixtures.

#### Does it cover live betting?

Yes. Set `mode` to `live` (or `both`). Live rows are marked `isLive: true`.

#### Why is a US proxy required?

FanDuel Sportsbook is only accessible from inside the United States. The Actor uses Apify US residential proxy by default.

#### How are duplicates handled?

Matches are deduplicated by FanDuel event ID within a run.

#### How fresh is the data?

Every run reads the live odds feed. Schedule the Actor to keep an odds history.

#### Does the cache affect repeated runs?

With **Use cache** on, a match already collected earlier is reused instead of re-requested, which is faster but can return an older price. Leave it off for the current line.

### Support

Found a problem or want another market added? Open an issue on the Actor's **Issues** tab in the Apify Console.

### Legal / Responsible Use

You are responsible for how you use this Actor and the data it collects, including compliance with FanDuel's Terms of Use and the gambling and data-protection laws that apply to you. This Actor collects publicly displayed betting odds for analysis; it does not place bets or access any account. Gambling is age-restricted and regulated and available only where licensed — check your local rules before using odds data commercially. If you or someone you know has a gambling problem, call 1-800-GAMBLER.

# Actor input Schema

## `mode` (type: `string`):

Which odds to collect: pre-match, live (in-play), or both.

## `sports` (type: `array`):

Sports to collect, by name ("Soccer", "NFL", "NBA", "MLB", "NHL", "MMA", "Boxing", "Cricket", "Rugby Union") or numeric FanDuel event-type ID. Use \["all"] for every supported sport.

## `matchUrls` (type: `array`):

Optional. Paste individual FanDuel Sportsbook match page URLs, for example https://sportsbook.fanduel.com/basketball/... . Each returns every market for that match.

## `maxMatches` (type: `integer`):

Maximum number of matches to collect per sport or run. Raise this for a full export.

## `region` (type: `string`):

US state whose FanDuel Sportsbook odds to read (two-letter code, for example nj, pa, mi, va, oh, il, co). Lines differ slightly between states.

## `includeMarkets` (type: `boolean`):

Add a `markets` array with every line on top of the tidy `odds` object. Turn off for smaller rows.

## `useCache` (type: `boolean`):

Reuse match records collected in an earlier run. Disabled by default so every run returns live odds.

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

FanDuel Sportsbook is only available inside the United States, so a US proxy is required. Apify Residential in the US is used by default.

## Actor input object example

```json
{
  "mode": "prematch",
  "sports": [
    "Soccer"
  ],
  "matchUrls": [],
  "maxMatches": 30,
  "region": "nj",
  "includeMarkets": true,
  "useCache": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `matches` (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 = {
    "sports": [
        "Soccer"
    ],
    "maxMatches": 30,
    "region": "nj",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("mrdoe/fanduel-odds-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 = {
    "sports": ["Soccer"],
    "maxMatches": 30,
    "region": "nj",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("mrdoe/fanduel-odds-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 '{
  "sports": [
    "Soccer"
  ],
  "maxMatches": 30,
  "region": "nj",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call mrdoe/fanduel-odds-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mrdoe/fanduel-odds-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/O1RqDzPe7ae42lA05/builds/G8tfOQSaFHoGCtOkr/openapi.json
