# Betano Odds Scraper — Live + All Markets, 14 Countries (`blackfalcondata/betano-scraper`) Actor

Scrape Betano betting odds from 14 country books at $3 per 1,000 events: pre-match and in-play with score and clock, 600+ markets per game · the same match priced across countries · changed-odds-only monitoring · decimal, fractional and American prices.

- **URL**: https://apify.com/blackfalcondata/betano-scraper.md
- **Developed by:** [Black Falcon Data](https://apify.com/blackfalcondata) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 2 monthly users, 58.3% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 events

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

### What does Betano Odds Scraper do?

Betano Odds Scraper is a Betano odds API for pre-match and live betting markets on betano.com and its 14 country sites, across all 23 sports the books carry. Pick a country book, one or several sports, and the leagues, teams or matches you care about, or take every league of a sport at once. Every event comes back with its markets and prices: match result, over/under, player props and 600+ more per game. Live matches carry the score, the clock and the period. The same match can be priced across several countries in one run, and Sportradar match statistics can ride along. Monitoring runs return only the odds that moved.

**New to Apify?** [Sign up free](https://console.apify.com/sign-up?fpr=1h3gvi) and use the included $5 monthly platform credit to test this actor.

### Key features

- **🌎 14-market coverage:** fourteen Betano country books on one actor: Germany, Brazil, Portugal, Romania, Denmark, Czechia, Bulgaria, Peru, Argentina, Chile, Ecuador, Nigeria, Ghana and Ontario. Pick the book that prices the rows, and optionally attach the same match priced in other books (`compareCountries`) for an in-house odds comparison. Event ids are shared across all books.
- **📌 Change classification:** every price arrives as decimal odds with an implied probability, and optionally as fractional and American odds too. Player and team table markets are flattened so each selection carries the player name and the line it refers to.
- **📦 Compact mode:** core fields only: event, teams, start time, league, book, markets and the change flag.
- **🧹 Empty-field stripping:** drop null, empty-string, and empty-array fields from each record before push. Smaller payloads for AI agents and dashboards that already handle missing fields gracefully.
- **♻️ Incremental mode:** monitoring runs return only events that are new or whose odds moved since the last run with the same settings. Unchanged events are skipped and not billed, so a schedule that refreshes a league every hour costs a fraction of a full pull. Each row carries `changeType`.
- **📤 Export anywhere:** Download the dataset as JSON, CSV, or Excel from the Apify Console, or stream live via the Apify API and integrations (Make, Zapier, Google Sheets, n8n, …).
- **🔌 MCP connectors:** send the run's events straight to a connected app through Apify's MCP connectors without writing glue code.

### What data can you extract from betano.com?

Each result includes Core event fields (`eventId`, `bookmaker`, `country`, `sport`, `sportId`, `leagueId`, `leagueName`, and `regionId`, and more). In standard mode, all fields are always present — unavailable data points are returned as `null`, never omitted. In compact mode, only core fields are returned.

### Input

Configure the actor through the input schema in Apify Console.

Key parameters:

- **`country`** — Which Betano country site prices the rows. Each site is a separate book with its own odds and its own fixture list. (default: `"DE"`)
- **`sports`** — Pick several sports for one run. When set it replaces the single Sport above. The coupon, league resolution, outrights and live matches are then done for each sport in turn. (default: `[]`)
- **`leagues`** — Leave empty for the whole coupon (see Hours ahead). Otherwise list leagues by name ("Premier League", "LaLiga", "Brasileirao Serie A"), by Betano league id ("1", "216") or by pasting the league page URL. Names are matched against the chosen sport's league list on the chosen country site. (default: `[]`)
- **`liveMatches`** — Also return every match of the chosen sport that is in play right now, with the current score, match clock, period and live odds. Headline markets come from the live overview; any other market choice opens each live match for all of its live markets. Comparing a live match across country books is skipped, because a second book's in-play price is already stale by the time it arrives. (default: `false`)
- **`markets`** — "Headline markets" uses the odds shown on the listing (match result, over/under, both teams to score) with no extra page per event. Every other choice opens each event page: "All markets" returns the book’s own combined list, and the specific tabs return one market group each. You can combine them: on a large fixture the individual tabs carry markets the combined list does not, so picking "All markets" plus the tabs you care about returns more than "All markets" alone, at one extra lookup per tab. (default: `["main"]`)
- ...and 37 more parameters

### Input examples

**Headline odds for two leagues** — Match result, over/under and both teams to score for every upcoming match on the German book.

→ One row per event with the listing markets nested under markets\[].

```json
{
  "country": "DE",
  "sport": "football",
  "leagues": [
    "Premier League",
    "Bundesliga"
  ],
  "maxEvents": 50,
  "markets": [
    "main"
  ]
}
```

**Every league of a sport** — The default scope is the next few hours. This covers the whole book: 209 football leagues on the Danish book alone.

→ Matches from across the book, leagues spread evenly so one sport cannot use up the limit.

```json
{
  "country": "DE",
  "sports": [
    "football",
    "basketball"
  ],
  "allLeagues": true,
  "maxEvents": 500
}
```

**Every market for one match** — Paste an event page URL from any Betano site; the site in the URL picks the book.

→ One event row with 600+ markets, each price in decimal, fractional and American odds.

```json
{
  "eventUrls": [
    "https://www.betano.dk/kampodds/crystal-palace-fc-manchester-city/90925073/"
  ],
  "markets": [
    "all"
  ],
  "oddsFormat": "all"
}
```

**Odds and match statistics together** — Betano publishes the Sportradar match id, so the join is on that id, not on team names.

→ Each event row carries its odds plus a `stats` object.

```json
{
  "country": "DK",
  "sport": "football",
  "leagues": [
    "Premier League"
  ],
  "includeStats": true,
  "statsLayers": [
    "lineups",
    "timeline",
    "playerStats"
  ]
}
```

**Find a match by team name** — No URLs or ids needed: Betano's own search matches the name, so "Man City" finds Manchester City.

→ One row per matching upcoming or live match, with its headline markets.

```json
{
  "country": "DE",
  "searchQueries": [
    "Bayern",
    "Dortmund"
  ],
  "markets": [
    "main"
  ]
}
```

**Live matches across four sports** — Everything in play right now on the German book, with score, clock and period.

→ Rows with isLive true, liveScore, liveClock, livePeriod and the live prices.

```json
{
  "country": "DE",
  "sports": [
    "football",
    "tennis",
    "basketball",
    "ice-hockey"
  ],
  "liveMatches": true,
  "maxEvents": 100
}
```

**Odds change monitor** — Schedule it: only new matches and matches whose odds moved come back.

→ Rows with changeType NEW or UPDATED; unchanged matches are skipped and not billed.

```json
{
  "country": "BR",
  "sport": "football",
  "hoursAhead": "24",
  "maxEvents": 200,
  "incrementalMode": true,
  "notifyOnlyChanges": true
}
```

**Selection table from a league page URL** — Any Betano page URL works as a start URL; the site in it picks the book.

→ One flat row per priced selection, ready for CSV or Sheets.

```json
{
  "startUrls": [
    "https://www.betano.pt/sport/futebol/portugal/primeira-liga/17083/"
  ],
  "maxEvents": 30,
  "outputMode": "selection"
}
```

### Output

Each run produces a dataset of structured event records. Results can be downloaded as JSON, CSV, or Excel from the Dataset tab in Apify Console.

### Example event record

```json
{
  "eventId": "91655188",
  "bookmaker": "betano",
  "country": "DK",
  "sport": "esports",
  "sportId": "ESPS",
  "leagueId": "193760",
  "leagueName": "LCK",
  "regionId": "189377",
  "regionName": "League of Legends",
  "name": "Gen.G - KT Rolster",
  "homeTeam": "Gen.G",
  "awayTeam": "KT Rolster",
  "participants": [
    {
      "id": "1952431",
      "name": "Gen.G"
    },
    {
      "id": "1952399",
      "name": "KT Rolster"
    }
  ],
  "startTime": "2026-09-01T08:00:00.000Z",
  "startTimeMs": 1788249600000,
  "isLive": false,
  "willGoLive": true,
  "streamingAvailable": true,
  "hasLineups": false,
  "totalMarketsAvailable": 237,
  "betRadarId": 0,
  "statsUrl": "/api/statistics/statsview?id=91655188",
  "url": "https://www.betano.dk/match-odds/gen-g-kt-rolster/91655188/",
  "outright": false,
  "marketsCount": 119,
  "markets": [
    {
      "marketId": "2933361425",
      "name": "Winner",
      "type": "H2HT",
      "typeId": 3183,
      "handicap": 0,
      "closeTime": "2026-09-01T08:00:00.000Z",
      "selections": [
        {
          "selectionId": "10309723095",
          "name": "Gen.G",
          "price": 1.16,
          "priceFractional": "4/25",
          "priceAmerican": -625,
          "impliedProbability": 0.8621,
          "handicap": 0,
          "teamId": "1952431"
        },
        {
          "selectionId": "10309723096",
          "name": "KT Rolster",
          "price": 4.75,
          "priceFractional": "15/4",
          "priceAmerican": 375,
          "impliedProbability": 0.2105,
          "handicap": 0,
          "teamId": "1952399"
        }
      ]
    },
    {
      "marketId": "2933361444",
      "name": "Map Winner (Map 1)",
      "type": "TMPW",
      "typeId": 3185,
      "handicap": 0,
      "closeTime": "2026-09-01T08:00:00.000Z",
      "selections": [
        {
          "selectionId": "10309723135",
          "name": "Gen.G",
          "price": 1.36,
          "priceFractional": "4/11",
          "priceAmerican": -278,
          "impliedProbability": 0.7353,
          "handicap": 0,
          "teamId": "1952431"
        },
        {
          "selectionId": "10309723134",
          "name": "KT Rolster",
          "price": 3,
          "priceFractional": "2/1",
          "priceAmerican": 200,
          "impliedProbability": 0.3333,
          "handicap": 0,
          "teamId": "1952399"
        }
      ]
    }
  ],
  "priceHash": "0c2830f09a34dc4083227d0aa00781b19465e8979afbd1452220c1452b8abc4e",
  "scrapedAt": "2026-08-31T17:08:59.102Z",
  "fetchedAt": "2026-08-31T17:11:42.038Z"
}
```

### Incremental fields

When incremental mode is on, each record also carries:

- `changeType` — one of `NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED`, `EXPIRED`. Default output covers `NEW` / `UPDATED` / `REAPPEARED`; set `emitUnchanged: true` to opt into the others.

### How to scrape betano.com

1. Go to [Betano Odds Scraper](https://apify.com/blackfalcondata/betano-scraper?fpr=1h3gvi) in Apify Console.
2. Configure the input.
3. Set `maxResults` to control how many results you need.
4. Click **Start** and wait for the run to finish.
5. Export the dataset as JSON, CSV, or Excel.

### Use cases

- Extract event data from betano.com for market research and competitive analysis.
- Track pricing trends across regions and categories over time.
- Monitor new and changed events on scheduled runs without processing the full dataset every time.
- Feed structured data into AI agents, MCP tools, and automated pipelines using compact mode.
- Export clean, structured data to dashboards, spreadsheets, or data warehouses.

### How much does it cost to scrape betano.com?

Betano Odds Scraper uses [pay-per-event](https://docs.apify.com/platform/actors/paid-actors/pay-per-event) pricing. You pay a small fee when the run starts and then for each result that is actually produced.

- **Run start:** $0.001 per run
- **Per event (primary event):** $0.003

You are billed only for the events your run actually triggers. Prices below are the Free plan tier.

| Event | Price (Free tier) | Charged when |
|---|---|---|
| Actor Start | $0.001 (one-time) | Charged once per run (one event per GB of memory, minimum one). Platform usage (compute and data transfer) is billed separately by Apify at your plan rates. |
| Event (primary) | $0.003 | One match or outright event delivered to your dataset with its headline markets (match result, over/under, both teams to score where offered). Charged once per event however many rows it produces, including in the one-row-per-selection output. |
| Full markets | $0.012 | Added once per event whose market tabs were opened (All markets or any specific tab such as player markets, corners, cards, handicaps). On top football matches this returns 600+ markets and several thousand priced selections. |
| Odds comparison | $0.002 | Added once per extra country book attached to an event under oddsByCountry (the same match priced on another Betano site). |
| Match statistics | $0.002 | Added once per event for which at least one statistics layer you asked for arrived. A match with no Sportradar coverage is free, and so is one still days from kick-off: lineups, timeline and player numbers only exist from around kick-off. |
| Statistics layer | $0.001 | Added once per statistics layer that came back for an event (lineups, timeline, player statistics, head to head, form, tables, situations, fun facts). A layer that did not answer is not charged. |

Example costs (primary event only — other events above add cost when they fire):

- 10 results: **$0.031**
- 25 results: **$0.076**
- 100 results: **$0.3**
- 200 results: **$0.6**
- 500 results: **$1.5**

> **Platform usage is billed on top of these prices.** The figures above are Apify event fees only. Compute units and proxy traffic are billed separately by Apify at your actual consumption, and for proxy- or browser-heavy workloads they can exceed the event fees. What you actually pay depends on your own input — how many results you request, whether detail enrichment is on, the run memory you choose, and your proxy settings — so it cannot be stated as a fixed figure here. Every run reports its exact platform usage on the run detail page.
>
> The **Actor Start** event is charged once per GB of run memory (minimum one), so a run configured with 2 GB is charged two start events rather than one.

#### Example: recurring monitoring savings

These examples compare full re-scrapes with incremental runs at different churn rates. Churn is the share of events that are new or whose tracked content changed since the previous run. Actual churn depends on your query breadth, source activity, and polling frequency — the scenarios below are examples, not predictions.

Example setup: 250 events per run, daily polling (30 runs/month). Costs scale linearly with the number of events.

Numbers below are for the primary **Event** event. Other events (**Full markets**, **Odds comparison**, **Match statistics**, **Statistics layer**) are billed separately when they fire.

| Churn rate | Full re-scrape run cost | Incremental run cost | Savings vs full re-scrape | Monthly cost after baseline |
|---|---:|---:|---:|---:|
| 5% — stable niche query | $0.75 | $0.04 | $0.71 (95%) | $1.16 |
| 15% — moderate broad query | $0.75 | $0.11 | $0.64 (85%) | $3.41 |
| 30% — high-volume aggregator | $0.75 | $0.23 | $0.53 (70%) | $6.78 |

Full re-scrape monthly cost at the same cadence: $22.53. First month with incremental costs $1.87 / $4.04 / $7.31 for the 5% / 15% / 30% scenarios because the first run builds baseline state at full cost before incremental savings apply.

Platform usage (see the note above) also applies to these figures. Incremental runs consume less of it on result processing, though the fixed per-run overhead stays the same.

### FAQ

#### How many results can I get from betano.com?

The number of results depends on the search query and available events on betano.com. Use the `maxResults` parameter to control how many results are returned per run.

#### Does Betano Odds Scraper support recurring monitoring?

Yes. Enable incremental mode to only receive new or changed events on subsequent runs. This is ideal for scheduled monitoring where you want to track changes over time without re-processing the full dataset.

#### Can I integrate Betano Odds Scraper with other apps?

Yes. Betano Odds Scraper works with Apify's [integrations](https://apify.com/integrations?fpr=1h3gvi) to connect with tools like Zapier, Make, Google Sheets, Slack, and more. You can also use webhooks to trigger actions when a run completes.

#### Can I use Betano Odds Scraper with the Apify API?

Yes. You can start runs, manage inputs, and retrieve results programmatically through the [Apify API](https://docs.apify.com/api/v2). Client libraries are available for JavaScript, Python, and other languages.

#### Can I use Betano Odds Scraper through an MCP Server?

Yes. Apify provides an [MCP Server](https://apify.com/apify/actors-mcp-server?fpr=1h3gvi) that lets AI assistants and agents call this actor directly. Use compact mode and `excludeEmptyFields` to keep payloads manageable for LLM context windows.

#### Is it legal to scrape betano.com?

This actor extracts publicly available data from betano.com. Web scraping of public information is generally considered legal, but you should always review the target site's terms of service and ensure your use case complies with applicable laws and regulations, including GDPR where relevant.

#### Your feedback

If you have questions, need a feature, or found a bug, please [open an issue](https://apify.com/blackfalcondata/betano-scraper/issues?fpr=1h3gvi) on the actor's page in Apify Console. Your feedback helps us improve.

### You might also like

- [Betano Odds API — Live and Pre-Match Odds, 14 Countries](https://apify.com/blackfalcondata/betano-odds-api?fpr=1h3gvi) — $3 day pass or $0.002 per call. Betano odds as a REST API: pre-match and live with score and clock,.
- [Elpris Scraper — Danish Electricity Prices & Suppliers](https://apify.com/blackfalcondata/elpris-scraper?fpr=1h3gvi) — Scrape every electricity product Danish suppliers report to elpris.dk — supplier, price bands.
- [Google Trends Scraper \[Just 💰$0.49\] — Interest & Related](https://apify.com/blackfalcondata/google-trends-scraper?fpr=1h3gvi) — 💰 $0.49 per 1,000 trending terms — the cheapest paid Google Trends scraper. Scrape live trending.
- [MLB Stats Scraper 💰$2/1K — Rosters & Season Stats](https://apify.com/blackfalcondata/mlb-scraper?fpr=1h3gvi) — Scrape statsapi.mlb.com for every MLB player in a season: full roster with batting, pitching.
- [Outseo Scraper: Full Leaderboard](https://apify.com/blackfalcondata/outseo-scraper?fpr=1h3gvi) — Scrape every ranked site on the outseo.lol organic-traffic leaderboard, not just the first page,.
- [Sportradar Match Stats Scraper — Lineups, Timeline, Players](https://apify.com/blackfalcondata/sportradar-stats-scraper?fpr=1h3gvi) — Match statistics from Sportradar at $2 per 1,000 matches plus $1 per 1,000 data layers: lineups,.
- [Transfermarkt Scraper \[Just 💰$0.5\] — football market values](https://apify.com/blackfalcondata/transfermarkt-market-value-scraper?fpr=1h3gvi) — 💰 $0.5 per 1,000 records. Scrape transfermarkt.com — player market values with full history ·.

### Getting started with Apify

New to Apify? [Create a free account with $5 credit](https://console.apify.com/sign-up?fpr=1h3gvi) — no credit card required.

1. Sign up — $5 platform credit included
2. Open this actor and configure your input
3. Click **Start** — export results as JSON, CSV, or Excel

Need more later? [See Apify pricing](https://apify.com/pricing?fpr=1h3gvi).

### How billing works

Per-event fees apply only to events actually delivered: the headline event fee for every match, the full-markets fee only when that match's market page came back, the comparison fee only for each extra country book attached, and the statistics fees only when a layer you asked for arrived. Sportradar publishes lineups, timeline, player numbers and situations only from around kick-off, so a match still days away returns the header and no layers, and costs nothing for statistics. Head to head, form and tables are available before the match.

A run that finds nothing is billed the Actor start fee and platform usage only. Platform usage is billed by Apify at your plan's rates on top of the event fees.

In incremental mode a match is re-emitted when its odds change, so a run can skip a match whose lineup moved while its prices did not. Tracking statistics in the change signal would re-emit and re-charge every live match every minute.

### Disclaimer

This actor reads publicly available odds from Betano's country websites. It is not affiliated with, endorsed by or operated by Betano or Kaizen Gaming. Odds, markets, scores and fixture lists are reproduced as the site served them at the time of the run and can change or be withdrawn at any moment; they are provided for information and analysis only, are not betting advice, and no result of this actor should be relied on to place a bet. Availability depends on the source: when a Betano site is down, blocks a region, changes its pages or lists no matches for your selection, a run can return fewer results or none. In that case you still pay the Actor start fee and the platform usage the run consumed, but no per-event fees, because events are charged only when they are delivered to your dataset. Access to gambling content is restricted in many jurisdictions; you are responsible for complying with the laws that apply to you and with Betano's terms of use.

### Search keywords

betano scraper, betano api, apify betano, betano data extraction, betano odds scraper, betano odds api, apify betano odds, betano odds data extraction, betano.com scraper, betano.com data, betano.com api, betano odds germany, betano odds germany scraper, betano odds brazil, betano odds brazil scraper, betano odds portugal, betano odds portugal scraper, betano odds romania, betano odds romania scraper, betano odds denmark, betano odds denmark scraper, betano odds czechia, betano odds czechia scraper, betano odds bulgaria, betano odds bulgaria scraper, betano odds peru, betano odds peru scraper, betano odds argentina, betano odds argentina scraper, betano odds chile, betano odds chile scraper, betano odds ecuador, betano odds ecuador scraper, betano odds nigeria, betano odds nigeria scraper, betano odds ghana, betano odds ghana scraper, betano odds canada, ontario, betano odds canada, ontario scraper.

# Actor input Schema

## `country` (type: `string`):

Which Betano country site prices the rows. Each site is a separate book with its own odds and its own fixture list.

## `sport` (type: `string`):

One sport per run. The coupon, the league list and the market tabs are all sport specific.

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

Pick several sports for one run. When set it replaces the single Sport above. The coupon, league resolution, outrights and live matches are then done for each sport in turn.

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

Leave empty for the whole coupon (see Hours ahead). Otherwise list leagues by name ("Premier League", "LaLiga", "Brasileirao Serie A"), by Betano league id ("1", "216") or by pasting the league page URL. Names are matched against the chosen sport's league list on the chosen country site.

## `allLeagues` (type: `boolean`):

Covers every league the book lists for the chosen sports, instead of only the matches starting in the next few hours. Use it to pull a whole sport rather than a time window. This is a much larger run: the Danish book alone lists 209 football leagues across 89 regions, so set Maximum events to something you actually want to pay for. Ignored when you name specific leagues, paste URLs or ask for live matches, because those are already an explicit scope.

## `eventUrls` (type: `array`):

Specific matches: paste Betano event page URLs from any country site, or bare event ids ("90925073"). These are fetched in addition to any leagues or coupon.

## `teamUrls` (type: `array`):

Paste Betano team page URLs from any country site. Every upcoming match of that team is returned; the site in the URL selects the book.

## `searchQueries` (type: `array`):

Team, player or competition names. Each query is one lookup on the chosen country site, and every matching upcoming or live match becomes an event. Free-text names are matched by Betano's own search, so "Man City" and "Manchester City" both work.

## `playerUrls` (type: `array`):

Paste Betano player page URLs from any country site. Every upcoming match of that player is returned, carrying that player's own markets: shots, assists, tackles, cards and goalscorer prices. The site in the URL selects the book.

## `startUrls` (type: `array`):

Any Betano page URL: a league, a region, a sport, a team, a player, a coupon page, an outrights page or an event. The site in the URL selects the country book for that URL. A region URL returns every league of that region.

## `hoursAhead` (type: `string`):

Coupon window used when no leagues, events or start URLs are given: every match of the chosen sport starting within the next 3, 12 or 24 hours.

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

Only matches starting within this many days from now. 0 keeps every upcoming match Betano lists. Applies to leagues, teams, regions and pasted start URLs; it does not apply to the hours-ahead coupon.

## `maxEvents` (type: `integer`):

Stop after this many events (0 = no limit). Applies across the whole run: every sport, league, coupon and URL in it shares the one budget, in the order they are listed.

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

"Headline markets" uses the odds shown on the listing (match result, over/under, both teams to score) with no extra page per event. Every other choice opens each event page: "All markets" returns the book’s own combined list, and the specific tabs return one market group each. You can combine them: on a large fixture the individual tabs carry markets the combined list does not, so picking "All markets" plus the tabs you care about returns more than "All markets" alone, at one extra lookup per tab.

## `liveMatches` (type: `boolean`):

Also return every match of the chosen sport that is in play right now, with the current score, match clock, period and live odds. Headline markets come from the live overview; any other market choice opens each live match for all of its live markets. Comparing a live match across country books is skipped, because a second book's in-play price is already stale by the time it arrives.

## `compareCountries` (type: `array`):

Also price each event's headline markets on these Betano country sites and attach them as oddsByCountry. Betano prices the same match differently per country, so this gives an in-house odds comparison. Each extra country adds one listing lookup per event.

## `includeOutrights` (type: `boolean`):

Add competition winner markets (league winner, tournament winner) for the chosen sport as extra rows with outright: true.

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

By default only matches that have not kicked off are returned. Turn this on to also return in-play matches with a snapshot of their current odds (isLive: true).

## `includeLogos` (type: `boolean`):

Adds team logo URLs, jersey colours, the league logo URL and the region flag URL to every event. Costs one extra lookup per country in the run. Coverage is partial: Betano publishes kit colours for most clubs, and crests mainly for national teams.

## `includeStats` (type: `boolean`):

Attaches Sportradar match statistics to every event that has them: lineups, timeline, per player numbers and more, depending on the layers you pick below. Betano publishes the Sportradar match id itself, so the two are joined on that id rather than matched by team name. Note that Sportradar publishes most layers only from around kick-off: a match days away returns the header (teams, venue, referee, competition, season) and no layers, and is not charged for statistics. Costs one extra lookup per event.

## `statsLayers` (type: `array`):

Which statistics to attach when "Match statistics" is on. Each layer is one more lookup per event, so pick what you use. The match header (teams, score, status, venue, referee) always comes with the statistics and needs no layer. Lineups, timeline, player statistics and situations exist only from around kick-off; head to head, form and tables are available before the match too.

## `language` (type: `string`):

English market and team names where the country site offers them (Germany, Portugal, Denmark, Czechia, Peru, Argentina, Chile, Ecuador). Brazil and Romania only serve their local language; Nigeria and Ghana are English already.

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

Decimal odds are always included. Add fractional (UK) or American (US) prices, or all three.

## `outputMode` (type: `string`):

"One row per event" nests all markets and selections inside the event (best for JSON). "One row per selection" flattens to a wide table with one price per row (best for CSV, Sheets and SQL).

## `compact` (type: `boolean`):

Core fields only (event, teams, start time, league, markets). Drops the descriptive extras.

## `excludeEmptyFields` (type: `boolean`):

Drop null, empty-string and empty-array fields from each record before it is saved.

## `incrementalMode` (type: `boolean`):

Remember every event and its prices between runs. The next run with the same settings returns only NEW events and events whose odds moved (UPDATED); unchanged events are skipped and not billed. Ideal for scheduled monitoring.

## `stateKey` (type: `string`):

Optional. Names the remembered universe for incremental mode. Leave empty to derive it from the country, sport, leagues, events and markets you selected.

## `emitUnchanged` (type: `boolean`):

In incremental mode, return unchanged events as well (marked UNCHANGED) instead of skipping them.

## `telegramToken` (type: `string`):

Telegram bot token (from @BotFather). Required for Telegram notifications.

## `telegramChatId` (type: `string`):

Telegram chat or channel ID (e.g. "-100123456789"). Required when telegramToken is set.

## `discordWebhookUrl` (type: `string`):

Discord incoming webhook URL. Server Settings, Integrations, Webhooks, New Webhook.

## `slackWebhookUrl` (type: `string`):

Slack incoming webhook URL. api.slack.com/messaging/webhooks.

## `notificationLimit` (type: `integer`):

Maximum number of events included in each notification message (1 to 20).

## `notifyOnlyChanges` (type: `boolean`):

When incremental mode is on, only send notifications for NEW and UPDATED events. Has no effect outside incremental mode.

## `whatsappAccessToken` (type: `string`):

WhatsApp Cloud API permanent access token (System User token from Meta Business). Recipient must have messaged the business number within the last 24h.

## `whatsappPhoneNumberId` (type: `string`):

Your WhatsApp Business phone-number ID (numeric, from Meta dashboard). Required when whatsappAccessToken is set.

## `whatsappTo` (type: `string`):

Recipient phone in E.164 format without + (e.g. "436641234567"). Recipient must have messaged your business number within last 24h.

## `webhookUrl` (type: `string`):

Receives a JSON POST with {metadata, items} after each run. Universal escape hatch for n8n, Make, Zapier or custom backends.

## `webhookHeaders` (type: `object`):

Optional JSON object of custom headers (e.g. {"Authorization":"Bearer ..."}).

## `appConnector` (type: `string`):

Optional. Pick a connected app under Settings, API & Integrations to receive your results. Best-effort across MCP connectors as Apify expands its catalog.

## `mcpIssueTeam` (type: `string`):

Only when the connected app is an issue tracker: the team (name or ID) the summary issue is created under, if that app requires one.

## Actor input object example

```json
{
  "country": "DE",
  "sport": "football",
  "sports": [],
  "leagues": [
    "Premier League",
    "Bundesliga"
  ],
  "allLeagues": false,
  "eventUrls": [],
  "teamUrls": [],
  "searchQueries": [],
  "playerUrls": [],
  "startUrls": [],
  "hoursAhead": "24",
  "daysAhead": 0,
  "maxEvents": 20,
  "markets": [
    "main"
  ],
  "liveMatches": false,
  "compareCountries": [],
  "includeOutrights": false,
  "includeLive": false,
  "includeLogos": false,
  "includeStats": false,
  "statsLayers": [
    "teamStats"
  ],
  "language": "en",
  "oddsFormat": "decimal",
  "outputMode": "event",
  "compact": false,
  "excludeEmptyFields": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "notificationLimit": 5,
  "notifyOnlyChanges": false
}
```

# Actor output Schema

## `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 = {
    "leagues": [
        "Premier League",
        "Bundesliga"
    ],
    "daysAhead": 0,
    "maxEvents": 20,
    "markets": [
        "main"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("blackfalcondata/betano-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 = {
    "leagues": [
        "Premier League",
        "Bundesliga",
    ],
    "daysAhead": 0,
    "maxEvents": 20,
    "markets": ["main"],
}

# Run the Actor and wait for it to finish
run = client.actor("blackfalcondata/betano-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 '{
  "leagues": [
    "Premier League",
    "Bundesliga"
  ],
  "daysAhead": 0,
  "maxEvents": 20,
  "markets": [
    "main"
  ]
}' |
apify call blackfalcondata/betano-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,blackfalcondata/betano-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/HdtlE4Wj5YhBUe3Ay/builds/ZNMKJhhbpkjfSeEW6/openapi.json
