PrizePicks Player Props Scraper - Lines & Line Moves
Pricing
from $0.07 / 1,000 line returneds
PrizePicks Player Props Scraper - Lines & Line Moves
For DFS and betting models: every PrizePicks player prop as a row - player, team, stat, line, standard/demon/goblin, over-only or both sides, start time. 9,455 lines in 23 leagues in one request (2026-09-28). Monitoring returns only lines that moved, with the earlier value.
Pricing
from $0.07 / 1,000 line returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
1
Monthly active users
22 days ago
Last modified
Categories
Share
For DFS and betting models: every PrizePicks player prop as one row - player, team, stat, period, the line itself, whether it is a standard, demon or goblin line, whether it is over-only or offers both sides, and the game start time. On 2026-09-28 a single request returned 9,455 lines across 23 leagues. Turn monitoring on and later runs return only the lines that have actually changed, with the previous value, the first value ever seen and both differences in the same row - so you are not charged again for a line that has not moved.
Export as JSON, CSV or Excel.
Why monitoring matters here
Most of PrizePicks' board does not move between runs. Measured by reading the whole board twice, 15 minutes apart, on 2026-09-28:
| lines | |
|---|---|
| on the board the first time | 9,381 |
| on the board the second time | 9,455 |
| changed (line, odds type, sides, status, flash-sale line or start time) | 35 |
| - of which the line itself moved | 15 |
| - of which the start time moved | 14 |
| newly listed | 105 |
| charged in monitoring mode | 140 (1.5%) |
| lines that had been taken down | 31 |
A line keeps its PrizePicks id when its number moves (for example Rush + Rec Yards 169.5 to 179.5 on the same id), so a moved line comes back as a change with previousLine and lineMove, not as an unrelated new row.
Both reads are in this repository as test/fixtures/board-a-summary.json and board-b-summary.json (the id and the watched values of every line), and npm test recounts every number above. The 94-line and 97-line samples in test/fixtures/board-a.json and board-b.json are cut from the same two reads.
How much moves depends on the gap between runs, and one measurement is one measurement. Set the run's maximum total charge if you want a hard ceiling rather than trusting a rate.
What you get
One row per line. Columns:
- Identity -
projectionId(PrizePicks' id; stable across runs and across line moves - use it to join runs),groupKey(shared by a line and its alternates) - League -
league(PrizePicks' league name, e.g.NFL,NFL1H,SOCCER),leagueId,leagueCode - Player -
playerId,playerName,isCombo(two or more players added up),position,jerseyNumber,team,teamName,teamMarket - Game -
description(PrizePicks' own text: usually the opponent, but for season props it is the season, and for esports it can be the opponent plus the map),eventType,gameId,gameExternalId,gameStartsAt(UTC),gameStatus,homeTeam,awayTeam - The prop -
stat,statDisplayName,statTypeId,period(Full,1st Half,1Q,MAP 3...),projectionType,line,oddsType(standard/demon/goblin),allowedWagerTypes,overOnly,flashSaleLine,isPromo,isLive,lineStatus,adjustedOdds,trendingCount,boardTime,lineUpdatedAt - Monitoring only -
isNewSinceLastRun,changeKinds(new/line/odds-type/sides/status/flash-sale/start-time),previousLine,lineMove,firstSeenLine,lineMoveSinceFirstSeen,previousOddsType,previousAllowedWagerTypes,previousLineStatus,previousGameStartsAt,firstSeenAt,previouslySeenAt
Standard, demon and goblin
PrizePicks lists the same stat at different difficulty levels. On 2026-09-28: 6,525 demon, 1,646 goblin and 1,284 standard lines of 9,455. Filter them with oddsTypes.
Over-only or both sides
allowedWagerTypes is PrizePicks' own field: over on 6,756 lines, under_or_over on 1,408, and missing on 1,291. overOnly is true, false, or empty when PrizePicks does not say - it is never guessed.
Leagues
Use PrizePicks' own league names: NFL, NBA, MLB, WNBA, NHL, SOCCER, TENNIS, CS2, VAL, Dota2, R6, DARTS, and the period and season boards such as NFL1H, NFL1Q, WNBA1Q, NHL1P, NBASZN, NHLSZN. Each name is checked against PrizePicks' league list (138 leagues, 24 with lines on 2026-09-28) before anything else is asked, because PrizePicks answers an unknown league with an empty list that looks exactly like a league with no lines today. A name PrizePicks does not have comes back as a free row that lists the leagues with lines right now.
Counts on 2026-09-28: SOCCER 3,210 / MLB 1,787 / WNBA 1,651 / NFL 905 / NBASZN 557 / NBA 193, and 17 smaller boards. NFL is the full game only; first-half and first-quarter props are the separate NFL1H and NFL1Q boards. Leave leagues empty and you read every league on the board - but a run returns at most maxLines rows (default 1,000), and the whole board was 9,455 to 9,636 lines on 2026-09-28, so raise maxLines (up to 20,000) to receive all of it in one run. PrizePicks decides the order, so the first 1,000 lines are not spread evenly across leagues.
Input
Everything is optional. With an empty input the whole board comes back, up to maxLines.
| field | what it does |
|---|---|
leagues | read only these PrizePicks leagues. Empty = every league |
players | keep a line only if the player's name contains one of these (partial, case-insensitive) |
stats | keep a line only if the stat contains one of these |
teams | keep a line only if the team, team name, market, description or home/away team contains one of these |
oddsTypes | keep only standard, demon and/or goblin lines |
onlyBothSides | keep only lines PrizePicks marks under_or_over |
excludeLiveLines | drop lines PrizePicks marks as live |
excludeCombos | drop lines that add up two or more players |
startsWithinHours | only games starting within this many hours. 0 = no limit |
keywords / keywordMatch / excludeKeywords | keep or drop on any of the text columns; keywordMatch is any or all |
maxLines | how many rows this run may return (default 1,000) |
monitoringMode | return only lines that changed since the last run with this same input |
resetMonitoringState | forget what was already returned, so everything counts as new again |
onlyLineMoves | monitoring only: drop changes where only the odds type, sides, status or start time changed |
minLineMove | monitoring only: the line must have moved at least this far |
Filtering happens after the board is read, so it never costs an extra request. Filters keep rows whose value is unknown rather than dropping them, because unknown is not the same as small - with two exceptions: teams drops rows with no team information at all, and onlyBothSides drops rows where PrizePicks does not say, because naming a team or asking for both sides means you do not want guesses.
Honest limits
- US residential addresses only. PrizePicks answers datacentre addresses with HTTP 403 ("PrizePicks is currently unavailable in your location"), so every request goes through Apify's US residential proxy. PrizePicks also decides by state, so a refused request is asked again through another US residential address, up to four times. If PrizePicks answers with a browser check page instead of data, the run stops at once and does not try to get around it.
- Pre-game board as PrizePicks publishes it.
lineStatuswaspre_gameon all 9,455 lines; 18 of them were also markedisLive. Results and scores are not included. descriptionis not always the opponent. It is PrizePicks' own text:CHIfor an NFL player, the other player for tennis,2026-2027 Seasonfor season props,Nemiga MAP 3for esports. It is returned as written and never relabelled as an opponent.homeTeamandawayTeamare filled in only when PrizePicks attaches them to the game.- Some values jump around by themselves.
trendingCount, the board position andlineUpdatedAtchange within seconds without the line changing, so they are returned but never count as a change. Two reads of the whole board made at the same moment returned the same watched values on all 9,455 lines, while those jumping values changed on hundreds of lines within the same minute. - Paging. PrizePicks returns a whole league in one answer and ignores page settings (asking for 50 per page still returned all 193 NBA lines). If it ever answers with more than one page, the run follows the pages and stops as soon as a page brings no new line, so the same line is never charged twice.
- Monitoring memory is per input. Two schedules with different filters keep separate memories. If two runs with the same input finish at the same instant, one can overwrite the other's memory - Apify key-value stores have no atomic update, so this cannot be fully prevented. The run says so in its log when it happens. Do not put the same input in two schedules that overlap.
- A changed line that was not returned is not remembered. If a run hits "Maximum lines to return" or the run's maximum total charge, or if a line changed but has not yet moved far enough for
minLineMove/onlyLineMoves, its earlier values are deliberately kept. So a line that moves 0.5 twice does reach aminLineMoveof 1 - the movement adds up instead of being reset each run. - A changed line your other filters exclude is remembered, at its new value. Leagues, players, stats, teams and odds types are about which lines you want at all, so widening one of them later does not dump the whole board on you as new.
startsWithinHoursis different: lines outside the window are not remembered. The window moves by itself as time passes, so a line whose game is still too far away is offered as new on the first run in which its game enters the window, instead of being hidden until its number happens to move.- This is not advice about betting or investing. It returns what PrizePicks publishes, nothing more.
Rows that are never charged
Every run that returns nothing, or not everything, says why, in a free row:
status | meaning |
|---|---|
no-results | PrizePicks answered correctly and listed no lines |
no-filter-match | lines were read, the filters removed all of them |
no-line-move | monitoring mode: nothing you asked for has changed |
limit-reached | more lines matched than "Maximum lines to return" |
charge-limit-reached | the run's maximum total charge was reached before all matching lines were returned |
partial-board | some of the leagues you asked for could not be read; the others were returned |
blocked | PrizePicks refused the request (403 / 429 / 503) every time it was asked |
challenge-page | PrizePicks answered with a browser check page; the run stopped without getting around it |
unreadable | the answer could not be read, or its shape changed |
unsupported-input | the input asks for something that does not exist (a league PrizePicks does not have, an unknown odds type) |
monitoring-memory-unavailable | monitoring mode could not read its memory for this input, so the run stopped before asking PrizePicks instead of charging every line again as new |
no-results, no-line-move and blocked are deliberately different things. A refused request is never reported as "there are no lines".
Pricing
Two charges, and nothing else:
| event | price |
|---|---|
actor-start - once per run in which PrizePicks answered with at least one line | $0.04 (less on paid Apify plans) |
prop-scraped - per line returned | $0.10 per 1,000 (less on paid Apify plans) |
Rows that explain why nothing came back are always free. A run is charged nothing at all, not even the start, when PrizePicks refused it, showed a browser check page, listed no lines, or when it was stopped before reading any line (a league PrizePicks does not have, an unknown odds type, monitoring memory that could not be read). A run whose maximum total charge is below the start price returns no line and is not charged; the same applies when the maximum covers the start but not one line on top of it. Filters that simply match nothing do not make a run free - the board was read, so the $0.04 start applies.
The whole board (9,455 lines) costs about $0.99 per run; one league such as NBA (193 lines) about $0.06. In monitoring mode only the lines that changed are charged; there is no separate per-check fee. A run where nothing moved therefore costs $0.04 and returns one free row saying so. Every run is a start, so a schedule every 15 minutes is about 2,880 runs a month - decide the schedule with that in mind, and set the run's maximum total charge if you want a hard ceiling.
How it reads PrizePicks
https://partner-api.prizepicks.com/projections (one request per league, or one for the whole board), plus https://partner-api.prizepicks.com/leagues when you name leagues. No login. https://partner-api.prizepicks.com/robots.txt answered 404 (no rules) and https://www.prizepicks.com/robots.txt is User-Agent: * with an empty Disallow: when checked on 2026-09-28. The whole board is about 11.5 MB of JSON (about 514 KB over the wire with gzip).
Unofficial. Public data only.
Not affiliated with, endorsed by or connected to PrizePicks or any sportsbook. It reads only what PrizePicks publishes without a login, and returns no personal data: the people in the output are professional athletes, and the columns are their public lines.