SportsLine Scraper - Odds, Expert Picks & Projections
Pricing
from $7.00 / 1,000 game rows
SportsLine Scraper - Odds, Expert Picks & Projections
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.
Pricing
from $7.00 / 1,000 game rows
Rating
0.0
(0)
Developer
ParseForge
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
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:
{"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:
{"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:
{"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:
{"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:
{"datasets": ["games"], "leagues": ["MLB"],"includeAllBooks": true, "includeBettingSplits": true, "maxItems": 200}
A historical window for backtesting — closing lines, results and public money:
{"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:
{"datasets": ["expertPicks"], "leagues": ["NFL"],"pickStatus": ["WIN", "LOSS", "PUSH"], "minPickUnits": 1, "maxItems": 5000}
Games the public is piling onto, across two leagues:
{"datasets": ["games"], "leagues": ["NFL", "NBA"],"minPublicBetPercent": 80, "onlyWithOdds": true}
Hunt for cross-book price gaps on close games:
{"datasets": ["games"], "leagues": ["MLB", "NHL"],"maxSpread": 2, "includeAnalytics": true, "maxItems": 500}
Super Bowl and division futures, plus the injury wire:
{ "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 to collect the full slate.
Run it
- Create a free Apify account with $5 in credit.
- Open the SportsLine Scraper.
- Pick your datasets and leagues, add any filters, and click Start.
- Export the results as CSV, Excel, JSON, or XML from the Dataset tab.
Run it programmatically through the Apify API or the ApifyClient 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:
$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: nine-book odds, props and futures across 10 sports.
- Action Network Scraper: odds, public betting and expert picks.
- The Odds API Sports Scraper: odds across bookmakers via The Odds API.
- Reddit Posts Scraper: posts from any subreddit, search, or URL.
- Twitter (X) Scraper: tweets, profiles and lists without a login.
Browse the full ParseForge collection 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.
