# Pinnacle Odds Scraper: Sharp Lines, Fair Odds, Limits (`scrapemint/pinnacle-odds-scraper`) Actor

Pinnacle's lines for every sport and league: moneyline, spread, total and team totals with vig-free fair probability, margin and the max stake Pinnacle accepts. Soccer, NFL, NBA, tennis, esports, MMA and more. Only-changed mode for line alerts. No key, no proxy.

- **URL**: https://apify.com/scrapemint/pinnacle-odds-scraper.md
- **Developed by:** [Ken M](https://apify.com/scrapemint) (community)
- **Categories:** Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 game odds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Pinnacle Odds Scraper: Sharp Lines, Fair Odds, Limits

Pinnacle's odds for every sport and league it prices, as one clean row per game: moneyline, spread, total and team totals, each outcome with American and decimal odds, implied probability and the **vig-free fair probability**, plus each market's **margin** and the **maximum stake** Pinnacle will accept.

No key, no account, no proxy.

### Why Pinnacle

Pinnacle is the sharp book. It runs on low margins and takes big bets, so its prices move on informed money, and its line with the margin removed is the closest thing betting has to a market consensus. Bettors use it to check whether a soft book's price is value, modelers use it as ground truth, and line movement at Pinnacle is a signal in itself.

### What you get

- **Every sport Pinnacle has open:** soccer (hundreds of leagues), NFL, NCAA, NBA, MLB, NHL, tennis, esports, MMA, boxing, golf, cricket, darts and more
- **Headline fields** for spreadsheets: `homeWinFair`, `awayWinFair`, `drawFair`, `spreadHome`, `totalPoints`
- **Full markets:** each with `marginPct`, `maxStake`, and outcomes carrying `american`, `decimal`, `line`, `impliedProbability`, `fairProbability` and `fairDecimal`
- **Line-movement mode:** with `onlyChanged` on, each run returns only games that are new or whose prices or lines moved since the last run. Unchanged games are skipped and not charged, so a schedule every few minutes is a cheap line alert.

### Example input

NFL and NBA main lines:

```json
{
  "sports": ["Football", "Basketball"],
  "leagues": ["NFL", "NBA"]
}
```

Line moves in top soccer leagues, every 10 minutes on a schedule:

```json
{
  "sports": ["Soccer"],
  "leagues": ["Premier League", "La Liga", "Bundesliga", "Serie A", "Champions League"],
  "includeTeamTotals": true,
  "onlyChanged": true
}
```

### Example output

```json
{
  "sport": "Soccer",
  "league": "Canada - Premier League",
  "gameId": "1637437064",
  "event": "Pacific @ Supra du Quebec",
  "homeTeam": "Supra du Quebec",
  "awayTeam": "Pacific",
  "startTime": "2026-10-04T20:00:00.000Z",
  "isLive": false,
  "homeWinFair": 0.5769,
  "awayWinFair": 0.2023,
  "drawFair": 0.2208,
  "spreadHome": -1,
  "totalPoints": 3.25,
  "markets": [
    {
      "market": "moneyline",
      "period": "game",
      "maxStake": 100,
      "marginPct": 9.14,
      "outcomes": [
        { "outcome": "Supra du Quebec", "side": "home", "american": -170, "decimal": 1.5882, "impliedProbability": 0.6296, "fairProbability": 0.5769, "fairDecimal": 1.733 },
        { "outcome": "Pacific", "side": "away", "american": 353, "decimal": 4.53, "impliedProbability": 0.2208, "fairProbability": 0.2023, "fairDecimal": 4.943 },
        { "outcome": "Draw", "side": "draw", "american": 315, "decimal": 4.15, "impliedProbability": 0.241, "fairProbability": 0.2208, "fairDecimal": 4.529 }
      ]
    }
  ]
}
```

### Pricing

**$0.004 per game**, with every market you asked for in that one row. No start fee. With `onlyChanged`, unchanged games are not charged, and a run where nothing moved costs nothing.

### Notes

- `fairProbability` removes the margin proportionally (each implied probability divided by their sum). It is the standard quick de-vig; other methods (power, Shin) differ slightly at long odds.
- `maxStake` is Pinnacle's own limit for that market. Higher limits mean Pinnacle trusts its price more; limits rise as kick-off approaches.
- Only real games are returned. Pinnacle's "special" markets (player props, futures) are left out because the public feed does not name their outcomes.
- League filters match on the name, so `Premier League` also matches other countries' Premier Leagues; use `England - Premier League` for one.
- For Pinnacle side by side with Bovada and DraftKings, see [Sports Odds Scraper](https://apify.com/scrapemint/sports-odds-scraper).

# Actor input Schema

## `sports` (type: `array`):

Pinnacle sport names, e.g. Soccer, Basketball, Football, Baseball, Hockey, Tennis, E Sports, Mixed Martial Arts, Boxing, Golf, Cricket. Empty for every sport with open games.

## `leagues` (type: `array`):

Keep leagues whose name contains one of these, e.g. NFL, NBA, Premier League, Champions League, ATP. Empty for every league in the sports above.

## `markets` (type: `array`):

Any of moneyline, spread, total.

## `includeTeamTotals` (type: `boolean`):

Also each team's own points/goals over-under.

## `includePeriods` (type: `boolean`):

Also first-half and other period markets, where Pinnacle prices them.

## `includeAlternateLines` (type: `boolean`):

Also alternate spreads and totals. Off returns the main line only.

## `hoursAhead` (type: `integer`):

Only games starting in the next N hours. 0 for all upcoming.

## `includeLive` (type: `boolean`):

Games already in play.

## `liveOnly` (type: `boolean`):

Only games in play.

## `onlyChanged` (type: `boolean`):

On: return only games that are new or whose prices or lines changed since the last run with the same settings. For line-movement alerts on a schedule; unchanged games are not charged.

## `maxGames` (type: `integer`):

Stop after this many games.

## Actor input object example

```json
{
  "sports": [
    "Football",
    "Basketball"
  ],
  "leagues": [
    "NFL",
    "NBA"
  ],
  "markets": [
    "moneyline",
    "spread",
    "total"
  ],
  "includeTeamTotals": false,
  "includePeriods": false,
  "includeAlternateLines": false,
  "hoursAhead": 0,
  "includeLive": true,
  "liveOnly": false,
  "onlyChanged": false,
  "maxGames": 100
}
```

# Actor output Schema

## `games` (type: `string`):

Sport, league, teams, start time, live flag, headline fair probabilities and lines, and markets with prices, fair odds, margin and max stake.

## `summary` (type: `string`):

Leagues read, games returned, unchanged games skipped, failed leagues.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "sports": [
        "Football",
        "Basketball"
    ],
    "leagues": [
        "NFL",
        "NBA"
    ],
    "maxGames": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapemint/pinnacle-odds-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "sports": [
        "Football",
        "Basketball",
    ],
    "leagues": [
        "NFL",
        "NBA",
    ],
    "maxGames": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapemint/pinnacle-odds-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "sports": [
    "Football",
    "Basketball"
  ],
  "leagues": [
    "NFL",
    "NBA"
  ],
  "maxGames": 100
}' |
apify call scrapemint/pinnacle-odds-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapemint/pinnacle-odds-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/hVyqyR2w4MFvPX8Kc/builds/sI1fIOyp8PdEEHo3J/openapi.json
