ParseForge Scrapers

Action Network Scraper - Odds, Splits & Props

parseforge/action-network-scraper

AutomationIntegrations

Scrape Action Network sports odds with public betting splits, line movement, player props, weather, injuries and ATS standings. NFL, NBA, MLB, NHL, NCAAF, soccer, UFC and tennis. No login, no API key, no proxy.

Run this scraper See the API call
Total users
2
Monthly active
1
Total runs
9
Bookmarked
0
Rating
Not rated yet
Last modified
29 hours ago

Overview

ParseForge

Action Network Scraper - Odds, Betting Splits & Player Props

Scrape Action Network odds for any game, in any league, with the public betting percentages attached. Every game comes back priced at up to 16 sportsbooks, with the opening line, the current consensus, the ticket-vs-money split on each side, no-vig win probabilities, and the best available price per side. No login, no API key, no cookies, and no proxy. Export to CSV, JSON, Excel, or XML.

Commercial odds feeds start in the hundreds per month and still do not publish betting splits. This reads the same public endpoints the actionnetwork.com website uses, filtered by league, date, week, team, or sharp-money divergence, and returns each match in one fixed schema. NFL odds, NBA odds, MLB odds, NHL odds and college football odds all come back with the same columns, so one run covers the whole board.

Who uses it What they scrape Action Network for
Sports bettors and handicappers Where the money disagrees with the tickets, and which book has the best number
Model builders and quants Opening-to-closing line movement as a training and CLV signal
Media and content teams Odds, splits and injury notes for previews on a schedule
Affiliates and odds-comparison sites A live board across DraftKings, FanDuel, BetMGM, Caesars and more
Researchers and data scientists Historical seasons with closing lines and final scores already graded

What it does

This Actor reads Action Network's public odds board and returns one flat row per game per period. Every row carries:

  • ๐ŸŸ๏ธ The game: teams with records, colours and logos, start time, venue, broadcast network, rotation numbers, and the bet count Action Network reports.
  • ๐Ÿ’ต Every book's number: moneyline, spread and total from up to 16 sportsbooks, each with its own two-way hold percentage.
  • ๐Ÿ“Š Public betting percentages: the share of tickets and the share of money on each side of the moneyline, spread and total: plus moneyMinusTickets per side and the biggest divergence on the game.
  • ๐Ÿ“ˆ Line movement: the opening line, the current consensus, how far the spread and total have moved, and which way.
  • ๐ŸŽฏ Best odds: the best price available on each side and the book offering it.
  • ๐Ÿงฎ Computed market signals: implied probability, no-vig probability (three-way for soccer), decimal and fractional odds, and profit per 100 staked.
  • ๐Ÿ Results, when the game is over: final score, linescore by period, half and first-five splits, and whether the closing spread covered and the total went over.

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

What you can do with Action Network data

๐Ÿ” Find where the sharp money is.

Set Minimum sharp gap to 15 and the Actor keeps only games where the money percentage runs at least 15 points ahead of the ticket percentage on some side, the classic sign that a few large bets disagree with the crowd.

๐Ÿ“‰ Track a line from open to close.

Every row already carries the opening number and the current one. Turn on Add full line movement history and you get each individual price change with its timestamp, per book.

๐Ÿ›’ Shop the best number.

bestOdds names the book with the top price on each side of every market, so you can see the half-point and the ten cents you are leaving on the table.

๐Ÿง  Build and backtest a model.

Set a past Season and the Actor returns that slate with its closing lines, final scores, and an already-graded ATS and over/under result on each row. Box scores go back to 2015; sportsbook prices fill in from 2023 and are complete from 2024.

๐ŸŽฒ Pull NFL player props in bulk.

Turn on Add player props and each game carries every passing, rushing, receiving, strikeout, points and rebounds market with each book's price and line.

Why choose this scraper

What you get
No login, ever No account, no cookies, no session token to paste or keep alive.
No proxy cost It runs on Action Network's public endpoints, so there is no proxy line on your bill.
Public betting splits Tickets and money percentages on both sides of all three core markets, on every row.
19 leagues, one schema NFL, NCAAF, NBA, NCAAB, WNBA, MLB, NHL, the five big soccer leagues, MLS, UFC, boxing and tennis all return the same columns.
Three-way markets handled Soccer draws and combat-sport matchups price correctly instead of coming back empty.
Periods, not just full game First half, second half, first quarter and MLB first five innings, each as its own row.
History that goes back Any season from 2015; closing lines from 2023.
Filters that cut noise League, date, week, season, team, start time, bet count, status and sharp-money divergence. Only matching games are written and billed.
Opt-in extras, off by default Line movement, player props, game props, rosters, weather, injuries, standings and futures are each a checkbox. Leave them off and you are never billed for them.

How it compares

Three other Action Network scrapers exist on the Store. All three read the same scoreboard endpoint; none had a run in the last 30 days at the time of writing.

Feature ParseForge automation-lab jungle_synthesizer
Odds from multiple sportsbooks Yes Yes Yes
Public betting percentages Yes, all three markets Partial Bet count only
Opening line and movement summary Yes, on every row No No
Full timestamped line-movement history Optional No No
Best price per side, with the book named Yes Yes No
No-vig probability, hold %, decimal and fractional Yes Implied prob. only No
Player props and game props Optional No No
Futures markets Optional No No
Weather, injuries, ATS standings Optional No No
Soccer three-way, UFC, boxing, tennis Yes No No
Past seasons with graded ATS and O/U result Yes No No
Half, quarter and first-five periods Yes Full game and half Full game
Price per 1,000 rows $7.00 Not published $0.90

The per-row price is the honest headline: this Actor costs meaningfully more per row than jungle_synthesizer's. The unit is not the same thing, though. There, a row is one odds line from one book. Here, a row is the whole game: every book's moneyline, spread and total, the splits, the movement, the best price and the computed probabilities in one record. If you want the cheapest possible per-line dump and will do the pivoting yourself, use theirs.

What a game looks like

Every game returns as one flat JSON row. Here is a real record, per-book lines trimmed to one:

{
  "gameId": 294284,
  "url": "https://www.actionnetwork.com/mlb/boston-red-sox-vs-miami-marlins-odds/294284",
  "league": "mlb",
  "leagueId": 8,
  "season": 2026,
  "seasonType": "reg",
  "week": null,
  "status": "scheduled",
  "isFinal": false,
  "isLive": false,
  "startTime": "2026-08-25T22:40:00.000Z",
  "startTimestamp": 1787697600,
  "hoursUntilStart": 6.16,
  "matchup": "Boston Red Sox @ Miami Marlins",
  "homeTeam": {
    "id": 214,
    "name": "Miami Marlins",
    "abbreviation": "MIA",
    "logo": "https://static.sprtactn.co/teamlogos/mlb/100/mia_n.png",
    "primaryColor": "#FF6600",
    "conference": "NL",
    "division": "EAST",
    "wins": 67,
    "losses": 65,
    "record": "67-65",
    "url": "https://www.actionnetwork.com/mlb/odds/miami-marlins"
  },
  "awayTeam": { "id": 190, "name": "Boston Red Sox", "abbreviation": "BOS", "record": "72-59" },
  "homeRotationNumber": 926,
  "awayRotationNumber": 925,
  "broadcastNetwork": "NESN",
  "betCount": 3927,
  "isTrending": false,
  "period": "event",
  "periodLabel": "Full game",
  "consensusSpreadHome": 1.5,
  "consensusSpreadHomeOdds": -144,
  "consensusSpreadAway": -1.5,
  "consensusSpreadAwayOdds": 118,
  "consensusMoneylineHome": 125,
  "consensusMoneylineAway": -142,
  "consensusMoneylineDraw": null,
  "consensusTotal": 7.5,
  "consensusOverOdds": -101,
  "consensusUnderOdds": -122,
  "homeWinProbability": 0.4444,
  "awayWinProbability": 0.5868,
  "homeWinProbabilityNoVig": 0.431,
  "awayWinProbabilityNoVig": 0.569,
  "moneylineHoldPercent": 3.12,
  "spreadHoldPercent": 4.89,
  "totalHoldPercent": 5.2,
  "homeDecimalOdds": 2.25,
  "homeFractionalOdds": "5/4",
  "homeProfitPer100": 125,
  "publicBetting": {
    "moneylineHome": { "ticketsPercent": 14, "moneyPercent": 11, "moneyMinusTickets": -3 },
    "moneylineAway": { "ticketsPercent": 86, "moneyPercent": 89, "moneyMinusTickets": 3 },
    "spreadHome": { "ticketsPercent": 14, "moneyPercent": 7, "moneyMinusTickets": -7 },
    "spreadAway": { "ticketsPercent": 86, "moneyPercent": 93, "moneyMinusTickets": 7 },
    "over": { "ticketsPercent": 77, "moneyPercent": 78, "moneyMinusTickets": 1 },
    "under": { "ticketsPercent": 23, "moneyPercent": 22, "moneyMinusTickets": -1 },
    "maxMoneyTicketGap": 7,
    "sharpSide": "spreadAway"
  },
  "bestOdds": {
    "moneylineHome": { "odds": 130, "book": "DraftKings", "value": null },
    "moneylineAway": { "odds": -135, "book": "Caesars", "value": null },
    "spreadHome": { "odds": -140, "book": "bet365", "value": 1.5 },
    "over": { "odds": 105, "book": "BetMGM", "value": 7.5 },
    "bookCount": 5
  },
  "lineMovement": {
    "openSpreadHome": 1.5,
    "openTotal": 7.5,
    "openMoneylineHome": 135,
    "currentSpreadHome": 1.5,
    "currentTotal": 7.5,
    "currentMoneylineHome": 125,
    "spreadMove": 0,
    "totalMove": 0,
    "moneylineHomeMove": -10,
    "spreadDirection": "flat",
    "totalDirection": "flat"
  },
  "books": [
    {
      "bookId": 68,
      "book": "DraftKings",
      "period": "event",
      "marketId": "24437052",
      "isLive": false,
      "spreadHome": 1.5,
      "spreadHomeOdds": -140,
      "spreadAway": -1.5,
      "spreadAwayOdds": 115,
      "moneylineHome": 130,
      "moneylineAway": -155,
      "moneylineDraw": null,
      "total": 7.5,
      "overOdds": -105,
      "underOdds": -115,
      "moneylineHoldPercent": 4.32,
      "spreadHoldPercent": 4.86,
      "totalHoldPercent": 4.55
    }
  ],
  "bookCount": 7,
  "boxscore": null,
  "result": null,
  "scrapedAt": "2026-08-25T16:41:07.108Z"
}

boxscore and result stay null until a game actually starts, a scheduled game ships an empty linescore, and grading that as 0-0 would put a fake result on every future game. consensusMoneylineDraw fills only on three-way soccer markets. venue fills when Add weather and venue is on.

Configure the run

Pick one or more leagues, then narrow the slate. Filters run as each game is read, so only matches reach your dataset and only matches are billed. The Input tab lists every parameter.

Today's NFL board at the five major books:

{ "leagues": ["nfl"], "books": ["draftkings", "fanduel", "betmgm", "caesars", "bet365"], "maxItems": 100 }

Only games where the money is at least 15 points ahead of the tickets, biggest divergence first:

{ "leagues": ["nfl", "ncaaf", "nba"], "minSharpGap": 15, "sortBy": "sharpGap", "maxItems": 50 }

A specific NFL week from a past season, already graded against the closing line:

{ "leagues": ["nfl"], "season": 2024, "week": 1, "seasonType": "reg", "gameStatus": "complete" }

An MLB slate for one date with player props, weather and both bullpens' injury lists:

{ "leagues": ["mlb"], "date": "2026-09-13", "includePlayerProps": true, "includeWeather": true, "includeInjuries": true }

First-half NBA lines with the full timestamped movement history:

{ "leagues": ["nba"], "periods": ["firsthalf"], "includeLineMovement": true, "maxItems": 20 }

Season-long futures for the NFL: championship, division, win totals, awards and player milestones:

{ "leagues": ["nfl"], "includeFutures": true, "maxItems": 1 }

Pricing

Pay-per-event. You are billed per game row written, plus a $0.054 run-start fee. Filtered-out games cost nothing.

Event Price When it fires
Run start $0.054 Once per run
Scoreboard request $0.01 Once per league and period read: one request covers that whole slate
Game row $0.007 Each game row written to the dataset
Line movement history $0.006 Only with Add full line movement history on
Player props $0.008 Only with Add player props on
Game props $0.004 Only with Add game props on
Game detail $0.005 Only with Add rosters, depth charts and trends on
Weather report $0.01 Only with Add weather and venue on, once per league
Injury report $0.01 Only with Add injury reports on, once per league
Standings table $0.01 Only with Add standings and ATS records on, once per league
Futures market $0.01 Only with Add futures markets on, per futures market row
Games collected Approximate cost
100 $0.76
1,000 $7.16
10,000 $71.15

The eight optional blocks are off by default. A run that leaves them off pays only the run-start fee, one scoreboard request per league and period, and $0.007 per game.

Two things worth knowing before you budget. A game requested across two periods is two rows and bills twice, because each period is a separate scoreboard read and a separate set of lines. And filters run on the full row before the optional blocks are bought, so you can filter on a column you did not pay to keep: screening by sharp gap costs nothing extra.

Free users

Free-plan runs return up to 10 games as a preview, and skip futures. Upgrade your Apify plan to collect up to 100,000 games per run.

Run it

  1. Create a free Apify account with $5 in credit.
  2. Open the Action Network Scraper.
  3. Pick your leagues, set a date or week, tick any optional blocks, and click Start.
  4. 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 sportsbook odds and public betting percentages 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/action-network-scraper"

Then prompt it in plain language:

  • "Pull today's NFL board and list the games where the money percentage is at least 15 points ahead of the tickets."
  • "Which book has the best price on every underdog moneyline in tonight's NBA slate?"
  • "Get NFL Week 1 of 2024 with closing lines and tell me how favourites did against the spread."

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

Use the Apify Actor "parseforge/action-network-scraper" to collect sportsbook odds with public betting splits. Input: { "leagues": ["nfl"], "date": "<YYYY-MM-DD>", "week": <n>, "season": <year>, "books": ["draftkings","fanduel","betmgm"], "minSharpGap": <n>, "maxItems": <n> }. Each row is one game with every book's moneyline, spread and total, the ticket and money percentages on each side, the opening line and how far it moved, the best price per side, and no-vig probabilities. Optional blocks: includeLineMovement, includePlayerProps, includeGameProps, includeGameDetail, includeWeather, includeInjuries, includeStandings, includeFutures. Call it with the ApifyClient and my APIFY_TOKEN.

Troubleshooting

Why is date being ignored?

NFL and NCAAF slates are addressed by week, not date. Use Week with Season type for those two; use Date for MLB, NBA, NHL, WNBA, college basketball and soccer.

Why are the public betting percentages all zero?

Splits come from Action Network's consensus book and only fill once a game has taken real action. Preseason games, deep college slates and markets that just opened often sit at zero for hours.

Why does a period come back with no lines?

Not every league prices every period, and books post half and quarter numbers later than the full game. Preseason NFL, for example, rarely has a first-half market. Turn on Priced games only to drop those rows before they are billed.

Why does my past season have scores but no odds?

Box scores go back to 2015. Sportsbook prices start appearing around 2023 and are complete from 2024 onward: before that, only the consensus line is available, and often not even that.

Why fewer games than I asked for?

Your filters removed them, or the slate is that size. minSharpGap, minNumBets and gameStatus cut hard. Loosen them or add leagues.

Why is venue empty?

Venue travels with the weather feed. Turn on Add weather and venue and it fills, along with surface and roof type.

A field stopped filling.

Action Network changed its response shape. Email us with your run ID and the column that went empty.

FAQ

Question Answer
Do I need an Action Network account or subscription? No. It reads the same public endpoints the logged-out site uses.
Do I need a proxy? No. There is no proxy cost on this Actor.
Which leagues does it cover? NFL odds, NBA odds, MLB odds, NHL odds, college football (NCAAF) and college basketball odds, WNBA, the five big European soccer leagues, MLS, UFC, boxing and ATP/WTA tennis: 19 in all.
Which sportsbooks does it cover? DraftKings, FanDuel, BetMGM, Caesars, BetRivers, bet365, Fanatics, Unibet, Hard Rock Bet, Bally Bet, theScore Bet, plus Kalshi and Polymarket, and state-specific skins by ID.
What are books 15 and 30? 15 is Action Network's consensus line, which carries the betting splits. 30 is the opening line. Both are always included and are excluded from best-price shopping.
Can I get closing line value? Yes. Pull a past season and compare lineMovement.openSpreadHome with result.closingSpreadHome on each row.
Does it do live in-game odds? It returns whatever is posted when the run fires, including live prices, with isLive on the affected lines. Schedule it to poll.
How many games per run? Free plan: 10. Paid: up to 100,000, bounded by how many games the leagues you picked actually have.
Does it return player props for every sport? It returns whatever the game offers. NFL and MLB are the deepest; college and soccer are thinner.
Are futures counted against the game cap? No. Futures are separate rows with their own event.
Is this an official Action Network product? No. It is unofficial and reads only public Action Network data.

Related actors

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 The Action Network, Inc. It collects only publicly available data. You are responsible for using the data in compliance with Action Network's terms and applicable laws. Odds data is provided for informational purposes only and is not betting advice. Gambling involves risk; if you or someone you know has a gambling problem, call 1-800-GAMBLER.

Input

FieldTypeWhat it doesDefault
leagues array Which league slates to read. Each league is one scoreboard request per period. Leave empty for NFL. ["nfl"]
gameUrls array Action Network game URLs or numeric game IDs. When set, only these games are kept out of their league's slate. Example: https://www.actionnetwork.com/nfl/bills-vs-chiefs-odds/290857 not set
date string Slate date as YYYY-MM-DD, for the date-scheduled leagues (MLB, NBA, NHL, WNBA, NCAAB, soccer). Ignored by NFL and NCAAF, which are addressed by week. not set
week integer Week number, for NFL and NCAAF. Combine with Season type. Leave empty for the current week. not set
seasonType string (3 options) Which part of the season the week belongs to. Only used with Week. not set
season integer Season year, for pulling a past slate. Results and box scores go back to 2015; sportsbook prices start filling in around 2023 and are complete from 2024. not set
periods array Which segment of the game to price. Each period is a separate row per game and a separate scoreboard request. Not every league posts every period. ["event"]
books array Which sportsbooks to price the game at. The Action Network consensus line and the opening line are always included, they carry the public betting splits and the line-movement baseline. ["draftkings","fanduel","betmgm","caesar
extraBookIds string Comma-separated Action Network book IDs for sportsbooks not in the list above, e.g. state-specific skins. Added to whatever the picker selects. not set
gameStatus string (5 options) Keep only games in this state. Filters run before anything optional is bought, so a filtered-out game costs nothing. any
teams array Keep only games involving one of these teams. Matches team name or abbreviation, case-insensitive, e.g. "Chiefs" or "KC". not set
startsAfter string Keep only games starting at or after this moment. YYYY-MM-DD or a full ISO timestamp. not set
startsBefore string Keep only games starting at or before this moment. YYYY-MM-DD or a full ISO timestamp. not set
minNumBets integer Keep only games with at least this many bets placed through Action Network. A rough handle proxy for filtering out dead games. not set
minSharpGap integer Keep only games where money percentage exceeds ticket percentage by at least this much on some side, the classic sign that the dollars disagree with the crowd. Try 15. not set
onlyTrending boolean Keep only games Action Network flags as trending. false
onlyWithOdds boolean Drop games where no sportsbook has posted a line for the chosen period yet. false
sortBy string (5 options) Order rows before the item cap is applied, so a small run keeps the games you care about. startTime
maxItems integer Cap on game rows written. Futures rows are counted separately. 100
includeLineMovement boolean Every price each sportsbook posted on the game's core markets, with the timestamp of each move. One extra request per market on the game. false
includePlayerProps boolean Passing, rushing, receiving, strikeout, hits, points, rebounds and assists markets with every book's price. One extra request per game. false
includeGameProps boolean Team totals, alternate lines, race-to markets and novelty props. Shares the same request as player props when both are on. false
includeGameDetail boolean Full player list, depth charts, situational trends, team stat rankings and the last five head-to-head meetings. One extra request per game. false
includeWeather boolean Hourly forecast around kickoff plus the venue's surface and roof type. One request per league, shared by every game in it. false
includeInjuries boolean Both teams' injury lists with status, description and whether the player is a starter. One request per league, shared by every game in it. false
includeStandings boolean Straight-up, against-the-spread, over/under and unit records overall, at home, on the road, as favourite and as underdog. One request per league. false
includeFutures boolean Season-long markets as extra rows: championship and division odds, win totals, award races and player milestones. One request per futures market in the league. false

Pricing

from $6.23 per 1,000 results

Charged forWhat it isPrice each
Game row Charged for each game row written to the dataset. A game requested across two periods is written and charged as two rows. $0.00623 to $0.007
Actor Start Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). $0.04806 to $0.054
Scoreboard request Charged once per league and period requested from the scoreboard. One request covers that whole slate. $0.0089 to $0.01
Line movement history Charged once per game when 'Add full line movement history' is on. $0.00534 to $0.006
Player props Charged once per game when 'Add player props' is on. $0.00712 to $0.008
Game props Charged once per game when 'Add game props' is on. $0.00356 to $0.004
Game detail Charged once per game when 'Add rosters, depth charts and trends' is on. $0.00445 to $0.005
Weather report Charged once per league when 'Add weather and venue' is on. $0.0089 to $0.01
Injury report Charged once per league when 'Add injury reports' is on. $0.0089 to $0.01
Standings table Charged once per league when 'Add standings and ATS records' is on. $0.0089 to $0.01
Futures market row Charged for each futures market row written when 'Add futures markets' is on. $0.0089 to $0.01

Tiered: the lower figure is the price on a higher Apify plan. Billing and the free credit live on Apify.

API

One POST returns the dataset directly. Same shape for every scraper in the library, so swapping the slug is the only change.

POST ยท run and get results
curl -X POST "https://api.apify.com/v2/acts/parseforge~action-network-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "helloWorld": 123
  }'

Examples

Input that runs as-is.

input.json
{
  "helloWorld": 123
}

Reviews

No reviews yet. Be the first.

Issues

We build and maintain this scraper, so a problem with it comes to us. Report it on the Apify listing and the thread stays attached to the scraper where the next person can find it: open an issue.

Broken and urgent, or you would rather not post in public? Write to parseforge@protonmail.com and it reaches the people who wrote it.

Related scrapers

Run Action Network Scraper - Odds, Splits & Props on Apify All scrapers