Sports Betting Odds Scraper — NFL, NBA, Soccer, Tennis & Props avatar

Sports Betting Odds Scraper — NFL, NBA, Soccer, Tennis & Props

Pricing

from $10.00 / 1,000 pre-match odds snapshots

Go to Apify Store
Sports Betting Odds Scraper — NFL, NBA, Soccer, Tennis & Props

Sports Betting Odds Scraper — NFL, NBA, Soccer, Tennis & Props

Scrape live and pre-match odds from Pinnacle (the sharp reference) and Bovada (largest US offshore book), keyless: moneyline, spreads, totals, specials and player props, de-vigged fair odds, line movement and best-price flags. College Football (NCAAF), NFL, MLB, NBA, soccer, tennis, NHL and UFC.

Pricing

from $10.00 / 1,000 pre-match odds snapshots

Rating

0.0

(0)

Developer

Sami

Sami

Maintained by Community

Actor stats

3

Bookmarked

136

Total users

41

Monthly active users

20 hours ago

Last modified

Share

Sports Betting Odds Scraper — Tennis, Soccer + Specials & Props

Status note (August 2026): This Actor is now multi-book. Pinnacle remains the reference sharp book (h2h, spreads, totals, AND its specials — thousands per sport in soccer, hundreds in NFL), Bovada is live as of 2026-08-29 — the largest US offshore book, keyless JSON verified from datacenter IPs, pre-match and live moneyline/spread/total across tennis, soccer, NFL, NBA, MLB and NHL — and Kambi adds Unibet and Paf plus Betsson, MrGreen and Storspiller where their market allows. Set books: ["pinnacle", "bovada"] for the sharp-baseline-vs-offshore pair every +EV workflow compares, or all three for the widest best-price sweep. The default stays ["pinnacle"], so nothing changes for existing runs unless you opt in. Bet365 remains under repair; its player-prop slot returns empty until it is back.

What the Start button runs. The Console form is prefilled for a cheap first try: Bovada, NFL + NHL, 15 events per sport — about 180 rows for ~$1.85. API calls and saved Tasks that omit books, sports or maxEventsPerSport keep the long-standing defaults: Pinnacle, soccer + tennis, 50.

The sportsbook odds scraper sharp bettors actually leave running. Pre-match + in-play odds from Pinnacle (the sharp reference) and Bovada (the largest US offshore book), plus the Kambi network, in one normalized feed — including Pinnacle's specials (thousands per sport in soccer, hundreds in NFL). Datacenter-proxy friendly, poll every 60 s or slower, with the same fixture matched across the books you enable. Pay-Per-Event from $0.01 per pre-match snapshot, $0.025 per live snapshot, $0.05 per specials / player-prop snapshot. Built for solo sharps, 2-3 person tipster shops, EV-modelling teams, and arbitrage operations who currently pay $249/mo for The Odds API or OddsJam Gold.

Pricing anchor: The Odds API sits at $249/mo for 15M credits ($0.0166/1K credits effective). OddsJam Gold is $249/mo monthly / $199/mo annual. This Actor delivers Pinnacle parity for ~$30-150/mo at typical sharp-bettor volume, and scales naturally past the OddsJam tier without you needing to "Contact Sales".

Fix note (21 August 2026) — your soccer runs now return the fixtures you asked for. Pinnacle changed its matchups endpoint: it now returns its special records (futures, yes/no, team props) even when they are not requested. In soccer those are 92% of the list — 19,707 of 21,395 entries — and this Actor was applying your maxEventsPerSport to the raw list before separating them out. The result: a run asking for 50 soccer fixtures was spending 44 of those 50 slots on records it then discarded, and emitting one event. Measured on the same input before and after the fix: 22 rows → 278 rows, 1 fixture → 47. Nothing about pricing changed ($0.01 per pre-match snapshot, as before), but because every snapshot is billed, a soccer run at the default cap now costs about $2.78 instead of $0.22. If that is more volume than you want, lower maxEventsPerSport — it now means what it says. Tennis and the other sports were never affected. Runs from build 0.3.26 onward.

Data corrections (September 2026) — what changes in your rows. Prices did not change.

  • Line-movement history restarts once, on every row of every book. The dedup/movement key now includes the book's own market id, so no row can inherit a different market's previous price. On your first run after this build previousPrice, priceChange, moveDirection, firstSeenPrice and moveSinceFirstSeen are absent; from the second run they are correct again.
  • Pinnacle away spread rows now carry their own line (e.g. +3.0 instead of -3.0); their snapshotId changes.
  • isBestPriceAcrossBooks is only set when at least two books quote the same outcome and line.
  • Bovada spreads now get fair odds when includeFairOdds is on (they came back empty), so those rows now also bill fair-odds-enrichment.
  • Bovada Asian quarter lines show the real line (-1.25, not -1.0).
  • Pinnacle 1st-half and 1st-quarter lines are no longer emitted as full-game h2h / spreads / totals rows. This applies to every Pinnacle run, with or without includeAlternateLines: measured on the saved NFL payload (h2h + spreads + totals), a default run at maxEventsPerSport 50 goes from 446 to 284 rows and one with alternates from 2,262 to 1,620 — all of them correctly labelled, and billed accordingly. If you were buying those rows, ask for them by period through the enterprise contact; do not read the drop as missing data.
  • Pinnacle over/under specials (per-game player props, season win totals) are now included: NFL specials went from 834 to 1,002 rows at full depth on the same payload (measured 2026-09-15).
  • Bovada events listed as pre-match that had already started are skipped and not charged; the run status gives the count.
  • Kambi: American football now returns rows, book shows the operator (Unibet, Paf…) and outcomes are home/away. Ice hockey is requested too, but Kambi lists only regulation-time hockey markets (a 3-way result and regulation totals), which are skipped rather than mixed with full-game lines, so it returns nothing yet. Kambi history restarts once.

How to scrape sports odds in 3 easy steps

  1. Pick your sports. Default is ["soccer", "tennis"] — the two highest-liquidity sharp markets year-round. Add basketball / MMA / baseball as your season picks up. Default book is ["pinnacle"]; add "bovada" for the largest US offshore book (the sharp-vs-offshore pair +EV models compare), and "kambi" for Unibet / Paf and the rest of the Kambi network in the same feed (Bet365 mode still under repair).
  2. Pick your market types. h2h (moneyline) + spreads + totals is the canonical EV-modelling triad. Add specials for Pinnacle's futures / yes-no / exact-totals / first-team-to-score / winning-margin / team-props markets and its over/under player props (premium $0.05 tier — these are the markets sharps and tipster shops actually mine for edge, and they are the segment OddsJam / The Odds API gate behind their highest tiers). player_props is the Bet365-only player-prop slot (returns empty while Bet365 is under repair). team_totals adds each team's own over/under from Pinnacle — measured 2026-09-18 at 399 markets in American football and 155 in baseball, about +20% and +40% on top of the base three — billed like any pre-match snapshot, with outcome keys home_over / home_under / away_over / away_under.
  3. Schedule a cron. Apify Saved Tasks → Schedules → e.g. */5 * * * * for 5-minute pre-match polling, * * * * * for in-play during target matches. To cut what you pay for unchanged prices, raise deduplicationWindowSeconds. The window is measured from the last time the row was delivered, not from the last run: an unchanged price is billed again as soon as the window has elapsed since its last delivery. So use the largest window you can tolerate — on a */5 Schedule, 3600 (the maximum) bills an unchanged row on about 1 run in 12, 600 on 1 in 3, 360 on 1 in 2, and the default 30 on every run. A changed price is always delivered and billed immediately, whatever the window.

That's it. Snapshots land in your Apify dataset, ready for export to your EV pipeline, Discord bot, or Sheets workbook.


Enterprise inquiry

Running >50K snapshots/month, need a dedicated polling cadence per book, custom market types (Asian handicap quarter-lines, derivative props, fancy bets), or a schema SLA for a downstream production pipeline? Contact the author through the Actor page — webhook integrations, dedicated proxy pools, and custom dataset views ship in ~1 week. Players who run sustained 7-figure-action operations can also discuss a dedicated-instance posture.


Who buys this Actor

Buyer personaTypical monthly spendWhy this Actor wins
Solo sharp bettor (10-30 events/day)$30-80/moReplaces a $59 The Odds API tier with two books in one feed and cross-book best-price flagging built in
2-3 person tipster operation$100-250/moPre-match polling on a 5-min cron across 50-100 fixtures/day, h2h+spreads+totals
EV-modelling solo / small team$200-650/moPinnacle's sharp closing lines are the canonical fair-value benchmark — feed straight into your EV-model with delta polling
Specials / futures trader$150-500/moPinnacle specials — thousands per sport in soccer, hundreds in NFL (futures, exact-totals, first-to-score, winning margins, over/under player props) — the segment OddsJam gates behind their highest tier
In-play model / fantasy ladder$650-1,900/moLive-only mode + 60-180s cadence + isLive on every row (match clock and score not populated yet)
Sports-media analyst / blog$35-120/moDaily pre-match dump for "lines moved" content; 6h cron covers the news cycle

Example use cases

  1. Pinnacle closing-line value (CLV) trackermode: "pre_match_only", run at T-30min and T-1min per fixture. Bet your soft book at T-30, measure CLV against Pinnacle's T-1 close. Pinnacle is the canonical sharp benchmark for fair-value. Cost: ~7 rows × $0.01 per fixture per capture, plus $0.05 per run that delivers rows.
  2. EV-model live edge harvestermode: "live_only", 60-second cron, NBA + tennis + soccer. Stream snapshots into your model; emit a bet ticket when (your_fair_value × book_price) > 1.03. ~$1,250/mo per 50K live snapshots/month ($0.025 each), plus $0.05 per run that delivers rows.
  3. Tipster Discord auto-postersports: ["soccer"], leagueFilter: ["UEFA", "EPL"], 6h cron. Webhook → Discord with the day's top 10 spreads + totals. Cost: 120 runs/month × (fixtures × ~7 rows × $0.01 + $0.05).
  4. Specials / futures snipermarketTypes: ["specials"], sports: ["soccer"], 4h cron during the season. Soccer carries thousands of Pinnacle specials (yes/no markets, exact totals, first-to-score, winning margins) — the segment where soft books haven't fully sharpened up. Cost: 180 runs/month × specials rows × $0.05 — cap the volume with maxEventsPerSport.
  5. The Odds API replacement (Pinnacle slice) — drop-in feed for teams currently paying $249/mo The Odds API just for the Pinnacle column. ~$0.01-0.05 per snapshot vs. $0.0166/1K credits effective — flips small/medium volume in your favor; raise the dedup window so unchanged prices are billed less often (see step 3 for the exact rule).
  6. Cross-book best-priceincludeBestPriceFlag: true compares prices per outcome across the books you enable, e.g. books: ["pinnacle", "bovada"]. It only fires on fixtures BOTH books cover, and only on outcomes both books quote at the same line. Measured 2026-08-02: a soccer run returned 2 Pinnacle fixtures against 60 Kambi ones with zero overlap, so the flag stayed false on all 186 rows — working as designed, but useless without shared fixtures. The run's status message now reports how many fixtures were matched across books, so you can tell "nothing was cheaper" apart from "the books never met". To force overlap, raise maxEventsPerSport and use leagueFilter to pin both books to the same competitions.

Line movement — included, not an add-on

Every snapshot is compared against the last price this account's runs saw for the same book + event + market + line + outcome, so a cron turns into a movement feed instead of a pile of disconnected prices:

FieldMeaning
previousPrice / previousPriceAtThe prior price for this exact outcome, and when it was seen
secondsSincePreviousPriceGap between the two observations
priceChange / priceChangePctDecimal-odds delta and percentage
impliedProbChangeChange in implied probability — the direction sharps read (odds down = probability up)
moveDirectionshortened (price fell), drifted (price rose) or unchanged
firstSeenPrice / firstSeenPriceAtThe first price your runs ever recorded for this outcome
moveSinceFirstSeen / moveSinceFirstSeenPctTotal movement since that first observation

It is free. The dedup window already stores the last price per outcome, so movement costs no extra request and carries no extra charge — turn it off with includeLineMovement: false if you want the leaner rows.

Honest naming: firstSeenPrice is the first price your runs observed, not the book's true opening line — no scraper can retro-fetch a line it never saw. Start a cron early on the fixtures you care about and it becomes your opener. Movement fields appear from the second run of a market onward, since the first run has nothing to compare to.

{
"books": ["pinnacle"],
"sports": ["soccer"],
"mode": "pre_match_only",
"includeLineMovement": true,
"deduplicationWindowSeconds": 30
}

Dedup suppresses an unchanged price only while the window has not yet elapsed since that row was last delivered (a suppressed run does not restart the clock). At the default 30 s that is almost never, so every scheduled run bills every row; at the 3600 maximum a */5 Schedule bills an unchanged row on about 1 run in 12.

Corrected 11 September 2026 — American football on Pinnacle. Until this build, every Pinnacle American-football row (NFL and NCAA) carried the same team in homeTeam and awayTeam — the away side overwrote the home slot — so outcome labels named the wrong team and those fixtures never matched Bovada's, leaving isBestPriceAcrossBooks false. Tennis, basketball, soccer and every Bovada row were not affected. If you consumed Pinnacle football rows before this date, re-pull them; open an issue and it will be made right.

Pricing (Pay-Per-Event)

EventPriceWhen it fires
odds-snapshot-pre-match$0.01 / snapshotOne market-outcome from a scheduled (not in-play) fixture. Default tier for 5-15 min cron workflows.
odds-snapshot-live$0.025 / snapshotOne market-outcome from a live (in-play) match. Premium tier — bot pressure on live endpoints is higher.
odds-snapshot-player-prop$0.05 / snapshotOne Pinnacle special (futures / yes-no / exact-totals / first-to-score / winning-margin / team prop) OR one Bet365 player-prop. Highest WTP segment of sports betting data.
scheduled-run$0.05 / runOnce per Actor invocation that delivered at least one row. A run that returns nothing — dedup suppressed everything, no fixtures matched, a book was unreachable — bills nothing at all.
fair-odds-enrichment$0.05 / snapshotOnly when includeFairOdds is on (off by default). Adds the vig-free fair price, fair probability and overround to a row, on top of its base snapshot price.

Prices effective 8 August 2026. Live snapshots moved from $0.020 to $0.025 and player-props / specials from $0.040 to $0.050 on that date; fair-odds-enrichment is new and opt-in. Pre-match ($0.01) and scheduled-run ($0.05) are unchanged.

How to estimate your monthly cost

Cost formula: runs per month × rows per run × $0.01 (pre-match; $0.025 live, $0.05 specials; plus $0.05 per row that carries a fair price when includeFairOdds is on) + runs that delivered rows × $0.05. Runs per month = 43,200 ÷ interval in minutes. Rows per fixture for h2h + spreads + totals measured 2026-09-15: 6.0 (Bovada NFL), 7.0 (Bovada soccer). The Schedule table further down gives upper bounds with nothing suppressed; how many prices stay unchanged is not measured, so no discount is promised.

In Apify Console, the built-in apify-default-dataset-item event is set to $0.00001 to avoid double-billing — your actual line items are the four events in the table above.


Python example

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("zhorex/sports-odds-aggregator").call(run_input={
"books": ["pinnacle"],
"sports": ["soccer", "tennis"],
"marketTypes": ["h2h", "spreads", "totals", "specials"],
"mode": "pre_match_only",
"maxEventsPerSport": 50,
"deduplicationWindowSeconds": 30,
})
for snapshot in client.dataset(run["defaultDatasetId"]).iterate_items():
if snapshot["marketType"] == "specials" and snapshot["impliedProbability"] < 0.10:
# Pinnacle special at >10x implied — possible long-shot value edge.
evaluate_for_bet(snapshot)

JavaScript example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('zhorex/sports-odds-aggregator').call({
books: ['pinnacle'],
sports: ['basketball'],
marketTypes: ['h2h', 'spreads', 'totals'],
mode: 'live_only',
deduplicationWindowSeconds: 0, // emit every snapshot during in-play runs
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const liveSpreads = items.filter(s => s.isLive && s.marketType === 'spreads');
console.log(`${liveSpreads.length} live spread snapshots`);

Scheduled / recurring runs — the money section

This is what turns the Actor from a one-off scraper into a $250/mo replacement for $1,500/mo SaaS. The recipe:

  1. Run once with the prefilled input (Bovada, NFL + NHL, 15 events per sport) to check your sport and league return data; add "pinnacle" to books for the sharp reference line.

🏈 College football (NCAAF) is the deepest American-football board right now. Measured on Bovada's own pre-match coupon on 2026-09-17: 57 College Football fixtures against 16 NFL. The league label the books report is College Football, so ask for it by name:

{
"books": ["bovada", "pinnacle"],
"sports": ["american_football_intl"],
"leagueFilter": ["College Football", "NCAA"],
"marketTypes": ["h2h", "spreads", "totals"],
"mode": "pre_match_only",
"maxEventsPerSport": 40
}

leagueFilter is a case-insensitive substring whitelist, so ["College Football", "NCAA"] catches both spellings and leaves NFL and CFL out. Drop the filter to get every league the sport carries.

  1. Save as a Task with your tuned sports / marketTypes / mode / dedupWindow combination.
  2. Open the Task → Schedules → New Schedule with one of the cron strings below.
  3. Add a webhook to the Schedule to ship the dataset into your EV pipeline, Discord/Slack bot, or Sheets workbook.
Use caseCron stringRuns / monthUpper bound, nothing suppressed
Pre-match every 5 min, 20 fixtures (~130 rows/run)*/5 * * * *8,640$11,700/mo — dedup only moves this if you raise the window: at 3600 a row that never moves bills on 1 run in 12 ($1,000 in that extreme), at 360 on 1 in 2 ($5,900)
Every 6 hours, 20 fixtures0 */6 * * *120~$160/mo
Daily 9am dump, 30 fixtures0 9 * * *30~$60/mo
Weekly audit, 20 fixtures0 10 * * 6~4~$6/mo
In-play every minute* * * * *up to 43,200live rows bill $0.025 each — limit the Schedule to match windows

Cut what a Schedule pays for unchanged prices. deduplicationWindowSeconds is measured from the last time a row was delivered, not from the previous run, so an unchanged price is billed again every time the window elapses. Measured on a */5 Schedule against a price that never moves: 3600 (the maximum) bills it on about 1 run in 12, 600 on 1 in 3, 360 on 1 in 2, and the default 30 on every run — use the largest window your staleness tolerance allows. A run whose rows were all suppressed delivers nothing and bills nothing (no per-run fee).

Corrected 10 September 2026. Until this build the $0.05 per-run fee was charged on every invocation, including the ones that returned an empty dataset, so a tight cron on stable prices could bill a standing fee for nothing. It no longer does. If that affected you, open an issue and it will be made right.


Example input

{
"books": ["pinnacle"],
"sports": ["soccer"],
"leagueFilter": ["EPL", "La Liga", "UEFA"],
"marketTypes": ["h2h", "spreads", "totals", "specials"],
"mode": "pre_match_only",
"priceFormat": "decimal",
"maxEventsPerSport": 50,
"includeBestPriceFlag": true,
"includeFairOdds": true,
"deduplicationWindowSeconds": 30,
"proxyConfiguration": { "useApifyProxy": true }
}

Example output (one snapshot record)

{
"snapshotId": "a1b2c3d4e5f6789012345678",
"book": "pinnacle",
"sport": "soccer",
"league": "Premier League",
"eventId": "1583217845",
"homeTeam": "Manchester City",
"awayTeam": "Liverpool",
"commenceTime": "2026-05-22T19:00:00Z",
"isLive": false,
"matchClock": null,
"matchScore": { "home": null, "away": null },
"marketType": "h2h",
"marketLine": null,
"outcomeKey": "home",
"outcomeLabel": "Home",
"price": 1.91,
"priceAmerican": -110,
"priceFractional": "10/11",
"impliedProbability": 0.52356,
"overround": 0.045,
"noVigProb": 0.5011,
"noVigFairPrice": 1.9956,
"isBestPriceAcrossBooks": false,
"scrapedAt": "2026-05-18T14:32:00Z"
}

A typical run for one Pinnacle fixture with ["h2h", "spreads", "totals"] emits ~7 snapshot records (3 outcomes h2h + 2 outcomes spreads + 2 outcomes totals). Add "specials" to that input and you typically get an extra 30-80 specials snapshots per fixture (yes/no markets, exact totals, first-to-score, winning margin per scoreline, etc.).


Output schema reference

FieldTypeNotes
snapshotIdstringStable id sha1(book | event | market | outcome | marketLine | marketKey | scrapedAt)[:24] — use as dataset primary key. marketLine and marketKey are part of it so every rung of an alternate ladder stays distinct
bookstringpinnacle, bovada, or the Kambi operator name when kambi is enabled (Unibet, Paf, Betsson, MrGreen, Storspiller). Bet365 mode in repair — when it returns, this column also surfaces bet365.
sportstringCanonical sport key (e.g. soccer, tennis, basketball)
leaguestringBook-reported league/competition name
eventIdstringBook-native event id (not portable across books — use homeTeam+awayTeam+commenceTime for joins)
homeTeamstring
awayTeamstring
commenceTimeISO 8601UTC scheduled start time
isLiveboolTrue if the match is currently in-play
matchClockstring | nullNot populated yet — null on every book
matchScoreobject{ "home": null, "away": null } today — live score not populated yet
marketTypestringh2h, spreads, totals, first_half_h2h, first_half_spreads, first_half_totals, specials, player_props, team_totals
marketLinefloat | nullSpread or total line of THIS outcome (e.g. home -1.5 / away 1.5, total 2.5; Asian quarter lines as -1.25); null for h2h. For Pinnacle over/under specials it is the prop's line
marketKeystringThe book's own market id — Pinnacle (s;0;s;-1.5, s;0;ou;2.5) and Bovada; absent on Kambi and on Pinnacle yes/no specials. Both sides of one market share it, which is how fair odds pair them. Use it when two rows share a market type, line and outcome but quote different prices — that happens with alternate ladders, and this is what tells them apart
isAlternateboolPresent on Pinnacle spread/total/team-total rows when includeAlternateLines is on: true for the extra rungs of the ladder, false for the primary line. Absent on h2h (no line, so the notion does not apply) and on other books, which do not expose it
outcomeKeystringhome, away, draw, over, under, yes, no
outcomeLabelstringHuman label (e.g. "Over 2.5", "Manchester City")
pricefloatDecimal odds (canonical internal format)
priceAmericanintAlways populated (e.g. -110, +180)
priceFractionalstringAlways populated (e.g. "10/11", "7/4")
impliedProbabilityfloat1 / price (raw — still includes the vig)
overroundfloat | nullThe market's total margin: Σ(1/price) − 1 (e.g. 0.045 = 4.5% vig). null for an incomplete market line
noVigProbfloat | nullVig-free fair probability — the implied prob divided by the market overround so a line's outcomes sum to 1. The true-probability estimate sharps actually bet against
noVigFairPricefloat | nullVig-free fair decimal odds (1 / noVigProb) — the book's price with its margin stripped out (on Pinnacle, the CLV / +EV benchmark number). Computed per market for h2h, spreads, totals and specials when includeFairOdds is on
isBestPriceAcrossBooksboolTrue if this is the highest price for this (event, market, outcome, line) and at least two of your books quote that outcome and line; every tied row is flagged. False when no other book quoted it
scrapedAtISO 8601UTC timestamp when the snapshot was captured

What this Actor is NOT

Honest scoping so you don't waste a run finding out:

  • NOT US bookmakers. DraftKings / FanDuel / BetMGM / Caesars / ESPN BET / William Hill US are geo-gated behind Akamai and require US residential proxy, pushing per-snapshot cost ~10x. Other Apify Actors target those — this one stays out.
  • NOT a managed data feed. Pinnacle's Terms of Service forbid commercial resale of raw odds. You are buying a SCRAPER (infrastructure that runs in YOUR Apify account, executes per-buyer), not a centralized data feed redistributed to many. See "Compliance posture" below.
  • NOT real-time WebSocket. This is a poll-based scraper, not a streaming feed. The fastest meaningful cadence is ~60s (limited by both API rate-tolerance and the value of polling faster than the book's own line updates).
  • NOT a guaranteed-uptime SLA. Pinnacle occasionally restructures their guest API path; the Actor has defensive degradation (graceful empty-result on schema drift, adaptive backoff on burst errors) and the author ships defensive patches within 48h of any production breakage — but it's not Bloomberg.
  • NOT exchange-style limit-order books. Betfair Exchange / Smarkets are different surfaces (depth-of-book, peer-to-peer pricing, commission model). Smarkets is on the v0.4 roadmap.

Proxy configuration — datacenter friendly

Most competing odds scrapers ship with RESIDENTIAL as the default and burn 10-20× the proxy budget. This Actor's default is plain useApifyProxy: true (no specific group required), so it runs on whichever proxy tier your Apify plan includes. For the lowest proxy cost:

  • Pinnacle's publicly accessible odds surface tolerates datacenter IPs by design — that's the entire reason Pinnacle is on the supported-books list, and the default proxy setting already uses them, so you pay roughly 5% of what a residential-default scraper costs. Leave proxyConfiguration alone: there is no Apify proxy group literally named DATACENTER, and passing one makes the run refuse to start. Pinnacle does block individual exit ranges from time to time; the Actor rotates exits and, if a sport still comes back with nothing, says so in the run status. If you see that repeatedly, set apifyProxyGroups: ["RESIDENTIAL"] for that run.
  • Residential is also fine and is the most universal fallback. Pinnacle responds 200 on plain residential without any cookie / fingerprint setup.
  • If your run logs show persistent backoff-active or throttled status on the pinnacle bucket, switch to residential or lower your scheduled-run frequency.

FAQ

Q: Is this the best Pinnacle scraper for 2026? Yes — this is the only Apify Store Actor that ships Pinnacle's full h2h + spreads + totals + its specials (thousands per sport in soccer, hundreds in NFL: futures, yes/no, exact totals, first-to-score, winning margin, team props, over/under player props) with proper American→decimal odds conversion and cross-run dedup state. The next-best Pinnacle-related actor on the store has 25 MAU and a 1.0★ rating.

Q: Is this a Pinnacle API alternative? It IS a wrapper over Pinnacle's publicly accessible guest API, normalized into a single per-market-outcome snapshot schema with both American AND decimal AND fractional price formats AND implied probability on every row. Plus the specials bucket (which Pinnacle exposes but is annoying to flatten yourself) and cross-run dedup state (which a one-off API client doesn't get for free).

Q: When does Bet365 come back? Bet365's publicly accessible odds surface returned HTTP 403 across every variant we probed in May 2026 (8 paths × datacenter AND USA residential). The path itself is dead, not just IP-blocked — even their public homepage 403s. Bet365 will return when either (a) their anti-bot posture relaxes, or (b) the scraping community documents a new entry point. Cross-book comparison already works today with Pinnacle + Bovada.

Q: How does this compare to The Odds API? The Odds API wraps ~80 books behind one paid endpoint at $59/$119/$249/mo tiered. This Actor gives you DIRECT scraped data from Pinnacle (the most-cited sharp-line book) without a middleman, at PPE pricing that beats The Odds API on small/medium workloads. It does NOT give you DraftKings or FanDuel — for those you need The Odds API or a US-residential scraper.

Q: Is this an OddsJam alternative pay-per-use? For OddsJam users whose primary value is line-tracking on a fixed cron, yes — typical OddsJam Gold customers will spend $50-200/mo here vs $249/mo there. Specials especially: OddsJam gates futures + props behind their highest tier; this Actor exposes them at $0.05/snapshot. For OddsJam users whose primary value is the proprietary EV models on top of the data, no — this Actor sells you the data, not the model.

Q: Can I use this for sports arbitrage? Yes. Pinnacle and Bovada are both live, so one run compares the same fixture across a sharp and an offshore book — the run status tells you how many fixtures matched across books. Compare price across books on matched fixtures; isBestPriceAcrossBooks flags the best price only when at least two of your books quote that outcome and line.

Q: Can I use this for in-play odds API workflows? Yes — mode: "live_only" with a 60-180s cron. isLive is set on every snapshot; match clock and score are not populated yet. Be aware the live tier charges $0.025/snapshot vs $0.01 pre-match.

Q: What ARE these "specials"? Pinnacle's withSpecials=true matchups call returns thousands per sport in soccer and a few hundred in American football (280 measured 2026-09-15, including over/under player props such as a quarterback's total interceptions): "First Team To Score" (3-way), "Win to Nil 1st Half" (Yes/No), "Exact Total Goals 1st Half" (multi-way), "Winning Margin" (per scoreline), and lots of team prop variants. They are the segment soft books are slowest to sharpen up on, so they have the most edge for value bettors and exact-totals modellers.

Q: Do I need a Pinnacle account login? No. The Actor reads only data that is publicly displayed on Pinnacle's anonymous guest API (the same API their own marketing-site widgets use). Never set up account-authenticated cookies you don't want exposed to a scraper.

Q: Does this work for esports? Pinnacle covers esports (CS2, Dota 2, LoL, Valorant), but only a subset of leagues are reliably priced pre-match — most esports volume is in-play. Use sports: ["esports"], mode: "pre_match_and_live".


Compliance posture

This Actor is a scraper tool sold to bettors who run it in their own Apify account for personal analysis, not a centralized commercial data feed.

  • Personal-analysis use only. Pinnacle's Terms of Service forbid commercial redistribution of raw odds. Buyers run their own instance against their own polling cadence — the architecture is per-buyer-execution by design.
  • No login bypass. The Actor accesses only data that is publicly displayed on Pinnacle's anonymous guest API. It will not authenticate to your account.
  • Rate-limited politely. Adaptive backoff prevents burst-traffic that would degrade Pinnacle's service for real users. If a buyer configures an aggressive cadence the backoff will throttle automatically.
  • Respect local law. Sports betting and odds-data scraping are legal in many jurisdictions but not all. Confirm before using.
  • Do not resell the data feed. If you want to redistribute scraped odds commercially, you need a licensed data agreement with Pinnacle — this Actor is not that agreement.

Roadmap

  • v0.3 (shipped, current). Pinnacle h2h + spreads + totals + specials; Bovada live since 2026-08-29; cross-book fixture matching.
  • v0.4 — Smarkets adapter. UK betting exchange, public API, no auth. Peer-to-peer pricing genuinely different from Pinnacle → adds exchange prices to the cross-book comparison.
  • v0.5 — Pinnacle alternate lines SHIPPED. Set includeAlternateLines: true. It needed no per-matchup fan-out after all: the same markets/straight call returns the whole ladder once primaryOnly is dropped. Measured 2026-08-07 on billable pre-match rows: ×1.66 soccer, ×2.59 tennis, ×3.24 basketball, ×1.58 baseball, ×1.00 ice hockey. Period markets beyond period 0 are still open. Fan-out to related/straight opens half/quarter handicap decomposition).
  • v0.6 — Betfair Exchange adapter (bring-your-own-credentials, opt-in tier for buyers who already have a Betfair account + App Key).
  • v0.7 — WebSocket mode where the book supports it, for sub-second in-play cadence.
  • v0.8 — Automatic arb finder. First-class output filter that emits only the rows that compose a positive-EV cross-book arb.

⭐ Review CTA

If this Actor saves you the $249/mo The Odds API subscription, a 30-second review is the single best thing you can do for the developer — it directly funds the next defensive patch when the books shift their schemas. The review page is apify.com/zhorex/sports-odds-aggregator/reviews.

For sharp-bettor research and finding new betting markets, see also the companion AI research Actor: zhorex/perplexity-ai-scraper.

Last updated: September 2026 — built and maintained by zhorex. Defensive patches typically ship within 48h of any production breakage.