# SportsLine Scraper - Odds, Expert Picks & Projections (`parseforge/sportsline-scraper`) Actor

Scrape SportsLine betting data across 16 leagues. Odds from seven sportsbooks per game, public betting splits, final scores with graded outcomes back to 2018, expert picks with writeups, futures, injuries and SportsLine model simulations.

- **URL**: https://apify.com/parseforge/sportsline-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)

### SportsLine Scraper - Odds, Expert Picks & Projections

**Scrape SportsLine's betting data across 15 leagues.** Every game comes with the consensus line plus six named sportsbooks, opening and current prices, the share of public bets on each side, and — on finished games — the final score with every market already graded WIN, LOSS or PUSH. Five more datasets sit alongside it: expert picks with the analyst's writeup, futures, injury reports, the handicapper leaderboard and SportsLine's own model simulations. No login, no API key, no proxy. Export to CSV, JSON, Excel, or XML.

SportsLine is CBS Sports' betting arm. Its odds board, its public-money splits and its settled pick history are served by a public API that needs no account, and this Actor reads it directly rather than parsing a page. Measured on the platform on 2026-08-25: 569 rows across all six datasets, with every optional block switched on, finished in 7.3 seconds inside 68 MB. A 1,200-game historical pull took 17 seconds.

| Who uses it | What they scrape SportsLine for |
|---|---|
| Bettors and handicappers | Six books on one row, plus which side the public is on |
| Quants and backtesters | Closing lines and graded outcomes back to October 2018 |
| Model builders | 110,001 archived games with the line, the result and the public split |
| Affiliate and media teams | Futures boards, injury reports and expert records for content pages |
| Tipster-tracking tools | 94,000+ expert picks, all but 41 already settled, with units staked and result |
| Arbitrage and +EV tools | Cross-book price gaps, with the hold and arbitrage check already run |

### What it does

This Actor reads SportsLine's public data API and writes one row per record, tagged with `resultType`. Pick the datasets you want; they share the same league list and filters.

- 🏟️ **Games** — teams, venue, kickoff, TV, weather, plus the consensus line and up to six named books.
- 💰 **Seven price sources per game** — Consensus, DraftKings, FanDuel, BetMGM, Caesars, BetRivers and theScore, each with moneyline, spread and total.
- 📐 **Every price four ways** — American odds, decimal odds, implied probability and profit per $100, opening and current, so you never convert by hand.
- 📊 **Public betting splits** — the share of bets on each side of the moneyline, spread and total.
- 🏁 **Graded history** — finished games carry the final score, period-by-period scoring, and each market side marked WIN, LOSS or PUSH against the closing line.
- 🎯 **Expert picks** — the market, line, price, side and units staked, the analyst's full writeup, their current streak, and the result once it settles.
- 🏆 **Futures** — division, conference, championship, win-total and player-award markets, one row per selection, with the field overround and a de-vigged fair probability.
- 🚑 **Injuries** — the league injury report with designation, body part, estimated return and the beat note.
- 🥇 **Experts** — the handicapper leaderboard with rank, dollars returned to a $100 bettor, streak record and live pick count.
- 🤖 **Simulations** — SportsLine's model picks with a letter grade, a confidence score and a win probability.
- 🧮 **Optional analytics** — bookmaker hold per book, de-vigged fair probability, best price per side with the book that holds it, line-shopping gain in basis points, and a cross-book arbitrage check with the stake split.

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

### Leagues covered

Measured on 2026-08-25. "Archive" is how many past games the API still serves for that league.

| League | Upcoming games | Archive | Expert picks | Futures markets | Injury report |
|---|---|---|---|---|---|
| NFL | 264 | 2,506 | 19,278 | 123 | 324 |
| College Football | 214 | 11,019 | 10,995 | 37 | 207 |
| NBA | 15 | 10,740 | 16,615 | 59 | 77 |
| College Basketball | — | 43,201 | 15,021 | 8 | 810 |
| MLB | 28 | 20,546 | 23,915 | 76 | 277 |
| NHL | 19 | 11,092 | 6,459 | 25 | 70 |
| MLS | 31 | 2,168 | 10 | — | — |
| NWSL | 7 | 711 | 12 | — | — |
| Premier League | 14 | 1,548 | 448 | — | — |
| La Liga | 13 | 1,344 | 177 | — | — |
| Bundesliga | 17 | 1,052 | 167 | — | — |
| Serie A | 16 | 1,535 | 198 | — | — |
| Ligue 1 | 9 | 1,310 | 122 | — | — |
| Champions League | 4 | 1,062 | 694 | 1 | — |
| FIFA World Cup | — | 167 | 281 | — | — |

The upcoming column moves with the calendar — college basketball shows nothing in August and 43,201 archived games. Soccer gets odds and an archive but almost no expert picks, and no futures board. Leave the dates empty and each league returns whatever it is currently showing, so a scheduled run is self-maintaining.

### What you can do with SportsLine data

**📈 Backtest against real closing lines.**

Set a date window and every finished game comes back with the closing spread, total and moneyline, the final score, and each side already marked WIN, LOSS or PUSH. That is the join you normally have to build yourself. Combined with the public betting split on the same row, you can test fade-the-public strategies without stitching two feeds together.

**🥇 Shop every line at once.**

Turn on **Add every sportsbook** and each game carries six named books beside the consensus. Turn on the analytics block and you get each book's hold, the best price per side with the book that has it, and how many basis points shopping is worth — the analytics block reads every book whether or not you buy the price grid, so you can take the analysis alone. Measured on one MLB game: DraftKings held 1.65% on the moneyline against BetRivers' 4.32%.

**🧠 Track handicappers.**

The expert pick dataset is effectively an archive of settled bets: 94,392 picks across every league the day this was written, of which 94,351 had already been graded. Each carries the exact line and price, the units staked, the result, and the analyst's reasoning. Filter to one expert with `expertIds` and you have their full public record.

**🏆 Build a futures page.**

Futures return one row per selection with the market, the price, the field overround and a de-vigged fair probability. NFL alone posts 123 markets: division winners, conference and Super Bowl odds, win totals, playoff berths and player awards.

**🚑 Watch the injury wire.**

The injury dataset returns every listed player with designation, body part, estimated return and the beat writer's note — 810 college basketball players and 324 NFL players on the day measured.

### Why choose this scraper

| | What you get |
|---|---|
| **Six named books, plus consensus** | Not one unnamed aggregate. Six books quoted on the same game in one row, with `booksQuoting` saying how many priced it. |
| **Graded history back to 2018** | Closing line, final score and a WIN/LOSS/PUSH outcome per market side, on 110,001 archived games. |
| **Public money on the same row** | The share of bets on each side, which most odds feeds either omit or sell separately. |
| **Six datasets, one Actor** | Games, expert picks, futures, injuries, experts and model simulations, sharing one league list and one filter set. |
| **No login or API key** | The API this reads is public and anonymous. Nothing to authenticate, nothing to expire. |
| **No proxy cost** | It ran clean from a plain datacenter IP, so no proxy is configured and no proxy line hits your bill. |
| **Opt-in extras, off by default** | Seven separate checkboxes. Leave them off and you are never billed for them. |
| **Filters that cut before billing** | Price bands, spread and total ranges, team lists, date windows and public-money thresholds all run before anything is written. |
| **You can filter on what you did not buy** | Screening by public bet percentage fetches the splits block, filters on it, then drops it. You pay the row rate, not the block. |

### How it compares

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

**This Actor reads SportsLine, not the sportsbooks themselves.** SportsLine refreshes on its own schedule, so these are near-live prices rather than tick-by-tick book feeds. If you need sub-second line movement straight from a book's API, a single-book scraper serves you better. What you get instead is six books normalised into one row, with the public split, the graded result and the fair-probability work already done.

| Feature | ParseForge | harvest/sportsline-picks-scraper |
|---|---|---|
| Odds board with six named books | Yes | No |
| Public betting splits | Optional block | No |
| Graded outcomes and final scores | Yes | No |
| Historical archive | Back to Oct 2018 | No |
| Expert picks with writeups | Yes | Yes |
| Futures markets | Yes | No |
| Injury reports | Yes | No |
| Expert leaderboard and streaks | Yes | No |
| Model simulations with grades | Yes | Yes |
| Line-shopping and arbitrage analytics | Optional block | No |
| Price per 1,000 rows | $7.00 | $15.00 |

The one direct competitor on the Store covers SportsLine's model picks alone, at more than twice the rate, on a single flat event with no filters and no optional blocks.

### What a game row looks like

Every game returns as one JSON row. Here is a real record with five of the six named books trimmed out:

```json
{
  "resultType": "game",
  "league": "MLB",
  "gameId": 50021911,
  "abbr": "MLB_20260825_TB@DET",
  "url": "https://www.sportsline.com/mlb/game-forecast/MLB_20260825_TB@DET/",
  "matchup": "TB @ DET",
  "scheduledTime": "2026-08-25T22:40:00Z",
  "status": "SCHEDULED",
  "seasonYear": 2026,
  "seasonType": "REGULAR_SEASON",
  "home": {
    "id": 306, "abbr": "DET", "location": "Detroit", "nickName": "Tigers",
    "colorPrimary": "001C42",
    "logoUrl": "https://sports.cbsimg.net/fly/images/team-logos/306.svg",
    "score": null
  },
  "away": { "id": 329, "abbr": "TB", "location": "Tampa Bay", "nickName": "Rays", "score": null },
  "venue": {
    "name": "Comerica Park", "city": "Detroit", "state": "MI",
    "zipCode": "48201", "timeZone": "US/Eastern", "type": "Outdoor"
  },
  "broadcast": { "name": "Detroit SportsNet", "callLetters": "DSN", "type": "Streaming - Regional" },
  "weather": { "temperature": 79, "description": "Passing clouds. Warm.", "metric": false },
  "odds": {
    "consensus": {
      "bookId": "31", "bookName": "consensus",
      "moneyline": {
        "home": {
          "price": { "american": 115, "decimal": 2.15, "impliedProbability": 0.46512, "payoutPer100": 115 },
          "openingPrice": { "american": 108, "decimal": 2.08, "impliedProbability": 0.48077 },
          "outcome": null
        },
        "away": { "price": { "american": -127, "decimal": 1.7874, "impliedProbability": 0.55947 } }
      },
      "spread": {
        "home": { "line": 1.5, "openingLine": 1.5, "price": { "american": -159 } },
        "away": { "line": -1.5, "openingLine": -1.5, "price": { "american": 133 } }
      },
      "total": {
        "over": { "line": 7.5, "openingLine": 7.5, "price": { "american": -119 } },
        "under": { "line": 7.5, "price": { "american": -102 } }
      },
      "hasMoneyline": true, "hasSpread": true, "hasTotal": true
    }
  },
  "booksQuoting": 6,
  "finalScore": null,
  "scrapedAt": "2026-08-25T20:41:02.118Z"
}
```

With **Add public betting splits** and **Add line-shopping analytics** on, the row also carries:

```json
{
  "bettingSplits": {
    "moneyline": { "betType": "Moneyline", "awayBetPercent": 81, "homeBetPercent": 19 },
    "spread":    { "betType": "Spread",    "awayBetPercent": 85, "homeBetPercent": 15 },
    "total":     { "betType": "Total",      "overBetPercent": 70, "underBetPercent": 30 }
  },
  "analytics": {
    "booksQuotingMoneyline": 6,
    "moneylineHoldByBook": {
      "draftkings": 1.653, "fanduel": 2.048, "betmgm": 3.594,
      "caesars": 2.068, "betrivers": 4.318, "thescore": 3.193
    },
    "lowestMoneylineHoldPercent": 1.653,
    "averageMoneylineHoldPercent": 2.812,
    "fairProbability": { "home": 0.45396, "away": 0.54604 },
    "best": {
      "moneyline": { "home": { "price": 116, "book": "draftkings" }, "away": { "price": -124, "book": "draftkings" } },
      "spread":    { "home": { "price": -149, "book": "betrivers" }, "away": { "price": 140, "book": "thescore" } },
      "total":     { "over": { "price": -114, "book": "betrivers" }, "under": { "price": 100, "book": "fanduel" } }
    },
    "shoppingGainBps": { "moneylineHome": 87, "moneylineAway": 1049.5, "over": 701.5 },
    "arbitrage": { "moneyline": { "exists": false, "roiPercent": -1.625, "stakeSplit": null } }
  }
}
```

A finished game replaces the nulls with results:

```json
{
  "status": "FINAL",
  "finalScore": { "home": 1, "away": 0 },
  "odds": { "consensus": {
    "spread":    { "home": { "line": -1.5, "outcome": "LOSS" } },
    "total":     { "over": { "line": 8.5, "outcome": "LOSS" } },
    "moneyline": { "home": { "price": { "american": -136 }, "outcome": "WIN" } }
  } },
  "scoreByPeriod": { "home": [{ "label": "1", "period": 1, "points": 0 }, "..."] }
}
```

And an expert pick row:

```json
{
  "resultType": "expert-pick",
  "league": "MLB",
  "gameAbbr": "MLB_20260824_CIN@SF",
  "scheduledTime": "2026-08-25T01:45:00Z",
  "result": "LOSS",
  "marketType": "PROP",
  "pick": "First 5 Innings Cincinnati -0.5 -103",
  "pickIsRevealed": true,
  "selection": {
    "market": "FIRST_5_INNINGS_HANDICAP",
    "marketLabel": "First 5 Innings - Spread",
    "side": "AWAY",
    "line": -0.5,
    "price": { "american": -103, "decimal": 1.9709, "impliedProbability": 0.50739 },
    "team": { "id": 317, "abbr": "CIN" }
  },
  "units": 0.5,
  "sportsbook": "Sugar House",
  "writeup": "The Reds F5 ML is around -200 with Chase Burns on the mound but we've still got some value...",
  "expert": {
    "cbsExpertId": 51295899, "fullName": "Angelo Magliocca",
    "nickName": "Amags", "twitterHandle": "@amagspicks"
  },
  "streaks": [{ "league": "MLB", "label": "6-5 in Last 11 MLB Game Props Picks", "recordLabel": "RECORD: 6-5", "profit": 39.5, "hot": false }]
}
```

Futures return one row per selection with the field overround and de-vigged probability. Injuries return one row per player with every listed injury. Experts return one row per handicapper with their streak records and live pick list. Simulations return one row per graded model pick.

### Configure the run

Pick your datasets and leagues. Everything else is a filter or a checkbox. The Input tab lists every parameter.

Tonight's MLB board, six books and the public split:

```json
{
  "datasets": ["games"], "leagues": ["MLB"],
  "includeAllBooks": true, "includeBettingSplits": true, "maxItems": 200
}
```

A historical window for backtesting — closing lines, results and public money:

```json
{
  "datasets": ["games"], "leagues": ["NFL"],
  "startDate": "2025-09-01", "endDate": "2025-12-31",
  "gameStatus": ["FINAL"], "includeBettingSplits": true, "includeScoreByPeriod": true
}
```

Every settled NFL expert pick, biggest stakes first:

```json
{
  "datasets": ["expertPicks"], "leagues": ["NFL"],
  "pickStatus": ["WIN", "LOSS", "PUSH"], "minPickUnits": 1, "maxItems": 5000
}
```

Games the public is piling onto, across two leagues:

```json
{
  "datasets": ["games"], "leagues": ["NFL", "NBA"],
  "minPublicBetPercent": 80, "onlyWithOdds": true
}
```

Hunt for cross-book price gaps on close games:

```json
{
  "datasets": ["games"], "leagues": ["MLB", "NHL"],
  "maxSpread": 2, "includeAnalytics": true, "maxItems": 500
}
```

Super Bowl and division futures, plus the injury wire:

```json
{ "datasets": ["futures", "injuries"], "leagues": ["NFL"], "maxItems": 500 }
```

Filters run on the complete row before the optional blocks are trimmed off, so you can filter on a market you did not buy — screen by public bet percentage without paying for the splits column.

### Pricing

Pay-per-event. You are billed per row written, plus a small charge for each listing page fetched and a $0.054 run-start fee. Filtered-out rows cost nothing.

| Event | Price | When it fires |
|---|---|---|
| Run start | $0.054 | Once per run |
| League scan | $0.010 | Each listing page fetched — one per page of up to 200 records, plus one per league for the team-form board and two per league for the expert leaderboard. A page that failed after retries is not billed. |
| Game row | $0.007 | Each game row written |
| Expert pick row | $0.004 | Each expert pick written |
| Futures row | $0.002 | Each futures selection written |
| Injury row | $0.003 | Each injured player written |
| Expert row | $0.004 | Each handicapper written |
| Simulation row | $0.005 | Each model pick written |
| Every sportsbook | $0.003 | Only with **Add every sportsbook** on, per game that has named books |
| Betting splits | $0.002 | Only with **Add public betting splits** on, per game that has them |
| Score by period | $0.001 | Only with **Add score by period** on, per game that has periods |
| Team form | $0.003 | Only with **Add projected score and team form** on, per game that has one |
| Season trends | $0.006 | Only with **Add season betting trends** on, per game that returns them |
| Player prop lines | $0.008 | Only with **Add player prop lines** on, per game that has props |
| Line-shopping analytics | $0.002 | Only with **Add line-shopping analytics** on, per row |

| Game rows collected | Approximate cost |
|---|---|
| 100 | $0.76 |
| 1,000 | $7.10 |
| 10,000 | $70.55 |

The seven optional blocks are off by default. A run that leaves them off pays the run-start fee, one league scan per page of 200, and $0.007 per game row. An optional block is only billed when it actually came back with data — a scheduled game has no period scoring, so **Add score by period** costs nothing on it.

**Why $7 per 1,000 and not $1.** Measured on the platform, this Actor's own cost is under a cent per 1,000 rows: 1,200 historical game rows with the betting splits attached billed $0.0068 in compute, and 569 rows across all six datasets with every optional block on billed $0.0033. It is HTTP-only, with no proxy and no browser, and peaked at 78 MB. We price on what the row is worth rather than what it costs us: six books, both sides, three markets, opening and closing prices, the public split and a graded outcome in a single row. The one direct competitor charges $15 per 1,000 for a narrower slice.

### Free users

Free-plan runs return up to 25 rows as a preview. [Upgrade your Apify plan](https://console.apify.com/sign-up?fpr=vmoqkp) to collect the full slate.

### Run it

1. [Create a free Apify account with $5 in credit](https://console.apify.com/sign-up?fpr=vmoqkp).
2. Open the [SportsLine Scraper](https://apify.com/parseforge/sportsline-scraper?fpr=vmoqkp).
3. Pick your datasets and leagues, add any filters, 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.

### Use with AI agents (MCP)

Give an AI agent live access to SportsLine's odds, picks and public-money data 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/sportsline-scraper"
```

Then prompt it in plain language:

- *"Pull tonight's MLB board with every book and tell me which side the public is on in each game."*
- *"Get every settled NFL expert pick from last season and rank the analysts by units won."*
- *"Fetch NFL futures and show me the best price on each division winner."*

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

```
Use the Apify Actor "parseforge/sportsline-scraper" to collect betting data from SportsLine. Input: { "datasets": ["games","expertPicks","futures","injuries","experts","simulations"], "leagues": ["NFL","NCAAF","NBA","NCAAB","MLB","NHL","MLS","NWSL","EPL","LIGA","BUND","SERI","FRAN","CHLG","WCS"], "startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD", "includeAllBooks": true, "includeBettingSplits": true, "includeAnalytics": true, "maxItems": <n> }. Each game row carries the consensus line plus six named sportsbooks with moneyline, spread and total in American and decimal odds, the share of public bets per side, and on finished games the final score with each market graded WIN/LOSS/PUSH. Call it with the ApifyClient and my APIFY_TOKEN.
```

### Troubleshooting

**Why did I get no rows?**

The league is probably between seasons. SportsLine only publishes a slate when there are games on it — college basketball returns nothing in August. The log says how many records matched before filters. Pass a `startDate` that lands on a slate with games, or add a league that is in season.

**Why does my date window return the wrong games?**

It should not, but the reason it could is worth knowing. SportsLine's own date arguments do not describe a window: one date alone acts as a lower bound, and passing both drops the lower bound and honours only the end date, which silently returns the whole archive from October 2018. The Actor works around this by sending the start date to the API and trimming the end date itself. Use plain `YYYY-MM-DD` and you get exactly the window you asked for — a single-day MLB window returned all 15 games from that date and nothing else.

**Why are some books missing from a game?**

Three reasons, in order of likelihood. **Add every sportsbook** is off, so the row carries the consensus line alone — that is the default. Not every book prices every game. And historical games keep only the consensus line, because the named books are not archived. `booksQuoting` tells you how many named books are on the row.

**I set `sportsbooks` and nothing changed.**

`sportsbooks` trims the named books, so it only bites when **Add every sportsbook** is on. Without that block there are no named books to trim, and the row keeps its consensus line. If your selection would leave a game with no price at all, the consensus line is kept anyway rather than writing a row with an empty odds block.

**Why does a pending expert pick say "Subscribers Only"?**

That is SportsLine's own label on the human-readable pick string until the game starts. The structured `selection` block on the same row still carries the market, the line, the price, the side and the units, so the pick is usable either way. Settled picks (win, loss, push) show the plain-language string too, and they are almost all of them: across every league, 94,351 of 94,392 picks were already graded on the day this was measured.

**Why is the money percentage missing from the betting splits?**

SportsLine publishes the share of *bets* but not the share of *money*. We measured 246 split outcomes across five leagues and the money field was null in all 246, so it is not shipped as an always-null column.

**Why did the player props block come back empty?**

Coverage is thin. Across 125 games in five leagues we found 25 prop records, all in MLB. Games with none are neither returned nor billed, so an empty block costs nothing.

**Why are the model projection numbers null?**

SportsLine gates its projected numbers behind a subscription on the prop feed. What the public feed does return — the market, the line, both sides priced, and SportsLine's rank — is what this Actor ships. The **Simulations** dataset is the one that does carry public grades, confidence scores and win probabilities.

**A run stopped early.**

It hit the run timeout and wrote what it had rather than being killed with rows in memory. Narrow the leagues or the date window, or raise the timeout.

### FAQ

| Question | Answer |
|---|---|
| Do I need a SportsLine account or subscription? | No. The API this Actor reads is public and anonymous. |
| Do I need a proxy? | No. It ran clean from a plain datacenter IP, so no proxy is configured and none is billed. |
| How many sportsbooks does it return? | Seven price sources: Consensus, DraftKings, FanDuel, BetMGM, Caesars, BetRivers and theScore. The consensus line is always there; the six named books need **Add every sportsbook**, and only those that priced a given game appear on its row. |
| Are these live odds? | They are SportsLine's published prices, refreshed on SportsLine's schedule. Near-live, not tick-by-tick. |
| How far back does the archive go? | October 2018. Across the 15 leagues that was 110,001 games on 2026-08-25, with closing lines, final scores and graded outcomes. |
| Does the archive include every book? | No. Historical games keep the consensus line only. |
| Does it cover college sports? | Yes, both college football and college basketball, with the two largest archives of any league here. |
| Is UFC supported? | No. SportsLine has a UFC odds page, but its data API returned zero fights on every query we ran, including the archive, so we left it out rather than ship a dead option. |
| Does it do player props? | It returns the prop lines with both sides priced, as an opt-in checkbox. SportsLine's own projection on those props is subscriber-only and is not returned. |
| What is the arbitrage check? | It takes the best price on each side across every book quoting the game and tests whether the implied probabilities sum below 100%. When they do, you get the ROI and the stake split. |
| How many rows per run? | Free plan: 25. Paid: as many as the leagues and filters you select contain. |
| Can I collect several datasets at once? | Yes. With more than one selected, `maxItems` is split evenly across them and whatever one leaves unused rolls forward to the next. |
| Is this an official SportsLine product? | No. It is unofficial and reads only public SportsLine endpoints. |

### Related actors

- [RotoWire Odds Scraper](https://apify.com/parseforge/rotowire-scraper?fpr=vmoqkp): nine-book odds, props and futures across 10 sports.
- [Action Network Scraper](https://apify.com/parseforge/action-network-scraper?fpr=vmoqkp): odds, public betting and expert picks.
- [The Odds API Sports Scraper](https://apify.com/parseforge/the-odds-api-sports-scraper?fpr=vmoqkp): odds across bookmakers via The Odds API.
- [Reddit Posts Scraper](https://apify.com/parseforge/reddit-posts-scraper?fpr=vmoqkp): posts from any subreddit, search, or URL.
- [Twitter (X) Scraper](https://apify.com/parseforge/x-com-scraper?fpr=vmoqkp): tweets, profiles and lists without a login.

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 SportsLine, CBS Sports, Paramount, or any sportsbook named in its output. It collects only publicly available data. Odds are informational and are not betting advice; you are responsible for complying with SportsLine's terms, with applicable gambling law in your jurisdiction, and with data-protection law including GDPR and CCPA.

# Actor input Schema

## `datasets` (type: `array`):

Which SportsLine feeds to write. Each one produces its own row shape, tagged by resultType. Games is the odds board; the rest are separate datasets that share the same league and filter settings.

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

Leagues to read. SportsLine only publishes a slate while a league is in season, so an out-of-season pick returns nothing rather than failing. UFC is not offered: SportsLine has a UFC odds page but its data API returns zero fights on every query, including the archive, so shipping it as a choice would only waste a run.

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

Stop after this many rows across every selected dataset. Leave empty to collect everything the filters allow. Free Apify plans are capped at 25 rows regardless.

## `startDate` (type: `string`):

Only games kicking off on or after this date, as YYYY-MM-DD. Leave empty for the upcoming schedule. SportsLine's archive reaches back to October 2018, and pulling a historical window returns the closing line, the graded outcome and the final score.

## `endDate` (type: `string`):

Only games kicking off on or before this date, as YYYY-MM-DD. Combine with the from-date for a window. On its own it means everything from the start of the archive up to that date.

## `gameStatus` (type: `array`):

Keep only games in these states. Leave empty for every state. FINAL games carry the final score and each market's graded WIN/LOSS/PUSH outcome.

## `teams` (type: `array`):

Team abbreviations such as KC, NYY or PHI. A game is kept when either side matches. Also filters expert picks and injuries.

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

Trim the odds block down to these books. Applies only when "Add every sportsbook" is on — without it the row carries the consensus line alone. Leave empty to keep every book fetched. This narrows the output, not the run, because SportsLine returns all books in the same response. If your selection would leave a game with no price at all, the consensus line is kept so the row still stands on its own.

## `onlyWithOdds` (type: `boolean`):

Drop games no book has priced yet. Useful on a schedule pulled far in advance.

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

Keep games where at least one book posts an over/under of at least this many points, runs or goals.

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

Keep games where at least one book posts an over/under no higher than this.

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

Keep games whose point spread is at least this wide, measured as an absolute value. Use it to isolate blowout candidates.

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

Keep games whose point spread is no wider than this, measured as an absolute value. Set it to 3 for coin-flip games.

## `minMoneyline` (type: `number`):

Keep games where some quoted moneyline is at least this price, in American odds. Also filters futures. Set 200 to find long shots.

## `maxMoneyline` (type: `number`):

Keep games where some quoted moneyline is no higher than this price, in American odds. Also filters futures.

## `minPublicBetPercent` (type: `number`):

Keep games where one side has drawn at least this share of public bets. Reads the betting-splits block even when you have not turned it on, so you can screen for lopsided public action without buying the column.

## `pickStatus` (type: `array`):

Keep only expert picks with these results. Settled picks (win, loss, push) show the plain-language selection; pending picks show the market, line, price and side but label the selection Subscribers Only.

## `pickMarketTypes` (type: `array`):

Keep only picks on these markets. Leave empty for all four.

## `expertIds` (type: `array`):

Keep only picks from these SportsLine expert IDs. Run the Experts dataset first to find the IDs you want.

## `onlyFeaturedPicks` (type: `boolean`):

Keep only the picks SportsLine flags as featured.

## `minPickUnits` (type: `number`):

Keep only picks staked at this many units or more. Experts stake 0.5 to 3 units, so 1 removes the low-conviction plays.

## `futureTypes` (type: `array`):

Which futures buckets to keep: league-wide markets (division and conference winners, win totals), team markets, or player awards. Leave empty for all three.

## `injuryStatuses` (type: `array`):

Keep only players carrying one of these designations. Matching ignores case and matches on substring, so IL also catches the 10-Day IL and SUS also catches Reserve-Sus. Leave empty for the whole report.

## `includeAllBooks` (type: `boolean`):

Adds DraftKings, FanDuel, BetMGM, Caesars, BetRivers and theScore alongside the consensus line, each with its own moneyline, spread and total. Off by default, and the base row still carries the consensus price on its own.

## `includeBettingSplits` (type: `boolean`):

Adds the share of public bets on each side of the moneyline, spread and total. SportsLine publishes the bet count share but not the money share, so only bet percentages are returned.

## `includeScoreByPeriod` (type: `boolean`):

Adds quarter, inning or period scoring for both teams. Only populated once a game is under way or final.

## `includeTeamForm` (type: `boolean`):

Adds SportsLine's projected score for each side plus the head-to-head form strip (win-loss, against-the-spread and over/under records). One extra request per league, not per game.

## `includeSeasonTrends` (type: `boolean`):

Adds each team's season records by situation on the moneyline, spread and total, with units won or lost. One extra request per game.

## `includePlayerProps` (type: `boolean`):

Adds the player prop markets SportsLine lists for the game — market, line, both sides priced, plus SportsLine's rank and matchup score. The model's own projection is subscriber-only and is not returned. One extra request per game, coverage is thin: 25 props across 125 games measured on 2026-08-25, and games with none are neither returned nor billed.

## `includeAnalytics` (type: `boolean`):

Adds bookmaker hold per book, de-vigged fair probability, best price per side with the book that holds it, line-shopping gain in basis points, and a cross-book arbitrage check with the stake split. It fetches every sportsbook in order to compute those numbers, but only writes them to the row if you also turn on "Add every sportsbook" — so you can buy the analysis without buying the price grid.

## Actor input object example

```json
{
  "datasets": [
    "games"
  ],
  "leagues": [
    "NFL",
    "MLB"
  ],
  "maxItems": 100,
  "onlyWithOdds": false,
  "onlyFeaturedPicks": false,
  "includeAllBooks": false,
  "includeBettingSplits": false,
  "includeScoreByPeriod": false,
  "includeTeamForm": false,
  "includeSeasonTrends": false,
  "includePlayerProps": false,
  "includeAnalytics": false
}
```

# Actor output Schema

## `games` (type: `string`):

No description

## `expertPicks` (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 = {
    "datasets": [
        "games"
    ],
    "leagues": [
        "NFL",
        "MLB"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/sportsline-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 = {
    "datasets": ["games"],
    "leagues": [
        "NFL",
        "MLB",
    ],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/sportsline-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 '{
  "datasets": [
    "games"
  ],
  "leagues": [
    "NFL",
    "MLB"
  ],
  "maxItems": 100
}' |
apify call parseforge/sportsline-scraper --silent --output-dataset

```

## MCP server setup

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