Pinnacle Odds Scraper
Pricing
from $2.50 / 1,000 market records
Pinnacle Odds Scraper
Collect Pinnacle pre-match odds for the NFL, NBA, NHL, MLB, college sports, soccer and UFC: moneyline, spread and total per game with American and decimal odds, implied probability and the published stake limit. Optional alternate lines, periods, team totals, props and futures.
Pricing
from $2.50 / 1,000 market records
Rating
0.0
(0)
Developer
Philip Kirkbride
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Features
Share
Collect Pinnacle's pre-match odds for the NFL, NBA, NHL, MLB, college football and basketball, 18 soccer leagues and UFC. Each record is one market of one game: the moneyline, the spread or the total, with both sides priced in American and decimal odds, the implied probability, and the largest stake Pinnacle shows for that market. Optional extras: every alternate line, halves, quarters and periods, team totals, game and player props, and futures boards. Built for bettors, modellers and odds-comparison builders who use Pinnacle as the sharp reference price and want it as plain JSON on a schedule. No Pinnacle account is needed.
Data only, not betting or financial advice. This is an unofficial tool: it is not affiliated with or endorsed by Pinnacle.
Use cases
- Reference prices: Pinnacle's main moneyline, spread and total for every listed game of a league, to compare against other sportsbooks, exchanges or prediction markets.
- Line tracking: schedule runs and chart how the main line and its price move before the start. A market at a new line is a new record, so a moved line is visible as such.
- Fair-price models: both sides of every market arrive in one record, so removing the margin is one step; stake limits show how firm a price is.
- Alternate lines and periods: the full ladder of spreads and totals, and first-half, quarter and period markets, each as its own record.
- Cross-source joins: every record carries the shared
canonicalenvelope our other sports Actors use, with explicit home and away, league, sport and start time.
Quick start
- Open the Actor and click Start. The prefilled form collects the main moneyline, spread and total of every listed NFL and NBA game in the next 14 days, capped at 100 records.
- Read the rows in the Output tab, or export them as JSON, CSV or Excel.
One soccer league, main lines:
{"leagues": ["epl"], "dateFrom": "2026-11-21", "dateTo": "2026-11-30", "maxResults": 20}
Upcoming NBA spread and total lines, including first-half markets (20-record cap):
{"leagues": ["nba"], "marketFamilies": ["spreads", "totals"], "periods": ["game", "first_half"], "mainLineOnly": false, "maxResults": 20}
Player and game props and futures for one league:
{"leagues": ["nhl"], "marketFamilies": ["props", "futures"], "maxResults": 20}
An empty input ({}) is a sample of at most 20 current main-line records.
The status message says "Sample run (...)" and the run summary has
sampleRun: true. It uses NFL and NBA in September–May, and MLB and EPL in
June–August, for today and the next 14 UTC days. If those leagues have no
markets, the run reports that honestly; source access failures fail the run.
Setting a filter, option or limit explicitly collects that requested scope
with sampleRun: false. Proxy settings alone still select a sample.
Input
| Name | Type | Default | What it does |
|---|---|---|---|
leagues | array | NFL and NBA | Leagues to collect: nfl, ncaaf, nba, wnba, ncaab, ncaaw, mlb, nhl, epl, laliga, seriea, bundesliga, ligue_1, ucl, uel, mls, liga_mx, brasileirao, argentina_primera, eredivisie, primeira_liga, belgian_pro_league, scottish_premiership, super_lig, chile_primera, j1_league, ufc. |
leagueIds | array | none | Any other competition by Pinnacle's own numeric league id, for example [382] for basketball's Euroleague. These records have league: null. Leagues and league ids together: at most 12 per run. |
marketFamilies | array | ["moneyline", "spreads", "totals"] | Any of moneyline (includes the three-way price with a draw), spreads, totals, team_totals, props, futures. |
periods | array | ["game"] | Any of game, first_half, first_period, second_period, third_period. A "period" is a quarter in football and basketball. |
mainLineOnly | boolean | true | Keep only the main spread, total and team total. Set false for every alternate line as its own record. |
includeRegulationTime | boolean | false | Hockey only: also collect the regulation-time markets (three-way moneyline with a draw, its own puck line and total), marked includesOvertime: false. |
dateFrom / dateTo | string | today to today + 14 | Start-time days as YYYY-MM-DD (UTC days). With only dateFrom, that single day. At most 31 days. Futures are not limited by the dates. |
maxResults | integer | 1000 | Maximum dataset records per explicit run (1–10,000). Bare start: 20; Console prefill: 100. |
requestDelaySecs | number | 1 | Seconds between requests (0.5–10). |
proxyConfiguration | object | Apify Proxy | The proxy connection the run uses. Pinnacle refuses some connections; if a run fails with a 403 answer, pick a different proxy group or country here. |
Omit optional fields to use their defaults. Explicit [], "" or null
for a league list, market list, period list or date is an input error naming
the field. Dates must be exactly YYYY-MM-DD. Numeric league ids alone
collect only those ids. For local direct runs, set proxyConfiguration to
{"useApifyProxy": false}; selecting Apify Proxy locally fails before requests.
A misspelt input field, an unknown league or a window over the limits stops the run with an error that names the problem. A league id that does not exist is reported in the run's warnings; when it is the only league asked for, the run fails and says so.
Output
One record is one market of one game: "Giants v Commanders, full game, spread −2.5". A game with a moneyline, a spread and a total is three records; with alternate lines switched on, each extra line is one more record.
Every record has four parts:
recordKey:pinnacle:pinnacle:<game id>:<market key>. It is stable while the market exists; a spread at another line has another key.quote: the market in a flat, source-independent shape:league,sport,eventNativeId,startTime(UTC),home,away(Pinnacle's own team names);family:moneyline,moneyline_3way,spreads,totals,team_totals,propsorfutures;period:game,first_half,first_period,second_period,third_period, ortournamentfor futures;includesOvertime: for full-game lines,truewhen the market settles including overtime,falsewhen it settles on regulation time only,nullwhen Pinnacle's data does not say (see below);line: the home side's line for a spread, the total for totals and team totals, a prop's line when it has one,nullfor moneylines;subject: the player or team a prop or team total is about, for example{"type": "player", "name": "Jayden Daniels", "stat": "touchdown_passes"};selections: every side withrole(home,away,draw,over,under,yes,noorother),name, its ownline, and the price asamerican,decimalandimpliedProbability;limits.maxStake: the largest stake shown for the market;book,bookName,source,firstParty,collectedAt.
canonical: the same market as the shared envelope our other sports Actors use, for joining across sources. Pinnacle's own detail is undercanonical.extensions.pinnacle: market key, version counter, native period number, whether the line is an alternate, cutoff time, rotation number, the prop's title and category, andpricesSnapshotAt(see the FAQ).source,collectedAtandsourceUrl.
How to read the prices:
impliedProbabilityis1 / decimalof that single price. It includes the bookmaker's margin, so the sides of a market add up to more than 1.- A spread gives each side its own signed line: home
-2.5means the home team gives 2.5 points and the away side shows2.5. - The main line is marked
isAlternate: falseby Pinnacle; other lines are markedisAlternate: truein the extension. - Overtime: hockey full-game lines are
includesOvertime: true(the two-way moneyline); the regulation-time hockey lines you can switch on arefalse. Soccer match lines arefalse: the moneyline has a draw price and settles on regular time. For the NFL, NBA, UFC and other sports the value isnullbecause nothing in the data states it. Never compare atrueline with afalseline as if they were the same market. - Anything not published is
null, never estimated: a side without a price keeps its place inselectionswithamerican,decimalandimpliedProbabilityallnull, and so do the sides of a market that is not open.sourceUpdatedAtandurlare alwaysnullbecause no change time and no page address are published with the prices. The stake limit has no stated currency, solimits.currencyisnull. - For props and futures the market's title is in
canonical.market.nativeName(for example "AFC Conference Winner"). - UFC fighters are listed as
homeandawayin Pinnacle's own order; there is no home fighter, and the extension says so (homeAwayNominal: true).
The run summary (OUTPUT in the key-value store) reports records per market
family, games, priced and unpriced selections, records per league, requests
made, what was left out and why, warnings, and the status succeeded,
succeeded_empty, succeeded_partial or failed.
Output example
Selected fields of a real NFL spread recorded 2026-11-10 (full records also
carry canonical, source, sourceUrl and collectedAt):
{"recordKey":"pinnacle:pinnacle:1639394521:s;0;s;-2.5","quote":{"quoteVersion":"1.1","source":"pinnacle","book":"pinnacle","bookName":"Pinnacle","firstParty":true,"league":"nfl","sport":"american_football","eventNativeId":"1639394521","startTime":"2026-11-13T01:15:00Z","home":"New York Giants","away":"Washington Commanders","family":"spreads","period":"game","includesOvertime":null,"line":-2.5,"subject":null,"selections":[{"role":"home","name":"New York Giants","line":-2.5,"american":-105,"decimal":1.9524,"impliedProbability":0.5122},{"role":"away","name":"Washington Commanders","line":2.5,"american":-107,"decimal":1.9346,"impliedProbability":0.5169}],"limits":{"maxStake":20000.0,"currency":null},"sourceUpdatedAt":null,"collectedAt":"2026-11-10T23:55:00Z","url":null}}
Pricing
Pay per result: $0.0025 per record ($2.50 per 1,000 records) plus $0.00005 per run start. Each dataset record is one market of one game. See the Actor's Pricing tab on Apify for current rates. There is no separate charge for compute or proxy traffic.
At these rates, 20 records cost $0.05005 including the start, 100 records
cost $0.25005, and 1,000 records cost $2.50005. An empty run costs $0.00005
and adds no record charge. Use leagues, marketFamilies, mainLineOnly,
the date window and maxResults to keep runs small. A total-charge limit
can stop delivery below maxResults; OUTPUT reports the stored count and
a warning when this happens.
Scheduling and monitoring
- Line movement: schedule a league-scoped run (for example every 15
minutes on game days) and key your history on
recordKeypluscollectedAt. Group the lines of one game withquote.eventNativeId,quote.familyandquote.period. - Closing prices: games leave the list when they start, so the last run
before
quote.startTimeholds the closing price. Results and scores are not part of this Actor. - Records are a fresh snapshot each run; nothing is remembered between runs.
De-duplicate on
recordKey. - A run plans two requests per league at about one request start per second. Source retries and network latency can add requests and time.
FAQ
How fresh are the prices? Each run reads Pinnacle at run time, but the
price list a visitor without an account receives is refreshed only every few
minutes: on 2026-11-11 it was up to about 15 minutes old. Each record says
when its price list was produced (pricesSnapshotAt in the extension) next
to when the run read it (collectedAt). This is not a feed for in-play or
last-second prices.
Which line is the main line? The one Pinnacle does not mark as an alternate. There is exactly one per game, market and period.
Why does a league return nothing? Out of season it lists no games (MLB in November), and most leagues are priced only a few days ahead (the NBA about a day, the NFL the current week, the Premier League two rounds). Widen the date window for leagues that play weekly. With named leagues an empty result is a normal, uncharged run.
Why did a run fail with "Pinnacle answered 403"? Pinnacle refuses some
connections outright and answers others. The run says so and stops without
charging for records. Choose a different proxy group or country in
proxyConfiguration (for example residential proxies in the United States)
and run it again.
Are live (in-play) prices included? No. Only pre-match markets are collected.
Are hockey regulation-time prices included? On request. By default the
hockey moneyline, puck line and total are the full game including overtime.
Set includeRegulationTime to also get the regulation-time markets (the
moneyline with a draw price, and their own puck line and total); they have
the same period (game) and includesOvertime: false.
What are the stake limits? The largest stake shown to a visitor without an account for that market at that moment. Account limits can differ.
Export formats? JSON, CSV, Excel, XML or RSS from the dataset, or read it through the Apify API in your own pipeline.
Limits
- The data comes from an unofficial, undocumented guest interface of the sportsbook's website. It can change or be withdrawn without notice. Check a run's status and warnings before relying on it.
- One sportsbook. This is Pinnacle's price only, not a multi-book odds feed.
- Prices and limits are what a visitor without an account is shown, and can be several minutes old. No account features: no bet placement, balances, bet history or personal limits.
- Pre-match only. No live prices, scores, results or settled markets, and no historical series; build history by scheduling runs.
- Halves, quarters and periods are collected only where they map to a shared period name; second halves and later quarters are not, and baseball is full game only until its period numbers are confirmed in season.
- Prop subjects are read from Pinnacle's own titles: player totals name the
player and the statistic; other props keep their title in
canonical.market.nativeName. - At most 12 leagues, 31 days and 10,000 records per run.
- You are responsible for using the data in line with the terms of the sites it comes from and the laws that apply to you, including any rules on sports-betting information where you live.
For support, contact Apify support and include the Actor run ID.