# Football Odds Scraper: 160+ Bookmakers, Fair Odds, Arbitrage (`zayne21/football-odds-comparison`) Actor

Pre-match football (soccer) odds from 160+ bookmakers in 40+ countries: 1X2, over/under, BTTS, handicaps and more, with best price, opening odds, margin-free fair odds, value bets and arbitrage. No browser, fast and cheap.

- **URL**: https://apify.com/zayne21/football-odds-comparison.md
- **Developed by:** [Elie Rusak](https://apify.com/zayne21) (community)
- **Categories:** Sports
- **Stats:** 5 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 match with 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

## Football Odds Scraper: 160+ Bookmakers, Fair Odds, Arbitrage

Get **pre-match football (soccer) odds from 160+ bookmakers in 40+ countries** for every match of the day, in one run: 1X2, over/under, both teams to score, double chance, draw no bet, Asian and European handicaps, correct score, half time/full time and odd/even — for full time, first half and second half.

Each match comes with the **best available price**, each bookmaker's **opening odds**, **bookmaker margins**, **margin-free fair odds** (market consensus), **value bets** and **arbitrage (surebet) opportunities**.

The Actor reads the data feeds behind FlashScore's odds comparison directly — **no browser**, so a run of 100 matches takes seconds and costs very little.

### What can you do with it?

- **Odds comparison**: find the best price for each outcome across all bookmakers of your country.
- **Value betting research**: compare each price with the consensus fair odds of the whole market.
- **Arbitrage scanning**: spot markets where the best prices of different bookmakers add up to less than 100 %.
- **Line movement**: opening vs current odds per bookmaker.
- **Backtests and models**: collect closing odds and final scores of finished matches (up to 7 days back), or schedule the Actor to build your own odds history.
- **Apps and dashboards**: feed odds into Google Sheets, Excel, a database or your website through the Apify API.

### Bookmaker countries

Bookmakers are shown per country, as licensed there. Select one or several countries; their bookmakers are merged into one comparison per match.

| Country | Bookmakers (examples) |
|---|---|
| United Kingdom | bet365, William Hill, Paddy Power, Betfair, Sky Bet, Ladbrokes, Coral, Betfred, BetVictor, Betway, Unibet, BetMGM, Midnite... (20) |
| Ireland | bet365, Paddy Power, Novibet, Betway, Midnite, 1xBet... |
| France | Betclic, Winamax, Unibet, PMU, Betsson, bet365, bwin, NetBet |
| Germany | bwin, Oddset, Winamax, Interwetten, Betano, Neobet, bet365 |
| Italy | Sisal, SNAI, GoldBet, Eurobet, Lottomatica, bet365, Planetwin365, bwin... (13) |
| Spain | bet365, Codere, Sportium, Luckia, William Hill, Betway, Retabet... |
| Also | Portugal, Netherlands, Austria, Switzerland, Poland, Czechia, Slovakia, Romania, Bulgaria, Serbia, Greece, Cyprus, Malta, Sweden, Denmark, Norway, Finland, Estonia, Latvia, USA (NJ), Canada (ON), Mexico, Colombia, Peru, Ecuador, Venezuela, Australia, South Africa, Nigeria, Ghana, Tanzania, South Korea, Thailand, Philippines, Malaysia, Morocco, International (1xBet, bet365, Unibet, Betfair, bwin, William Hill) |

### Input

| Field | Description |
|---|---|
| Bookmaker countries | One or more countries (default: United Kingdom). |
| Days ahead / Past days | Today up to 7 days ahead; up to 7 days back for finished matches. |
| Leagues | Empty = all leagues. A FlashScore URL (`https://www.flashscore.com/football/england/premier-league/`), a competition name (`ENGLAND: Premier League`, `EUROPE: Champions League`) or a country (`England`). |
| Markets / Periods | Choose among 10 markets and full time / first half / second half. |
| Match statuses | Upcoming (default), live, finished. |
| Maximum matches | Cost cap: soonest kickoffs first. |
| Output format | One item per match, or one row per outcome (best for spreadsheets). |
| Value bet threshold / maximum odds | Flag outcomes whose best price beats the fair odds by at least X %, up to a maximum price. |
| Only value bets and arbitrage | Save only matches (or rows) with an opportunity — you are not charged for the others. |

Example — Premier League and LaLiga, UK and Irish bookmakers, next 3 days:

```json
{
  "countries": ["GB", "IE"],
  "daysAhead": 3,
  "leagues": ["ENGLAND: Premier League", "SPAIN: LaLiga"],
  "markets": ["1x2", "over_under", "btts", "asian_handicap"]
}
```

### Output

One item per match (real run, UK + French bookmakers, shortened):

```json
{
  "matchId": "rH0l2Mhl",
  "url": "https://www.flashscore.com/match/football/kazakhstan-llUzzQCL/faroe-islands-KWK6U3zq/?mid=rH0l2Mhl",
  "kickoff": "2026-10-06T14:00:00Z",
  "status": "scheduled",
  "tournament": "EUROPE: UEFA Nations League - League C",
  "homeTeam": "Kazakhstan",
  "awayTeam": "Faroe Islands",
  "bookmakerCount": 26,
  "bestHome": 2.4, "bestBookmakerHome": "7BetUK", "fairHome": 2.495,
  "bestDraw": 3.1, "bestBookmakerDraw": "Coral", "fairDraw": 3.28,
  "bestAway": 3.3, "bestBookmakerAway": "bet365", "fairAway": 3.398,
  "margin1x2Percent": 9.68,
  "valueBets": [
    {"market": "over_under", "period": "full_time", "line": 3.5, "outcome": "over",
     "bestOdds": 5.25, "bestBookmaker": "Parimatch.uk", "fairOdds": 4.874, "valuePercent": 7.72}
  ],
  "arbitrages": [],
  "markets": [
    {
      "market": "1x2", "period": "full_time", "line": null,
      "outcomes": [
        {"outcome": "home", "bestOdds": 2.4, "bestBookmaker": "7BetUK", "fairOdds": 2.495,
         "fairProbability": 0.4009, "valuePercent": -3.79, "outlier": false,
         "odds": {"10bet": 2.34, "7BetUK": 2.4, "bet365": 2.35, "Betfair": 2.3},
         "openingOdds": {"10bet": 2.35, "7BetUK": 2.38, "bet365": 2.45, "Betfair": 2.3}}
      ],
      "fairOddsBookmakerCount": 26,
      "averageMarginPercent": 9.68,
      "lowestMarginBookmaker": "bet365",
      "bookmakerMarginsPercent": {"bet365": 5.11, "Midnite": 6.53, "Betway": 6.6},
      "arbitrage": null
    }
  ],
  "scrapedAt": "2026-10-05T19:39:10Z"
}
```

Handicap lines are given from the home team's side (`line: -0.5` = home -0.5 / away +0.5). Over/under lines are the goal line.

In **one row per outcome** format, each row holds one match × market × line × outcome with the best price, fair odds, value, arbitrage and every bookmaker's odds as columns — ready for Excel or Google Sheets.

### How fair odds, value and arbitrage are computed

1. For each bookmaker that prices every outcome of a market line, its margin is removed (proportional method by default, or the power method).
2. The fair probability of each outcome is the **median over bookmakers**, normalised to 100 %. Fair odds = 1 / fair probability. Double chance uses the 1X2 consensus.
3. **Value %** = best price × fair probability − 1. It is computed when at least 3 bookmakers price the full line.
4. **Arbitrage** is reported when the best prices of all outcomes add up to less than 100 %, with the stake share for each outcome.
5. A best price more than 25 % above fair odds is marked `outlier` (usually a stale price or a palpable error) and is never flagged as a value bet or arbitrage.
6. Upcoming matches whose kickoff passed more than 15 minutes ago without live coverage are skipped (their odds are stale).
7. Value bets and arbitrage are flagged for upcoming matches only. For live and finished matches you get each bookmaker's last price (closing odds), taken at slightly different moments.

European handicap lines are labelled differently by some bookmakers, so they get margins but no fair odds, value or arbitrage.

### Pricing

You pay per match saved (all selected countries and markets included). Matches without odds, and matches filtered out by *Only value bets and arbitrage*, are free. Set *Maximum matches* to cap the cost of a run.

### Tips

- Odds move quickly: schedule the Actor (for example every hour) and use the API or webhooks to process fresh data.
- First-half, second-half and exotic markets are only offered by some bookmakers.
- Live odds are included only if you select the *Live* status and may lag behind bookmakers' sites.

### FAQ

**Is it legal to scrape this data?** The Actor collects publicly visible prices and match information, with no personal data. Check the terms of the source website and your local laws for your use case.

**Is this betting advice?** No. Value and arbitrage flags are price comparisons against the market consensus. Bookmakers can change prices, void obvious errors and limit accounts. Gamble responsibly — 18+ only. UK: GamCare 0808 8020 133.

**Is this Actor affiliated with FlashScore or the bookmakers?** No.

**Something is missing or broken?** Open an issue in the Issues tab — fixes are usually quick.

# Actor input Schema

## `countries` (type: `array`):

Bookmakers licensed in these countries are compared (UK: 20 bookmakers, Italy: 13, Canada: 10, France: 8...). Several countries are merged into one comparison per match.

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

Matches from today up to this many days ahead (0 = today only, max 7).

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

Also include matches of the last N days (max 7), e.g. closing odds of finished matches for backtests. Add 'Finished' to the match statuses.

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

Leave empty for all leagues. Accepts a FlashScore league URL (https://www.flashscore.com/football/england/premier-league/), a competition name as FlashScore writes it (ENGLAND: Premier League, EUROPE: Champions League) or a country (England).

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

Betting markets to collect.

## `periods` (type: `array`):

Full time, and optionally first-half and second-half markets.

## `statuses` (type: `array`):

Upcoming matches by default. Finished matches keep their closing odds.

## `maxMatches` (type: `integer`):

Stop after saving this many matches (soonest kickoffs first). Matches without odds are skipped and not counted. You are charged per match saved.

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

One item per match (all markets nested), or one row per match x market x outcome for spreadsheets.

## `valueThresholdPercent` (type: `integer`):

An outcome is flagged as a value bet when best price x fair probability - 1 is at least this percentage.

## `valueMaxOdds` (type: `integer`):

Ignore value bets above these odds: longshot prices differ a lot between bookmakers and are often limited.

## `onlyValueBets` (type: `boolean`):

Save only matches (or rows) with at least one value bet or arbitrage. You are not charged for the others.

## `demarginMethod` (type: `string`):

How each bookmaker's margin is removed before taking the median over bookmakers. Power shrinks longshots more than favourites (favourite-longshot bias).

## `includeOpeningOdds` (type: `boolean`):

Add each bookmaker's opening price, to see how the line moved.

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

Not needed in most cases.

## Actor input object example

```json
{
  "countries": [
    "GB"
  ],
  "daysAhead": 1,
  "daysBack": 0,
  "leagues": [
    "ENGLAND: Premier League",
    "SPAIN: LaLiga",
    "https://www.flashscore.com/football/italy/serie-a/"
  ],
  "markets": [
    "1x2",
    "over_under",
    "btts"
  ],
  "periods": [
    "full_time"
  ],
  "statuses": [
    "scheduled"
  ],
  "maxMatches": 20,
  "outputFormat": "match",
  "valueThresholdPercent": 2,
  "valueMaxOdds": 10,
  "onlyValueBets": false,
  "demarginMethod": "proportional",
  "includeOpeningOdds": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `matches` (type: `string`):

One row per match with the best full-time 1X2 prices and fair odds; all markets are in the full JSON.

## `outcomes` (type: `string`):

Rows of the 'One row per outcome' output format.

## `results` (type: `string`):

No description

# 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 = {
    "countries": [
        "GB"
    ],
    "daysAhead": 1,
    "markets": [
        "1x2",
        "over_under",
        "btts"
    ],
    "maxMatches": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("zayne21/football-odds-comparison").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 = {
    "countries": ["GB"],
    "daysAhead": 1,
    "markets": [
        "1x2",
        "over_under",
        "btts",
    ],
    "maxMatches": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("zayne21/football-odds-comparison").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 '{
  "countries": [
    "GB"
  ],
  "daysAhead": 1,
  "markets": [
    "1x2",
    "over_under",
    "btts"
  ],
  "maxMatches": 20
}' |
apify call zayne21/football-odds-comparison --silent --output-dataset

```

## MCP server setup

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

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/UycTrdDRZ6F1fD2yz/builds/7CeAMRlBZ3iXNqRS5/openapi.json
