Sports Odds Aggregator: Pinnacle + Bovada Odds Feed
Pricing
from $9.00 / 1,000 results
Sports Odds Aggregator: Pinnacle + Bovada Odds Feed
One odds feed from Pinnacle and Bovada: moneyline, spreads and totals for soccer, NFL, NBA, MLB, NHL, tennis and MMA with no-vig fair odds, best-price flags and line movement. No API key.

What does Sports Odds Aggregator: Pinnacle + Bovada Odds Feed do?
Sports Odds Aggregator pulls pre-match and live betting odds from Pinnacle (the sharp reference book) and Bovada (the largest US offshore book) into one clean, normalized table. Every row is one outcome of one market - moneyline, spread or total - for soccer, NFL and college football, NBA, MLB, NHL, tennis and MMA. The same match is matched across both books automatically, so you can compare prices, see which book is best, and get no-vig fair odds and line movement without any extra work. No API key and no account needed.
Quick start (3 steps)
- Open the Actor on Apify and click Try for free.
- Pick your sports and books (the defaults - NFL/college football and basketball on both books - already work). Press Start.
- Download the odds as JSON, CSV or Excel, connect them to Google Sheets, or call the Actor as a live API (see below).
Where and how can you use it?
| Use case | Who it is for | How to do it |
|---|---|---|
| Line shopping | Bettors | Filter rows where isBestPriceAcrossBooks is true to always see the best price. |
| Fair-value and +EV models | Sharp bettors, quants | Use noVigFairPrice from Pinnacle as the benchmark and compare it to Bovada's price. |
| Closing-line value (CLV) tracking | Serious bettors | Schedule a run before kickoff and compare with the price you took. |
| Line-movement alerts | Tipsters, Discord/Telegram bots | Schedule runs every 5-15 minutes and read moveDirection, priceChange, firstSeenPrice. |
| Arbitrage research | Arb hunters | Join both books on fixtureId and check the implied probabilities. |
| Odds widgets and betting content | Publishers, app builders | Call the live API and render the best prices per match. |
| Datasets and backtesting | Analysts, students | Schedule daily runs and build your own odds history. |
| AI agents and chatbots | Developers using LLMs | Let an assistant answer "who has the best price on tonight's game?" with fresh data. |
Works with: Google Sheets, Excel, Make, Zapier, n8n, Airtable, Slack, Discord, Telegram, webhooks, Python, JavaScript, cURL and any AI agent that can call an HTTP API.
What data do you get?


Each row has:
| Field | Meaning |
|---|---|
book, sport, league | Bookmaker, sport and competition |
homeTeam, awayTeam, commenceTime, isLive | The match |
fixtureId, booksOnFixture | The same match across books - join on fixtureId |
marketType, marketLine, outcomeKey, outcomeLabel | h2h / spreads / totals, the line, and the outcome (home, away, draw, over, under) |
price, priceAmerican | Decimal and American odds |
impliedProbability, overround | Raw probability and the book's margin on that market |
noVigProb, noVigFairPrice | Margin-free probability and fair odds |
isBestPriceAcrossBooks | True for the highest price when at least two books quote the same outcome and line |
previousPrice, priceChange, priceChangePct, moveDirection, firstSeenPrice, moveSinceFirstSeen | Line movement versus your last run (from the second run onward) |
scrapedAt | When the row was captured |
Example result
{"book": "pinnacle","sport": "basketball","league": "Philippines - NCAA","homeTeam": "Arellano Chiefs","awayTeam": "UPHSD Altas","commenceTime": "2026-09-25T07:00:00Z","isLive": false,"marketType": "spreads","marketLine": -2.5,"outcomeKey": "home","outcomeLabel": "Arellano Chiefs -2.5","price": 1.833,"priceAmerican": -120,"impliedProbability": 0.545554,"overround": 0.091107,"noVigProb": 0.5,"noVigFairPrice": 2,"isBestPriceAcrossBooks": false,"fixtureId": "basketball-pinnacle-1636906808"}
Input parameters

| Parameter | Type | Default | What it does |
|---|---|---|---|
sports | array | ["american_football","basketball"] | soccer, basketball, american_football, baseball, hockey, tennis, mma |
books | array | ["pinnacle","bovada"] | Which bookmakers to include (Bovada has no MMA) |
marketTypes | array | ["h2h","spreads","totals"] | Moneyline, handicap, over/under |
mode | string | pre_match_only | pre_match_only, live_only or pre_match_and_live |
leagueFilter | array | - | Keep leagues whose name contains a word, e.g. NFL, NCAA, Premier League |
maxEventsPerSport | integer | 5 | Matches per sport. Matches on both books come first, then the soonest. 0 = all |
includeFairOdds | boolean | true | Adds implied probability, margin and no-vig fair odds |
includeBestPriceFlag | boolean | true | Flags the best price across books |
includeLineMovement | boolean | true | Compares with the previous run |
Use it as a live API (Actor Standby)
Need an answer right now instead of starting a run? This Actor also works as an always-on HTTP endpoint (Apify Actor Standby). Send a request, get JSON back in seconds.
curl -H "Authorization: Bearer $APIFY_TOKEN" \"https://mrdoe--multi-book-sports-odds-feed.apify.actor/?sports=basketball,american_football&books=pinnacle,bovada&maxEventsPerSport=5"
import requestsr = requests.get("https://mrdoe--multi-book-sports-odds-feed.apify.actor/",params={"sports": "soccer", "leagueFilter": "Premier League", "maxEventsPerSport": 5},headers={"Authorization": "Bearer YOUR_APIFY_TOKEN"},timeout=90,)print(r.json()["items"])
const res = await fetch("https://mrdoe--multi-book-sports-odds-feed.apify.actor/?sports=tennis&mode=pre_match_and_live", {headers: { Authorization: `Bearer ${process.env.APIFY_TOKEN}` },});const { count, items } = await res.json();
You can also POST a JSON body with the same fields as the Actor input. The response is { "count": 12, "items": [ ... ] }. Line movement needs stored history, so movement fields are added on normal (scheduled) runs, not on live API calls.
| Standby API | Normal run | |
|---|---|---|
| Best for | Apps, bots, chat assistants, quick checks | Scheduled polling, exports, history |
| Output | JSON in the response | Dataset (JSON, CSV, Excel) |
| Line movement | Not included | Included from the second run |
Schedule it
Save your settings as a Task, then add a Schedule in Apify Console: every 5-15 minutes for line movement, hourly for dashboards, daily for a history dataset. Add a webhook to send fresh rows to Discord, Slack, Sheets or your own system.
Tips for best results
- Use both books and keep
includeBestPriceFlagon - matches covered by both books are returned first. - Use
leagueFilterto focus, for example["NFL"],["NCAA"]or["Premier League"]. - For soccer, set
maxEventsPerSportto control how many matches you pull. - For line movement, run on a schedule with the same settings each time.
Known limitations
- Pre-match and live moneyline, spread and total markets only; player props and specials are not included.
- Only two books (Pinnacle and Bovada) for now. Bovada does not list MMA.
- Books can pause or change prices at any moment; each row is a snapshot at
scrapedAt. - Team names are matched across books automatically; very unusual name differences may not match, in which case each book's rows simply appear separately.
Frequently Asked Questions
Do I need an API key or a bookmaker account?
No. There is nothing to sign up for or configure beyond the input.
Which sports and markets are covered?
Soccer, NFL and college football, NBA and other basketball, MLB, NHL, tennis and MMA - moneyline (1X2 in soccer), spreads and totals.
What are no-vig fair odds?
The bookmaker's margin removed from the market so the probabilities add up to 100%. Pinnacle's no-vig price is widely used as a fair-value benchmark.
How do I find the best price?
Filter rows where isBestPriceAcrossBooks is true. It is set only when at least two books quote the same outcome and line.
Can I use it as an API?
Yes - see Use it as a live API above. It works with Python, JavaScript, cURL, Make, Zapier, n8n and AI agents.
Can I run it on a schedule?
Yes. Create a Task with your input and add a schedule in Apify Console.
Am I charged for failed runs or empty results?
You are charged only for rows actually returned.
Support
Questions or a missing field? Open an issue from the Issues tab on this Actor's page.
Legal / Responsible Use
Odds data is provided for personal analysis and research. Check the rules for sports betting and data use in your jurisdiction, and do not redistribute the data commercially without the right licences. Gamble responsibly.