# Sportsbook Review Scraper - NFL, NBA & MLB Odds, Betting Lines (`parseforge/sportsbook-review-scraper`) Actor

Scrape NFL, NBA, MLB, NHL and college odds from SportsbookReview. Point spreads, moneylines and totals from 5 sportsbooks, with opening lines, line movement, betting splits and history back to 2008.

- **URL**: https://apify.com/parseforge/sportsbook-review-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 game rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

[![ParseForge](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner.jpg)](https://apify.com/parseforge?fpr=vmoqkp)

### Sportsbook Review Scraper - NFL, NBA & MLB Odds and Betting Lines

**Scrape NFL odds, NBA odds, MLB odds and betting lines for 11 leagues, from five sportsbooks at once.** Every game comes back with each book's opening and current number, the best price on the board, how far the line moved, what percentage of the public is on each side, and — for games already played — the final score with the ATS and over/under result already graded. No login, no API key, no proxy. Export to CSV, JSON, Excel, or XML.

Odds APIs charge a monthly subscription and quote one blended price per game. This reads the same public SportsbookReview pages your browser does, keeps every book's number separate so you can shop the line, and reaches back to **2008** for closed lines.

| Who uses it | What they scrape SportsbookReview for |
|---|---|
| Bettors and handicappers | Line shopping across five books, and fading a public that is 70% on one side |
| Quant and model builders | Years of opening and closing lines to backtest against real results |
| Odds and media sites | A normalised feed of spreads, moneylines and totals for 11 leagues |
| Affiliate and content teams | Live numbers for comparison pages, with each book's affiliate link attached |
| Data scientists | Labelled market data: no-vig probabilities, hold, movement, and graded outcomes |

### What it does

This Actor collects the SportsbookReview betting board for a league and a date, and returns each game as one flat row. Every row carries:

- 🧾 **The game:** teams, kickoff, venue, city, state, country, status, and — for MLB — both starting pitchers with their throwing hand.
- 📊 **Every book's line:** BetMGM, FanDuel, DraftKings, bet365 and Fanatics, each with its **opening** number and its **current** number.
- 🛒 **Line shopping, solved:** the best price and best number on the board for every side, with the book that has it named.
- 📈 **Movement:** how far the consensus spread, total and price travelled from the opener, and which way.
- 👥 **Betting splits:** the public betting percentage on each side of the moneyline, point spread and over/under.
- 🧮 **Market maths already done:** implied probability, book hold, no-vig fair probability and fair price, and the edge line shopping buys you.
- 🏁 **Graded results** on finished games: final score, margin, winner, ATS result, over/under result, and the period-by-period box score.
- ⚾ **Live state** where the sport publishes it: inning, half, outs, hits and errors for baseball.

Turn on the optional blocks and each row also carries the moneyline board, the totals board, half and quarter lines, the **timestamped line-movement series** for every book, and both teams' season form.

Results export to CSV, JSON, Excel, or XML, or stream from the API.

### What you can do with SportsbookReview data

**🛒 Shop every line before you bet.**

One row already names the book with the best price on each side and the best number on each spread and total, so the comparison is a column, not a workflow.

**🕰️ Backtest a model on real closing lines.**

Point it at a league and a date range and pull years of openers, closers and final results in one schema. Nine of the eleven leagues go back to 2008.

**👥 Fade the public.**

Filter to the games where one side holds 70% or more of the tickets, and read what the line did while the crowd piled in.

**🚂 Catch steam moves.**

Ask for only the games whose consensus spread moved a point or more from the opener, then read the timestamped series to see which book moved first.

**💰 Find the softest market.**

Sort by hold percentage and no-vig fair price to see where the vig is thin and which book is out of line with the other four.

### Why choose this scraper

| | What you get |
|---|---|
| **No login, no key, no proxy** | It reads public pages. There is no account to create, no session to keep alive, and no proxy line on your bill. |
| **Five books kept separate** | Opening and current numbers per book, not one blended average. That is what makes line shopping possible. |
| **17 years of closed lines** | Verified back to 2008 for the nine date-scheduled leagues. Most odds feeds start when you subscribe. |
| **Results already graded** | Finished games carry the final score plus the ATS and over/under result, so a backtest needs no join. |
| **Movement, not just a snapshot** | Opener, current, direction, and an optional timestamped series per book. |
| **Market maths in the row** | Implied probability, hold, no-vig fair odds and line-shopping edge, computed per book and per game. |
| **11 leagues, one schema** | NFL, NCAAF, NBA, NCAAB, MLB, NHL, WNBA, CFL, EPL, Champions League and MLS return identical fields. |
| **Opt-in extras, off by default** | Moneyline, totals, period lines, line history, matchup stats and futures are each a checkbox. Leave them off and you are never billed for them. |
| **Filter without buying** | A total or spread filter reads the board it needs and then drops those columns, so you can narrow a run without paying for data you do not keep. |

### How it compares

Be clear about the trade-offs before you pick this one.

**Five sportsbooks, not twenty.** SportsbookReview shows BetMGM, FanDuel, DraftKings, bet365 and Fanatics to anonymous visitors, and this Actor returns all five. If you need Pinnacle, Circa or a European book, you need a different source.

**Football has no historical dates.** SportsbookReview serves NFL and NCAA Football by week, for the current season only — a date on those two leagues is silently ignored by the site and returns the current board. The Actor warns you and uses weeks instead. The other nine leagues take any date back to 2008.

**No player props.** This is the game board: spreads, moneylines, totals, periods and futures. Props are not on these pages.

| Feature | ParseForge | lulzasaur | scrapemint |
|---|---|---|---|
| Source | SportsbookReview | SportsbookReview | Aggregated feed |
| Opening **and** current line per book | Yes | Current only | Current only |
| Best price and best number, book named | Yes | No | No |
| Historical dates back to 2008 | Yes, 9 leagues | No | No |
| Timestamped line-movement series | Optional | No | No |
| Public betting percentages | Yes | No | No |
| Graded ATS / over-under results | Yes | No | No |
| No-vig fair odds and hold % | Yes, per book | No | No |
| Half, quarter and period lines | Optional | No | No |
| Futures markets | Optional | No | No |
| Team season form on the row | Optional | No | No |
| Price per 1,000 games | **$7.00** | $10.00 | $12.00 |

We are the cheapest of the three per row and the only one that returns openers, movement, public splits and graded results. The honest caveat is coverage of books: all three read the same five-book board.

### What a game looks like

Every game returns as one flat JSON row. Here is a real record, book list trimmed to two:

```json
{
  "recordType": "game",
  "gameId": 370242,
  "league": "MLB",
  "leagueSlug": "mlb-baseball",
  "market": "pointspread",
  "scope": "full-game",
  "gameDate": "2026-08-24",
  "startDate": "2026-08-24T22:40:00.000Z",
  "status": "final",
  "statusText": "Final",
  "awayTeam": "Tampa Bay Rays",
  "awayTeamShort": "TB",
  "homeTeam": "Detroit Tigers",
  "homeTeamShort": "DET",
  "matchup": "TB @ DET",
  "awayStarter": "Drew Rasmussen",
  "awayStarterHand": "R",
  "homeStarter": "Framber Valdez",
  "homeStarterHand": "L",
  "venueName": "Comerica Park",
  "venueCity": "Detroit",
  "venueState": "MI",
  "venueCountry": "USA",
  "awayScore": 4,
  "homeScore": 1,
  "totalPoints": 5,
  "margin": -3,
  "winner": "away",
  "atsResult": "away",
  "totalResult": "under",
  "periodType": "Inning",
  "awayScoreByPeriod": [2, 0, 0, 1, 0, 1, 0, 0, 0],
  "homeScoreByPeriod": [0, 0, 0, 1, 0, 0, 0, 0, 0],
  "publicBetPercentHome": 33.63,
  "publicBetPercentAway": 66.37,
  "publicOverPercent": 53.97,
  "publicUnderPercent": 46.03,
  "publicFadeSide": "away-ml",
  "booksWithOdds": 5,
  "odds": [
    {
      "sportsbook": "betmgm",
      "sportsbookName": "BetMGM",
      "openingSpreadHome": 1.5,
      "openingSpreadAway": -1.5,
      "openingPriceHome": -160,
      "openingPriceAway": 135,
      "spreadHome": 1.5,
      "spreadAway": -1.5,
      "priceHome": -145,
      "priceAway": 120,
      "impliedProbHome": 0.59184,
      "impliedProbAway": 0.45455,
      "holdPercent": 4.638,
      "noVigProbHome": 0.5656,
      "noVigProbAway": 0.4344,
      "spreadMove": 0,
      "priceMoveHome": 15,
      "priceMoveAway": -15
    },
    {
      "sportsbook": "fanduel",
      "sportsbookName": "FanDuel",
      "openingPriceHome": -164,
      "openingPriceAway": 136,
      "spreadHome": 1.5,
      "priceHome": -152,
      "priceAway": 126,
      "holdPercent": 4.565,
      "noVigProbHome": 0.57684,
      "noVigProbAway": 0.42316,
      "priceMoveHome": 12
    }
  ],
  "consensusSpreadHome": 1.5,
  "consensusTotal": null,
  "consensusPriceHome": -145,
  "consensusPriceAway": 120,
  "openingSpreadHome": 1.5,
  "spreadMovement": 0,
  "priceMovementHome": 15,
  "lineDirection": "flat",
  "bestPriceHome": -143,
  "bestPriceHomeBook": "DraftKings",
  "bestPriceAway": 130,
  "bestPriceAwayBook": "bet365",
  "bestSpreadHome": 1.5,
  "bestSpreadHomeBook": "BetMGM",
  "decimalPriceHome": 1.6993,
  "fairProbHome": 0.5656,
  "fairProbAway": 0.4344,
  "fairPriceHome": -130,
  "marketHoldPercent": 4.565,
  "lineShoppingEdgeHome": 0.336,
  "spreadDisagreement": 0,
  "totalsConsensus": 7.5,
  "totalsOpening": 7.5,
  "totalsMovement": 0,
  "totalsBestOver": -110,
  "totalsBestOverBook": "BetMGM",
  "totalsBestUnder": -102,
  "totalsBestUnderBook": "FanDuel",
  "totalsLowestNumber": 7.5,
  "totalsHighestNumber": 7.5,
  "url": "https://www.sportsbookreview.com/scores/mlb-baseball/matchup/370242/",
  "sourceUrl": "https://www.sportsbookreview.com/betting-odds/mlb-baseball/pointspread/full-game/?date=2026-08-24",
  "scrapedAt": "2026-08-25T16:56:04.190Z"
}
```

A base row carries **104 fields**, with 31 per sportsbook inside `odds[]`. Turn every optional block on and a row reaches **157 fields**. A futures row is its own 23-field shape.

### Configure the run

Pick leagues and a date, or paste SportsbookReview URLs directly. Filters run as each game is read, so only matches reach your dataset and only matches are billed. The Input tab lists every parameter.

**Filters can read a block you did not buy.** Set `minTotal` on a point-spread run and the Actor fetches the totals board, filters on it, and then drops the totals columns again — you pay for the page, not for columns you never receive. Tick **Add totals odds** if you want to keep them.

Today's board for one league:

```json
{ "leagues": ["nfl-football"], "maxItems": 50 }
```

A month of MLB history with all three markets on every row:

```json
{ "leagues": ["mlb-baseball"], "dateFrom": "2026-07-01", "dateTo": "2026-07-31", "includeMoneyline": true, "includeTotals": true, "maxItems": 500 }
```

Fade the public — only games where one side holds 70% of tickets, with the movement series attached:

```json
{ "leagues": ["mlb-baseball"], "dates": ["2026-08-24"], "minPublicBetPercent": 70, "includeLineHistory": true, "maxItems": 100 }
```

Steam moves only — games whose spread moved half a point or more off the opener:

```json
{ "leagues": ["nfl-football"], "minSpreadMovement": 0.5, "includeLineHistory": true, "maxItems": 100 }
```

Soccer three-way board with totals, two books only:

```json
{ "leagues": ["english-premier-league", "major-league-soccer"], "includeTotals": true, "sportsbooks": ["fanduel", "draftkings"] }
```

Futures — every team's title, conference and division price:

```json
{ "leagues": ["nfl-football"], "includeFutures": true, "maxItems": 300 }
```

### Pricing

Pay-per-event. You are billed per row written, plus a small fee for each board page fetched and a $0.054 run-start fee. Filtered-out games cost nothing, and an optional block that returns no data is never charged.

| Event | Price | When it fires |
|---|---|---|
| Run start | $0.054 | Once per run |
| Board page | $0.005 | Each SportsbookReview page fetched, whatever it yields |
| Game row | $0.007 | Each game written — the primary event |
| Moneyline block | $0.004 | Only with **Add moneyline odds** on |
| Totals block | $0.004 | Only with **Add totals odds** on |
| Period block | $0.005 | Only with **Add half / quarter / period odds** on |
| Line-movement series | $0.006 | Only with **Add timestamped line movement** on |
| Team matchup stats | $0.008 | Only with **Add team matchup stats** on |
| Futures selection | $0.005 | Only with **Add futures markets** on |

| Games collected, defaults | Approximate cost |
|---|---|
| 100 | $0.79 |
| 1,000 | $7.43 |
| 10,000 | $73.80 |

The board-page fee depends on how many games a slate holds, so these are mid estimates. A college football week puts 200 games on one page and costs $0.005 for all of them; a ten-game MLB slate costs $0.005 for ten. Measured on the platform: a 144-game college football run with **every** optional block turned on billed $4.06 in total.

The six optional events are off by default. A run that leaves them off pays the run-start fee, $0.005 per board page, and $0.007 per game — nothing else. Verified on a production run: with defaults, the only events charged were `apify-actor-start`, `odds-page` and `game-odds`.

**Why $7.00 per 1,000 and not $3.00.** The other SportsbookReview scraper on the Store charges $10.00 per 1,000 and returns the current line only. The most-used generic odds Actor charges $12.00. We are the cheapest of the three, and each of our rows also carries the opener, the movement, the best price with its book, the public split, the no-vig maths and — on a finished game — the graded result. If all you need is one current number per game and nothing else, a $3.00 Actor will do it more cheaply.

### Free users

Free-plan runs return up to 10 rows as a preview. [Upgrade your Apify plan](https://console.apify.com/sign-up?fpr=vmoqkp) to collect up to 1,000,000 rows per run.

### Run it

1. [Create a free Apify account with $5 in credit](https://console.apify.com/sign-up?fpr=vmoqkp).
2. Open the [Sportsbook Review Scraper](https://apify.com/parseforge/sportsbook-review-scraper?fpr=vmoqkp).
3. Pick your leagues, set a date or a week, tick any extras, and click **Start**.
4. Export the results as CSV, Excel, JSON, or XML from the **Dataset** tab.

Run it programmatically through the [Apify API](https://docs.apify.com/api/v2) or the [ApifyClient](https://docs.apify.com/api/client/js) for JavaScript and Python. Schedule it to capture the closing line every day.

### Use with AI agents (MCP)

Give an AI agent live access to the betting board through the Model Context Protocol. Add the Actor to Claude, Cursor, or any MCP client:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=parseforge/sportsbook-review-scraper"
```

Then prompt it in plain language:

- *"Pull tonight's NBA board and tell me which games have the biggest price difference between books."*
- *"Get every MLB game from July and list the ones where the public was over 70% on the loser."*
- *"Show me the NFL Week 5 games whose total moved more than a point, and which book moved first."*

Copy this into ChatGPT, Claude, or Cursor to start:

```
Use the Apify Actor "parseforge/sportsbook-review-scraper" to collect betting lines from SportsbookReview. Input: { "leagues": ["nfl-football"], "dateFrom": "YYYY-MM-DD", "dateTo": "YYYY-MM-DD", "includeMoneyline": true, "includeTotals": true, "maxItems": 200 }. It returns one row per game with each of five sportsbooks' opening and current line, the best price and the book holding it, line movement, public betting percentages, no-vig fair odds, and graded ATS / over-under results on finished games. NFL and NCAA Football use "weeks" (Week1…Week18) instead of dates. Call it with the ApifyClient and my APIFY_TOKEN.
```

### Troubleshooting

**Why did my NFL date get ignored?**

SportsbookReview does not serve NFL or NCAA Football by date — it serves them by week, for the current season only. A date on those two leagues returns the current board on the site itself, so the Actor warns you and scrapes that board. Use `weeks` instead: `Week1` … `Week18`, or `PreSeasonWeek1` … `PreSeasonWeek3`.

**Why am I getting no results?**

Most often the league had no games that day. MLS and the CFL play a handful of fixtures a week, and the Champions League only on matchdays. Try a nearby date, or turn off **Skip games with no posted line** to see the bare schedule.

**Why are there fewer rows than games on the page?**

Games no book has priced yet are dropped by default and never billed. A football week that is still months away is the usual case: the schedule is published long before any book posts a number, so `Week5` in August returns 115 games and zero lines. Ask for a week that is closer, or set `onlyGamesWithOdds` to false to keep the bare schedule.

**Why is `consensusTotal` empty?**

The base row carries the market you chose. On a point-spread run there is no total on it — tick **Add totals odds** and the row gains `totalsConsensus`, the per-book totals, and the graded over/under result.

**Why is there no line history for my soccer game?**

SportsbookReview has no line-history page for EPL, the Champions League or MLS; the URL returns a server error. The Actor detects this, skips the request, and does not charge for it.

**Why is `homeAtsRecord` empty?**

Season form is whatever the sport publishes. Baseball tracks win-loss and over/under records but no ATS record; football and basketball track ATS. Soccer matchups carry no stats block at all, and are never charged for one.

**A field stopped filling.**

SportsbookReview changed a page's shape. Email us with your run ID and we will fix the mapping.

### FAQ

| Question | Answer |
|---|---|
| Do I need a SportsbookReview account or an API key? | No. It reads the same public pages an anonymous browser gets. |
| Do I need a proxy? | No. The site serves these pages without one, so there is no proxy cost. A proxy field exists if your own network is blocked. |
| Which sportsbooks are covered? | BetMGM, FanDuel, DraftKings, bet365 and Fanatics — the five SportsbookReview shows publicly. |
| How far back does the history go? | Verified to 2008 for the nine date-scheduled leagues. NFL and NCAA Football are current-season only, by week. |
| Which leagues? | NFL, NCAA Football, NBA, NCAA Basketball, MLB, NHL, WNBA, CFL, English Premier League, UEFA Champions League and MLS. |
| Does it return player props? | No. It returns the game board: spreads, moneylines, totals, period lines and futures. |
| Can I get live in-play odds? | It returns the board as SportsbookReview publishes it, including live scores and, for baseball, the current inning and count. It is not a low-latency in-play feed. |
| How do soccer odds work? | Soccer has no handicap board, so the primary market is the real three-way home / draw / away price. Moneyline returns the two-way price with the draw removed. |
| Are the results graded? | Yes. Finished games carry the final score, margin, winner, ATS result and over/under result. |
| Is this an official SportsbookReview product? | No. It is unofficial and reads only publicly available data. |

### Related actors

- [FanDuel Sportsbook Odds Scraper](https://apify.com/parseforge/fanduel-scraper?fpr=vmoqkp): the full FanDuel board, straight from the source.
- [DraftKings DFS Scraper](https://apify.com/parseforge/draftkings-scraper?fpr=vmoqkp): DraftKings daily-fantasy contests, salaries and slates.
- [NFL Stats Scraper](https://apify.com/parseforge/nfl-stats-scraper?fpr=vmoqkp): official NFL team and player statistics.
- [NBA Stats Official Scraper](https://apify.com/parseforge/nba-stats-scraper?fpr=vmoqkp): box scores and advanced stats from stats.nba.com.
- [MLB Stats Scraper](https://apify.com/parseforge/mlb-stats-scraper?fpr=vmoqkp): schedules, box scores and player stats from the MLB API.
- [Equibase Scraper](https://apify.com/parseforge/equibase-scraper?fpr=vmoqkp): horse racing entries, results and charts.

Browse the full [ParseForge collection](https://apify.com/parseforge?fpr=vmoqkp) for more scrapers.

🆘 **Need help?** Email parseforge@protonmail.com with your run ID, your input, and what you expected.

⚠️ **Disclaimer.** This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by SportsbookReview or any sportsbook named in its output. It collects only publicly available data. Betting odds are provided for informational purposes and are not betting advice. You are responsible for complying with SportsbookReview's terms, with the gambling laws of your jurisdiction, and with applicable data-protection law. 21+. If gambling is a problem for you, call 1-800-GAMBLER.

# Actor input Schema

## `leagues` (type: `array`):

Leagues to pull odds for. Every league returns the same fields.

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

Paste SportsbookReview odds or futures URLs to scrape exactly those pages. When set, the league, date and week fields below are ignored.

## `dateFrom` (type: `string`):

First slate day, as YYYY-MM-DD. SportsbookReview keeps closed lines back to 2008, so historical dates work for every league except NFL and NCAA Football, which are selected by week instead. Leave both dates empty for today's board.

## `dateTo` (type: `string`):

Last slate day, as YYYY-MM-DD. Defaults to the same day as Date from. Capped at 400 days per run.

## `dates` (type: `array`):

Exact days to scrape, as YYYY-MM-DD. Takes priority over the date range.

## `weeks` (type: `array`):

NFL and NCAA Football weeks, written the way SportsbookReview writes them: Week1 … Week18, PreSeasonWeek1 … PreSeasonWeek3. Football is the only schedule SportsbookReview serves by week, and only for the current season — dates do not work there. Ignored for every other league.

## `oddsMarket` (type: `string`):

The market the base row carries. Point spread also fills in the run line (MLB) and puck line (NHL); for soccer it returns the real three-way home / draw / away board, because SportsbookReview has no handicap board for soccer. Moneyline is the two-way price with the draw removed.

## `oddsScope` (type: `string`):

Which part of the game the base row prices. Full game is what most boards quote; halves, quarters and periods depend on the league and are not always posted.

## `includeMoneyline` (type: `boolean`):

Fetches the moneyline board and merges every book's price, draw price, hold and no-vig probability into the same row. One extra page request per slate. Off by default, and never charged when Moneyline is already your primary market.

## `includeTotals` (type: `boolean`):

Fetches the over/under board and merges every book's total, prices, best number and hold into the same row. One extra page request per slate. Off by default, and never charged when Totals is already your primary market.

## `includePeriodOdds` (type: `boolean`):

Fetches the scopes listed below and appends them as a periodOdds array on each game. One extra page request per scope per slate.

## `periodScopes` (type: `array`):

Scopes to fetch when the box above is ticked. Not every league posts every scope; a scope with no lines is skipped and not charged.

## `includeLineHistory` (type: `boolean`):

Every price change SportsbookReview recorded for each book, with a timestamp: spread, total and moneyline series, plus the high, low and swing of each. One extra page request per slate. Not available for the three soccer leagues, where the page does not exist.

## `includeMatchupStats` (type: `boolean`):

Season form for both teams from the matchup page: win-loss and over/under records, ATS record where the sport tracks one, moneyline units, and the sport's own box-score averages. One extra request per game, so this is the most expensive box on the list. Soccer matchups carry no stats block and are never charged.

## `includeFutures` (type: `boolean`):

Scrapes the league's futures board too — title, conference and division winners — and writes one row per selection with every book's price. One extra page request per league.

## `sportsbooks` (type: `array`):

Keep only these books in every odds array. Leave empty for all five.

## `teamQuery` (type: `array`):

Keep only games where either side matches one of these, by city, nickname, full name or abbreviation. Case-insensitive.

## `gameStatus` (type: `string`):

Keep only games in this state. Final games carry scores and graded ATS / over-under results.

## `onlyGamesWithOdds` (type: `boolean`):

Drops games no book has priced yet. Leave on unless you want the bare schedule too.

## `minBooks` (type: `integer`):

Keep only games priced by at least this many books. Useful when you compare prices and need a real market.

## `minSpread` (type: `number`):

Keep only games whose consensus home spread is at or above this. Home favourites are negative, so -7 keeps everything from a 7-point home favourite up to any home underdog.

## `maxSpread` (type: `number`):

Keep only games whose consensus home spread is at or below this.

## `minTotal` (type: `number`):

Keep only games whose consensus over/under is at or above this.

## `maxTotal` (type: `number`):

Keep only games whose consensus over/under is at or below this.

## `minPriceHome` (type: `integer`):

Keep only games whose consensus home price is at or above this, in American odds. Use 100 to keep home underdogs only.

## `maxPriceHome` (type: `integer`):

Keep only games whose consensus home price is at or below this, in American odds. Use -150 to keep heavy home favourites only.

## `minPublicBetPercent` (type: `integer`):

Keep only games where one side holds at least this share of public tickets. Set to 70 to find the games the crowd is piled onto.

## `maxPublicBetPercent` (type: `integer`):

Keep only games where no side exceeds this share of public tickets, in other words the evenly split board.

## `minSpreadMovement` (type: `number`):

Keep only games whose consensus spread moved at least this many points from the opener, in either direction.

## `minTotalMovement` (type: `number`):

Keep only games whose consensus total moved at least this much from the opener, in either direction.

## `maxHoldPercent` (type: `number`):

Keep only games whose median book margin is at or below this. A tighter market usually means a sharper number.

## `startTimeFrom` (type: `string`):

ISO timestamp, for example 2026-09-13T17:00:00Z. Keeps only games starting at or after it.

## `startTimeTo` (type: `string`):

ISO timestamp. Keeps only games starting at or before it.

## `venueState` (type: `array`):

Two-letter state or province codes, for example NY or CA.

## `venueCountry` (type: `array`):

Country as SportsbookReview writes it, for example USA, CAN or England.

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

Hard cap on rows written and billed. The run stops as soon as it is reached.

## `maxConcurrency` (type: `integer`):

How many games are enriched at once. Raise it for long historical ranges; lower it if you hit timeouts.

## `maxRequestRetries` (type: `integer`):

Retries per failed page, with exponential backoff.

## `requestTimeoutSecs` (type: `integer`):

Per-request timeout.

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

SportsbookReview serves these pages to anonymous clients, so this Actor needs no proxy and leaves it off. Turn it on only if your own network is blocked.

## Actor input object example

```json
{
  "leagues": [
    "nfl-football"
  ],
  "dates": [],
  "weeks": [],
  "oddsMarket": "pointspread",
  "oddsScope": "full-game",
  "includeMoneyline": false,
  "includeTotals": false,
  "includePeriodOdds": false,
  "periodScopes": [
    "1st-half",
    "2nd-half"
  ],
  "includeLineHistory": false,
  "includeMatchupStats": false,
  "includeFutures": false,
  "sportsbooks": [],
  "teamQuery": [],
  "gameStatus": "any",
  "onlyGamesWithOdds": true,
  "venueState": [],
  "venueCountry": [],
  "maxItems": 200,
  "maxConcurrency": 8,
  "maxRequestRetries": 3,
  "requestTimeoutSecs": 45,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Every game with each sportsbook's opening and current line, best available price, consensus number, line movement, public betting split, and graded ATS / over-under results for finished games

# 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 = {
    "leagues": [
        "nfl-football"
    ],
    "dateFrom": "",
    "dateTo": "",
    "dates": [],
    "weeks": [],
    "teamQuery": [],
    "venueState": [],
    "venueCountry": [],
    "maxItems": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/sportsbook-review-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 = {
    "leagues": ["nfl-football"],
    "dateFrom": "",
    "dateTo": "",
    "dates": [],
    "weeks": [],
    "teamQuery": [],
    "venueState": [],
    "venueCountry": [],
    "maxItems": 200,
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/sportsbook-review-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 '{
  "leagues": [
    "nfl-football"
  ],
  "dateFrom": "",
  "dateTo": "",
  "dates": [],
  "weeks": [],
  "teamQuery": [],
  "venueState": [],
  "venueCountry": [],
  "maxItems": 200
}' |
apify call parseforge/sportsbook-review-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parseforge/sportsbook-review-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/Uzf55cAv0yK7gYxey/builds/spdG8q06CoDHWLCr3/openapi.json
