Pinnacle Odds Scraper avatar

Pinnacle Odds Scraper

Pricing

from $2.50 / 1,000 market records

Go to Apify Store
Pinnacle Odds Scraper

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

Philip Kirkbride

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 hours ago

Last modified

Categories

Features

Limited permissions

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 canonical envelope our other sports Actors use, with explicit home and away, league, sport and start time.

Quick start

  1. 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.
  2. 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

NameTypeDefaultWhat it does
leaguesarrayNFL and NBALeagues 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.
leagueIdsarraynoneAny 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.
marketFamiliesarray["moneyline", "spreads", "totals"]Any of moneyline (includes the three-way price with a draw), spreads, totals, team_totals, props, futures.
periodsarray["game"]Any of game, first_half, first_period, second_period, third_period. A "period" is a quarter in football and basketball.
mainLineOnlybooleantrueKeep only the main spread, total and team total. Set false for every alternate line as its own record.
includeRegulationTimebooleanfalseHockey only: also collect the regulation-time markets (three-way moneyline with a draw, its own puck line and total), marked includesOvertime: false.
dateFrom / dateTostringtoday to today + 14Start-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.
maxResultsinteger1000Maximum dataset records per explicit run (1–10,000). Bare start: 20; Console prefill: 100.
requestDelaySecsnumber1Seconds between requests (0.5–10).
proxyConfigurationobjectApify ProxyThe 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, props or futures;
    • period: game, first_half, first_period, second_period, third_period, or tournament for futures;
    • includesOvertime: for full-game lines, true when the market settles including overtime, false when it settles on regulation time only, null when 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, null for 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 with role (home, away, draw, over, under, yes, no or other), name, its own line, and the price as american, decimal and impliedProbability;
    • 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 under canonical.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, and pricesSnapshotAt (see the FAQ).
  • source, collectedAt and sourceUrl.

How to read the prices:

  • impliedProbability is 1 / decimal of 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.5 means the home team gives 2.5 points and the away side shows 2.5.
  • The main line is marked isAlternate: false by Pinnacle; other lines are marked isAlternate: true in the extension.
  • Overtime: hockey full-game lines are includesOvertime: true (the two-way moneyline); the regulation-time hockey lines you can switch on are false. Soccer match lines are false: the moneyline has a draw price and settles on regular time. For the NFL, NBA, UFC and other sports the value is null because nothing in the data states it. Never compare a true line with a false line as if they were the same market.
  • Anything not published is null, never estimated: a side without a price keeps its place in selections with american, decimal and impliedProbability all null, and so do the sides of a market that is not open. sourceUpdatedAt and url are always null because no change time and no page address are published with the prices. The stake limit has no stated currency, so limits.currency is null.
  • For props and futures the market's title is in canonical.market.nativeName (for example "AFC Conference Winner").
  • UFC fighters are listed as home and away in 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 recordKey plus collectedAt. Group the lines of one game with quote.eventNativeId, quote.family and quote.period.
  • Closing prices: games leave the list when they start, so the last run before quote.startTime holds 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.