# Sports Betting Results: Closing Odds vs Final Scores (`scrapemint/sports-betting-results`) Actor

Keyless settled results for the NFL, NBA, MLB, NHL, college and soccer: the closing spread, moneyline and total each game was played at, joined to the final score and graded. Who covered, who was upset, over or under, plus team records against the spread and profit on a flat stake. Pay per row.

- **URL**: https://apify.com/scrapemint/sports-betting-results.md
- **Developed by:** [Ken M](https://apify.com/scrapemint) (community)
- **Categories:** News, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 result rows

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Sports Betting Results: Closing Odds vs Final Scores

Every other odds feed stops at kickoff. This one starts there.

It takes the **closing line** a game was actually played at, joins it to the **final score**, and grades the three markets people bet: the moneyline, the spread and the total. No key, no login, no proxy.

Use it to settle a slate, check how your picks did, build a results history for a model, or answer the question every bettor asks on Monday morning: did favourites cover this week, or did the underdogs pay?

### What you get

**Games mode** (default) returns one row per finished game:

| Field | Meaning |
| --- | --- |
| `homeScore`, `awayScore`, `winner`, `margin` | The final result |
| `closingSpreadHome`, `closingSpreadAway` | The spread the game closed at |
| `closingTotal`, `closingMoneylineHome`, `closingMoneylineAway`, `closingMoneylineDraw` | The rest of the closing board |
| `closingSpreadPriceHome`, `closingSpreadPriceAway` | The price attached to each side of the spread |
| `moneylineFavorite`, `spreadFavorite` | Who was favoured in each market, and by which team |
| `moneylineResult` | `favorite_won`, `upset` or `draw` |
| `spreadResult`, `favoriteCovered` | `home_covered`, `away_covered` or `push` |
| `totalResult`, `totalPoints` | `over`, `under` or `push`, with the actual points |
| `favoriteProfit100`, `underdogProfit100`, `favoriteSpreadProfit100` | Profit on a flat 100 stake at the closing price |
| `openingSpreadHome`, `spreadMove` | Where the number opened and how far it travelled |

**Teams mode** returns one row per team over the range: straight up record, record against the spread with a win percentage, over and under record, average closing spread, record as a favourite and as an underdog, and the profit a flat 100 on that team every game would have returned.

**Summary mode** returns one row per league: games graded, how often the favourite won, how often the favourite covered, how often the home side covered, the over percentage, average closing total against the average actual total, and what backing every underdog (or every favourite) would have paid.

### Leagues

`nfl`, `nba`, `mlb`, `nhl`, `ncaaf`, `ncaab`, `wnba`, `epl`, `laliga`, `seriea`, `bundesliga`, `ligue1`, `mls`, `ucl`, `uel`. A raw path such as `football/nfl` also works, so any league the source covers is reachable.

Past seasons work: set `dateFrom` and `dateTo` to any range and the closing prices come back with it.

### Example input

```json
{
  "mode": "games",
  "leagues": ["mlb"],
  "daysBack": 3
}
```

A season month for one league:

```json
{
  "mode": "summary",
  "leagues": ["nfl"],
  "dateFrom": "2025-11-01",
  "dateTo": "2025-11-30"
}
```

### Two things worth knowing

**The moneyline favourite and the spread favourite are not always the same team.** Baseball and hockey run the spread at a fixed 1.5 goals or runs, so the side laying that number is regularly the moneyline underdog. In a sample of MLB games this happened in roughly one game in five. Each market is therefore graded against its own favourite, and both are reported, so `moneylineResult` and `favoriteCovered` never contradict each other.

**Draws lose both sides of a moneyline.** In soccer the draw is priced as its own outcome, so a 2-2 result is reported as `moneylineResult: "draw"` and both the favourite and the underdog stake are marked lost. The draw price is returned as `closingMoneylineDraw` so you can grade it yourself.

### Pricing

Pay per result row, `$0.004`. The first 2 rows of every run are free.

Games that have not been played, games with no published line, and every note row are never charged. A run that finds nothing returns a free row explaining why.

Each finished game costs one lookup, so `maxGames` is the lever that controls both speed and spend. Grading a full 15 game baseball slate takes a few seconds.

### Related actors

- **Sports Odds Scraper** for the lines on games that have not been played yet
- **Sports Odds Movement and Arbitrage Tracker** for how a line is moving right now
- **Sports Futures Odds** for championship, division and award markets
- **Sports Scores, Fixtures & Standings Scraper** for results without the betting layer

# Actor input Schema

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

games = one row per finished game with its closing line and how each market settled. teams = one row per team with straight up and against the spread records. summary = one row per league showing how often favourites won, covered and went over.

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

nfl, nba, mlb, nhl, ncaaf, ncaab, wnba, epl, laliga, seriea, bundesliga, ligue1, mls, ucl, uel. A raw ESPN path such as football/nfl also works.

## `daysBack` (type: `integer`):

How many days of finished games to grade, counting back from today. Ignored when a start date is given.

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

YYYY-MM-DD. Grade a fixed range instead of the last few days, e.g. a whole season month. Past seasons work too.

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

YYYY-MM-DD. Defaults to the start date, so leaving it empty grades a single day.

## `teamFilter` (type: `array`):

Keep only games involving these teams, by abbreviation or name, e.g. NYY, Lakers. Empty returns every game.

## `onlyUpsets` (type: `boolean`):

Keep only games the underdog won outright at the closing moneyline.

## `minClosingSpread` (type: `integer`):

Keep only games where the closing spread was at least this many points, e.g. 7 for clear mismatches. 0 = no limit.

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

Cap on how many finished games are looked up, newest first. Each game is one request, so this is the main speed and cost lever.

## `maxRows` (type: `integer`):

Cap on rows returned after grading and filtering. Controls total cost.

## Actor input object example

```json
{
  "mode": "games",
  "leagues": [
    "mlb"
  ],
  "daysBack": 3,
  "dateFrom": "",
  "dateTo": "",
  "teamFilter": [],
  "onlyUpsets": false,
  "minClosingSpread": 0,
  "maxGames": 200,
  "maxRows": 500
}
```

# 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": [
        "mlb"
    ],
    "daysBack": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapemint/sports-betting-results").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": ["mlb"],
    "daysBack": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapemint/sports-betting-results").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": [
    "mlb"
  ],
  "daysBack": 3
}' |
apify call scrapemint/sports-betting-results --silent --output-dataset

```

## MCP server setup

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

```

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/DdWBuv5Bc9RfzP2O1/builds/DuqP44BFk3mgeNwYr/openapi.json
