# Pinnacle Odds API — Sharp Lines, Limits & Fair Odds (`lergassy/pinnacle-odds-api`) Actor

Pinnacle's moneyline, spread and total for every game, with the maximum stake it will accept on each market and the fair probability with the bookmaker's margin removed. Pinnacle is the sharp reference the rest of the market prices against — no API key, no login.

- **URL**: https://apify.com/lergassy/pinnacle-odds-api.md
- **Developed by:** [Matvey](https://apify.com/lergassy) (community)
- **Categories:** Sports, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 69 total users, 30 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.40 / 1,000 odds rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 API** returns Pinnacle's moneyline, spread and total for every game it prices, with two numbers almost no other feed carries: the **maximum stake Pinnacle will accept** on that market, and the **fair probability** with the bookmaker's margin removed. No API key, no account, no browser.

![One run of Pinnacle Odds API: moneyline and spread prices with fair probabilities and the stake limit.](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/pinnacle-odds-api/pinnacle-odds-api-output-table.png)

Pinnacle is the sharp reference book. It runs on low margins and high limits and it does not restrict winning customers, so the rest of the market prices against it. Its number, stripped of margin, is the closest thing to a true probability that a betting market produces.

### What is Pinnacle Odds API?

A clean feed of Pinnacle's own board: every game in the leagues you pick, every market on it, both sides priced, with the implied and the fair probability side by side. Two modes: **odds** (one row per game, market and side) and **leagues** (what is covered right now).

### What makes it different

**The limit is data.** Pinnacle publishes the maximum it will accept on each market, and that figure says how much the book itself trusts its own number. A line with a low limit is one Pinnacle is unsure about; a full-limit line is one it will happily take money on. Feeds that only copy prices throw that away.

**Fair probability, not implied.** Both sides of a market always add up to more than 1: the surplus is the margin. Every row carries the raw `impliedProbability`, the `overround`, and the `fairProbability` with the margin split out — a share of 1, summing to 1, which is the number a model should actually consume.

**Every price format.** American, decimal, fractional or implied probability — set `oddsFormat` for the price columns; the decimal price is on every row as well.

### What data does it return?

| Field | Example |
|---|---|
| `league`, `game`, `startTime`, `status` | nfl · Baltimore Ravens at Indianapolis Colts · … |
| `market`, `line` | moneyline / spread / total · −3.5 |
| `homePrice`, `awayPrice`, `drawPrice` | −165 · +140 · (soccer only) |
| `overPrice`, `underPrice` | −110 · −110 |
| `homeDecimal`, `awayDecimal`, `overDecimal`, `underDecimal` | 1.606 · 2.40 · … |
| `homeImpliedProbability`, `awayImpliedProbability` | 0.67 · 0.3623 — shares of 1, and they sum to more than 1 |
| `homeFairProbability`, `awayFairProbability` | 0.649 · 0.351 — the same two with the margin removed, summing to 1 |
| `overround` | 0.0323 — the book's margin on this market, here 3.2% |
| `limitUsd` | 20,000 — the largest stake Pinnacle will take here |
| `favorite`, `sourceUrl` | Indianapolis Colts · link to the game |

Alternate lines — the full ladder of spreads and totals, not just the main number — come back when you ask for them.

### How much does it cost?

Pay per row, and only for rows you actually get:

| Event | Price |
| --- | --- |
| Odds row | $0.002 |
| Game (nested output) | $0.006 |
| League row | $0.0005 |

**Error rows are never charged.** No browser, no proxy — one public JSON API — so platform usage on top is negligible.

| Job | Cost |
| --- | --- |
| An NFL Sunday, moneyline, spread and total (≈40 rows) | $0.08 |
| Five leagues, moneyline only, once a day for a month | $6.00 |
| A single game's full ladder of alternate lines | $0.20 |

#### Bulk export: what 50,000 odds rows actually cost

This Actor is built for bulk jobs — put hundreds of inputs into one run, or call it from the API on
a schedule. There is **no fee per run, no fee per page and no proxy charge**: you pay for the rows
you keep, and error rows are free. That is what decides the bill once you pull a whole market
rather than a single league.

| Job | This Actor | Most-used Actor in this category |
|---|---|---|
| 50,000 odds rows across 100 runs | **$100** | $150 |

Checked on the Apify Store on 24 September 2026 against the Actor with the most monthly users in
this category ($0.003 per odds row plus a $0.00005 start fee, counted in). Its row is one side of a
market, ours carries both sides, so per market the gap is wider than the table shows. Some Actors
here ask less per row — this table compares against the one buyers actually use most.

### How to use it

1. Name your **🏆 Leagues** — `nfl`, `nba`, `mlb`, `nhl`, `epl`, `ncaaf` and the rest.
2. Pick the **📈 Markets**: moneyline, spread, total.
3. Set **📅 Days ahead**, or an explicit date range.
4. Choose **🔢 Odds format** — American, decimal, fractional or implied probability.
5. Click **Start**, then export as JSON, CSV or Excel, or read the dataset through the API.

![The input form of Pinnacle Odds API: leagues, markets, days ahead and odds format.](https://raw.githubusercontent.com/lergassy/apify-actor-assets/main/pinnacle-odds-api/pinnacle-odds-api-input-form.png)

### ⬇️ Input

```json
{
  "mode": "odds",
  "leagues": ["nfl", "nba"],
  "markets": ["moneyline", "spread", "total"],
  "daysAhead": 7,
  "oddsFormat": "american"
}
```

#### One game with every alternate line

```json
{ "mode": "odds", "leagues": ["nfl"], "includeAlternateLines": true, "maxItems": 500 }
```

#### One row per game instead of one per side

```json
{ "mode": "odds", "leagues": ["epl"], "outputFormat": "nested" }
```

### ⬆️ Output

```json
{
  "type": "odds",
  "league": "nfl",
  "game": "Baltimore Ravens at Indianapolis Colts",
  "startTime": "2026-09-13T17:00Z",
  "market": "moneyline",
  "homeTeam": "Indianapolis Colts",
  "awayTeam": "Baltimore Ravens",
  "homePrice": -203,
  "awayPrice": 176,
  "homeDecimal": 1.493,
  "awayDecimal": 2.76,
  "homeImpliedProbability": 0.67,
  "awayImpliedProbability": 0.3623,
  "homeFairProbability": 0.649,
  "awayFairProbability": 0.351,
  "overround": 0.0323,
  "limitUsd": 20000,
  "favorite": "Indianapolis Colts",
  "sourceUrl": "https://www.pinnacle.com/en/football/nfl/matchups",
  "scrapedAt": "2026-09-09T13:30:00.000Z"
}
```

A request that fails arrives as a `type: "error"` row with the reason, never as a silently short list.

### Use cases

#### A reference price for your model

Fair probabilities from the sharpest book are the benchmark every other price is judged against.

#### Closing line value

Schedule the run and store the line at intervals; the closing number is the standard measure of whether a bet was good.

#### Comparing your book against the market

Put Pinnacle's fair probability next to whatever price you were offered elsewhere and see who is paying more than the risk deserves.

#### Limits as a signal

Track `limitUsd` through the week: limits rising into kick-off means the book has settled on its number.

#### AI agents

An agent asked "what are the real odds on this game" reads `homeFairProbability` straight off the row.

### 🤖 For AI Agents & LLM Apps

Compact reference for agents calling this Actor through the [Apify MCP server](https://mcp.apify.com) or the Apify API (`lergassy/pinnacle-odds-api`).

**Minimal input:**

```json
{ "leagues": ["nfl"], "markets": ["moneyline"], "daysAhead": 3 }
```

**Behaviors an agent should know:**

- **Quote `fairProbability`, not `impliedProbability`.** Both are shares of 1. The implied numbers include the book's margin and sum to more than 1; the fair ones sum to exactly 1. Multiply by 100 before showing a percentage.
- `limitUsd` is how much Pinnacle will accept on that market — a confidence signal, not a price.
- `line` belongs to spreads and totals; a moneyline row has none.
- `drawPrice` exists only where a draw is possible, which in practice means soccer.
- Prices move constantly. Every row carries `scrapedAt`; treat a row as a snapshot, not a standing quote.
- Set `oddsFormat` rather than converting prices yourself.
- The Pinnacle guest API is public: no key, no account, no proxy.

### Pinnacle API without a key

Pinnacle's own guest endpoints serve matchups and prices as JSON, split across two documents that have to be joined by matchup id — and the market list carries the limits that most feeds discard. This Actor does the join, keeps the limits, and returns one stable row shape per league.

### ❓ FAQ

#### Is this betting advice?

No. It reads public odds data and returns it as a table. It places no bets.

#### Why Pinnacle rather than a retail sportsbook?

Because its margin is small and it does not close winning accounts, so its price reflects what the market actually believes rather than what a book can get away with.

#### What is the overround?

The amount by which the two sides of a market exceed 1. It is the book's margin — 0.0323 means 3.2% — and removing it gives the fair probability.

#### Which leagues are covered?

The major US leagues and the main soccer competitions. Run the leagues mode to see the current list.

#### How fresh are the numbers?

Live at the moment of the run. Schedule the Actor if you want a line-movement history.

#### Can I use it with the Apify API or an MCP server?

Yes. It runs from the API and the official clients, and AI agents reach it through the Apify MCP server without extra setup.

### Your feedback

Missing a league or a market? Open an issue on the **Issues** tab — every one gets answered.

### You might also like

| Actor | What it does |
|---|---|
| [Sports Betting Odds API](https://apify.com/lergassy/sports-odds-api) | Several books at once, with arbitrage and value bets |
| [DFS Player Props API](https://apify.com/lergassy/dfs-props-scraper) | PrizePicks and Underdog lines side by side |
| [Sports Injury Report API](https://apify.com/lergassy/sports-injuries-api) | Who is out, questionable or probable |
| Sports Scores & Schedules API | Live scores and schedules for 33 leagues |

### Also known as

People look for this Actor as a Pinnacle API, Pinnacle odds scraper, sharp odds data, closing line value data, fair odds, no-vig odds and betting limits data.

### Use via API

Run this Actor from your own code or pipeline. Get your token in Apify Console → Settings → API & Integrations. Every input field below has the same name as in the JSON tab of the input form.

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("lergassy/pinnacle-odds-api").call(run_input={
    "mode": "odds",
    "leagues": [
        "nfl",
        "nba",
        "epl"
    ],
    "daysAhead": 7
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

**JavaScript**

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

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('lergassy/pinnacle-odds-api').call({
    "mode": "odds",
    "leagues": [
        "nfl",
        "nba",
        "epl"
    ],
    "daysAhead": 7
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**cURL** (runs the Actor and returns the results in one call)

```bash
curl -X POST "https://api.apify.com/v2/acts/lergassy~pinnacle-odds-api/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"mode": "odds", "leagues": ["nfl", "nba", "epl"], "daysAhead": 7}'
```

# Changelog

This Actor's version history is a separate document: https://apify.com/lergassy/pinnacle-odds-api/changelog.md

# Actor input Schema

## `mode` (type: `string`):

<b>Odds</b> — moneyline, spread and total for every game, per book, with opening lines and movement. <b>Props</b> — player and game props from DraftKings for every game. <b>Futures</b> — championship, division, award and season-win markets. <b>Prediction markets</b> — Kalshi game contracts with traded probabilities. <b>Leagues</b> — every league DraftKings currently prices, with ids.

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

One or more leagues. Odds, props and Kalshi contracts are matched game by game. You can also type any ESPN league path such as <code>soccer/eng.2</code> for the game list (DraftKings and Kalshi prices then depend on whether they carry that league).

## `daysAhead` (type: `integer`):

Games from today up to this many days ahead (ignored when dates are set below). 0 = today only.

## `dateFrom` (type: `string`):

<code>YYYY-MM-DD</code>, UTC. Optional.

## `dateTo` (type: `string`):

<code>YYYY-MM-DD</code>, UTC. Optional; at most 60 days after the start.

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

Odds mode: which game lines to output. Spread is the run line in MLB and the puck line in NHL; soccer moneylines carry a draw price.

## `oddsFormat` (type: `string`):

How the <code>homePrice</code>/<code>awayPrice</code>/<code>overPrice</code>… fields are written. Decimal odds and implied probabilities are always included as separate fields.

## `outputFormat` (type: `string`):

<b>Flat</b> — one row per game × market × book, spreadsheet-friendly. <b>Nested</b> — one row per game with all books inside and the best price per outcome.

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

Add DraftKings' alternate lines as extra rows (market <code>alternate-spread</code> / <code>alternate-total</code>).

## `includeFinished` (type: `boolean`):

Odds mode: keep games that are already final (closing lines, if a source still carries them). Prediction-markets mode: keep settled contracts.

## `eventIds` (type: `array`):

ESPN event ids (the <code>eventId</code> field of any row, or the number in an ESPN game URL). Leave empty for every game in the date range.

## `maxItems` (type: `integer`):

Stop after this many rows in the run.

## `concurrency` (type: `integer`):

How many requests run at once.

## `proxyConfiguration` (type: `object`):

Not needed: every source answers Apify's own servers directly. Set only if a source starts refusing. <b>Leave it off unless a source starts refusing you:</b> a datacenter proxy is blocked by some books, so switching it on can cost you prices rather than save them. If you do need one, pick Residential.

## Actor input object example

```json
{
  "mode": "odds",
  "leagues": [
    "nfl",
    "nba",
    "mlb",
    "epl"
  ],
  "daysAhead": 7,
  "markets": [
    "moneyline",
    "spread",
    "total"
  ],
  "oddsFormat": "american",
  "outputFormat": "flat",
  "includeAlternateLines": false,
  "includeFinished": false,
  "maxItems": 5000,
  "concurrency": 6,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `rows` (type: `string`):

Odds mode: one row per game × market × book with prices in the chosen format, decimal odds, implied and fair probabilities, opening line and movement (or one nested row per game with best prices). Props/futures: one row per selection. Prediction markets: one row per Kalshi contract.

## `runSummary` (type: `string`):

JSON counters for the run: rows delivered, filtered out, errors and request statistics.

# 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 = {
    "leagues": [
        "nfl",
        "nba",
        "mlb",
        "epl"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/pinnacle-odds-api").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 = { "leagues": [
        "nfl",
        "nba",
        "mlb",
        "epl",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lergassy/pinnacle-odds-api").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 '{
  "leagues": [
    "nfl",
    "nba",
    "mlb",
    "epl"
  ]
}' |
apify call lergassy/pinnacle-odds-api --silent --output-dataset

```

## MCP server setup

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

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/FjL0i4DqqRdjF3RkA/builds/nFUFCS8GUOvyAppPG/openapi.json
