Sports Betting Odds Scraper — NFL, NBA, Soccer, Tennis & Props
Pricing
from $10.00 / 1,000 pre-match odds snapshots
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
Maintained by CommunityActor stats
3
Bookmarked
136
Total users
41
Monthly active users
19 hours ago
Last modified
Categories
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,sportsormaxEventsPerSportkeep 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
specialrecords (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 yourmaxEventsPerSportto 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, lowermaxEventsPerSport— 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,firstSeenPriceandmoveSinceFirstSeenare absent; from the second run they are correct again.- Pinnacle away spread rows now carry their own line (e.g.
+3.0instead of-3.0); theirsnapshotIdchanges.isBestPriceAcrossBooksis only set when at least two books quote the same outcome and line.- Bovada spreads now get fair odds when
includeFairOddsis on (they came back empty), so those rows now also billfair-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/totalsrows. This applies to every Pinnacle run, with or withoutincludeAlternateLines: measured on the saved NFL payload (h2h + spreads + totals), a default run atmaxEventsPerSport50 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,
bookshows the operator (Unibet, Paf…) and outcomes arehome/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
- 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). - Pick your market types.
h2h(moneyline) +spreads+totalsis the canonical EV-modelling triad. Addspecialsfor 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_propsis the Bet365-only player-prop slot (returns empty while Bet365 is under repair).team_totalsadds 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 keyshome_over/home_under/away_over/away_under. - 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, raisededuplicationWindowSeconds. 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*/5Schedule,3600(the maximum) bills an unchanged row on about 1 run in 12,600on 1 in 3,360on 1 in 2, and the default30on 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 persona | Typical monthly spend | Why this Actor wins |
|---|---|---|
| Solo sharp bettor (10-30 events/day) | $30-80/mo | Replaces 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/mo | Pre-match polling on a 5-min cron across 50-100 fixtures/day, h2h+spreads+totals |
| EV-modelling solo / small team | $200-650/mo | Pinnacle's sharp closing lines are the canonical fair-value benchmark — feed straight into your EV-model with delta polling |
| Specials / futures trader | $150-500/mo | Pinnacle 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/mo | Live-only mode + 60-180s cadence + isLive on every row (match clock and score not populated yet) |
| Sports-media analyst / blog | $35-120/mo | Daily pre-match dump for "lines moved" content; 6h cron covers the news cycle |
Example use cases
- Pinnacle closing-line value (CLV) tracker —
mode: "pre_match_only", run atT-30minandT-1minper 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. - EV-model live edge harvester —
mode: "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. - Tipster Discord auto-poster —
sports: ["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). - Specials / futures sniper —
marketTypes: ["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 withmaxEventsPerSport. - 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).
- Cross-book best-price —
includeBestPriceFlag: truecompares 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 stayedfalseon 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, raisemaxEventsPerSportand useleagueFilterto 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:
| Field | Meaning |
|---|---|
previousPrice / previousPriceAt | The prior price for this exact outcome, and when it was seen |
secondsSincePreviousPrice | Gap between the two observations |
priceChange / priceChangePct | Decimal-odds delta and percentage |
impliedProbChange | Change in implied probability — the direction sharps read (odds down = probability up) |
moveDirection | shortened (price fell), drifted (price rose) or unchanged |
firstSeenPrice / firstSeenPriceAt | The first price your runs ever recorded for this outcome |
moveSinceFirstSeen / moveSinceFirstSeenPct | Total 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
homeTeamandawayTeam— the away side overwrote the home slot — so outcome labels named the wrong team and those fixtures never matched Bovada's, leavingisBestPriceAcrossBooksfalse. 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)
| Event | Price | When it fires |
|---|---|---|
odds-snapshot-pre-match | $0.01 / snapshot | One market-outcome from a scheduled (not in-play) fixture. Default tier for 5-15 min cron workflows. |
odds-snapshot-live | $0.025 / snapshot | One market-outcome from a live (in-play) match. Premium tier — bot pressure on live endpoints is higher. |
odds-snapshot-player-prop | $0.05 / snapshot | One 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 / run | Once 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 / snapshot | Only 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-enrichmentis new and opt-in. Pre-match ($0.01) andscheduled-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 ApifyClientclient = 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:
- Run once with the prefilled input (Bovada, NFL + NHL, 15 events per sport) to check your sport and league return data; add
"pinnacle"tobooksfor 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}
leagueFilteris 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.
- Save as a Task with your tuned
sports / marketTypes / mode / dedupWindowcombination. - Open the Task → Schedules → New Schedule with one of the cron strings below.
- Add a webhook to the Schedule to ship the dataset into your EV pipeline, Discord/Slack bot, or Sheets workbook.
| Use case | Cron string | Runs / month | Upper bound, nothing suppressed |
|---|---|---|---|
| Pre-match every 5 min, 20 fixtures (~130 rows/run) | */5 * * * * | 8,640 | 3600 a row that never moves bills on 360 on 1 in 2 ( |
| Every 6 hours, 20 fixtures | 0 */6 * * * | 120 | ~$160/mo |
| Daily 9am dump, 30 fixtures | 0 9 * * * | 30 | ~$60/mo |
| Weekly audit, 20 fixtures | 0 10 * * 6 | ~4 | ~$6/mo |
| In-play every minute | * * * * * | up to 43,200 | live rows bill $0.025 each — limit the Schedule to match windows |
Cut what a Schedule pays for unchanged prices.
deduplicationWindowSecondsis 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*/5Schedule against a price that never moves:3600(the maximum) bills it on about 1 run in 12,600on 1 in 3,360on 1 in 2, and the default30on 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.05per-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
| Field | Type | Notes |
|---|---|---|
snapshotId | string | Stable 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 |
book | string | pinnacle, 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. |
sport | string | Canonical sport key (e.g. soccer, tennis, basketball) |
league | string | Book-reported league/competition name |
eventId | string | Book-native event id (not portable across books — use homeTeam+awayTeam+commenceTime for joins) |
homeTeam | string | |
awayTeam | string | |
commenceTime | ISO 8601 | UTC scheduled start time |
isLive | bool | True if the match is currently in-play |
matchClock | string | null | Not populated yet — null on every book |
matchScore | object | { "home": null, "away": null } today — live score not populated yet |
marketType | string | h2h, spreads, totals, first_half_h2h, first_half_spreads, first_half_totals, specials, player_props, team_totals |
marketLine | float | null | Spread 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 |
marketKey | string | The 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 |
isAlternate | bool | Present 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 |
outcomeKey | string | home, away, draw, over, under, yes, no |
outcomeLabel | string | Human label (e.g. "Over 2.5", "Manchester City") |
price | float | Decimal odds (canonical internal format) |
priceAmerican | int | Always populated (e.g. -110, +180) |
priceFractional | string | Always populated (e.g. "10/11", "7/4") |
impliedProbability | float | 1 / price (raw — still includes the vig) |
overround | float | null | The market's total margin: Σ(1/price) − 1 (e.g. 0.045 = 4.5% vig). null for an incomplete market line |
noVigProb | float | null | Vig-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 |
noVigFairPrice | float | null | Vig-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 |
isBestPriceAcrossBooks | bool | True 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 |
scrapedAt | ISO 8601 | UTC 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
proxyConfigurationalone: there is no Apify proxy group literally namedDATACENTER, 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, setapifyProxyGroups: ["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-activeorthrottledstatus on thepinnaclebucket, 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 linesSHIPPED. SetincludeAlternateLines: true. It needed no per-matchup fan-out after all: the samemarkets/straightcall returns the whole ladder onceprimaryOnlyis 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 torelated/straightopens 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.