# Fonbet Scraper - Live Sports Odds, Scores & Betting Markets (`abotapi/fonbet-ru-scraper`) Actor

Scrape Fonbet (fonbet.ru) sports betting events by sport, tournament, team or URL. Extract odds across all markets, live scores, match clocks, teams, start times, promotions and sub-events including halves, corners and cards.

- **URL**: https://apify.com/abotapi/fonbet-ru-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 event 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

## Fonbet Scraper: Sports Betting Odds, Live Scores & Events

Fonbet Scraper turns fonbet.ru (fon.bet) into clean, structured betting data. Pick sports, tournaments or teams, or paste page links, and get one row per event with the teams, the tournament, the start time, the live score and match clock, every odds price with its market name and the sub-events (halves, corners, cards and more). Export to JSON, CSV or Excel, or pull results straight into your app through the API.

### Why This Scraper?

- **Every market, every price.** One row per event with the full market list: decimal odds, handicap and total parameters, market names and outcome captions, in Russian or English.
- **Live data included.** Match clock, running score, period scores, live delay and the scoring function of each live event.
- **Sub-events in the same row.** Halves, periods, corners, cards and other derived events come nested under their parent with their own odds.
- **Three ways in.** Search by sport, tournament or team keyword, filter live or pre-match and the start window, or paste any supported page link.
- **Built for monitoring.** Incremental mode returns only new and changed events, with a grace period before an event is marked expired.
- **Final scores of past games.** Switch on Final scores and the same run also returns every finished game of the last days in your selection, with the final score, the winner, the period scores and the match statistics the bookmaker publishes.
- **One clear cap.** Max items is the only default limit, so a run does exactly as much as you ask.

### Use Cases

- **Odds comparison and aggregation:** pull prices into your own comparison table, one stable schema across every sport.
- **Betting models and research:** build price histories and closing line datasets for football, tennis, hockey, esports and more.
- **Live score dashboards:** follow live events with clock, score and period breakdown.
- **Price alerts:** schedule incremental runs and react to price moves, new events and withdrawn events.
- **Bet grading and model backtests:** pair the prices you collected with the final scores from the same actor to grade picks and measure accuracy.
- **Media and content teams:** feed fixtures, tournaments and markets into previews and tipping pages.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `rowId` / `eventId` | `1000000` / `1000000` |
| `url` | `https://fon.bet/sports/football/100000/1000000` |
| `title` | `Team A - Team B` |
| `sportName` / `tournamentName` | `Football` / `Country. League` |
| `startTimeIso` / `isLive` | `2026-01-01T00:00:00Z` / `false` |
| `sport` | id, parentId, kind, name, alias |
| `tournament` | id, name, tournamentInfoId, caption, icon, sportCategoryId, geoCategoryId, regionId |
| `event.id` / `event.parentId` / `event.level` / `event.num` | `1000000` / `null` / `1` / `10000` |
| `event.sportId` / `event.kind` / `event.rootKind` | `100000` / `1` / `1` |
| `event.team1` / `event.team2` | `Team A` / `Team B` |
| `event.team1Id` / `event.team2Id` | `100000` / `100001` |
| `event.team1RegionId` / `event.team2RegionId` | `100` / `200` |
| `event.name` / `event.info` / `event.url` | \`\` / `Match in City` / event page link |
| `event.startTime` / `event.place` / `event.state` | `1790000000` / `line` / `null` |
| `event.priority` / `event.statisticsTypes` | `6` / `++-` |
| `event.hasPromos` / `event.tv` / `event.matchOfTheDay` / `event.willStartSoon` | `["3"]` / `[4, 6]` / `false` / `false` |
| `live.timer` / `live.timerSeconds` / `live.liveDelay` | `70:00` / `4200` / `3` |
| `live.scoreFunction` / `live.scoreComment` / `live.scores` | `Football` / `(1-0)` / period scores |
| `odds[].factorId` / `odds[].value` / `odds[].eventId` | `921` / `1.50` / `1000000` |
| `odds[].param` / `odds[].paramText` / `odds[].isMain` | `-150` / `-1.5` / `true` (price sits in a main-market table the site shows first) |
| `odds[].marketName` / `odds[].outcome` / `odds[].countAll` | `Outcomes` / `1` / `700` |
| `subEvents[]` | every sub-event at any depth as a flat list in tree order (halves, then their corners, cards and fouls): id, parentId, level, kind, name, startTime, odds |
| `publicPromos` / `oddsCount` / `subEventCount` | `["3"]` / `700` / `15` |
| `changeType` / `changedFields` | `NEW` / `[]` (incremental mode) |
| `scrapedAt` | `2026-01-01T00:00:00Z` |

With **Final scores of past games** on, every finished game also arrives as a `result` row (`recordType` = `result`): `homeTeam`, `awayTeam`, integer `homeScore` and `awayScore`, `winner` (`home`, `away` or `draw`), `winnerTeam`, `status` (always `finished`), `scoreText`, `periodScores`, `statistics` (corners, cards, fouls and other counted statistics with home and away values and their period split, where published), `sportName`, `leagueName`, `tournamentName`, `competitionId`, `startTimeIso`, the odds `eventId` when the game is still on the line (otherwise empty, with a `matchKey` of competition, date and teams for your own join) and `note` (for example the first-goal comment). The bookmaker does not publish a venue, so result rows carry none. Only finished games are returned: games not played, interrupted or still running never produce a result row. `winner` compares the final scores only.

### How to Use

1. Open the actor and choose a mode: search by sport, tournament or team, or paste page links.
2. Set Max items (default 20). Turn full market detail on for every market and sub-event, or off for one lighter row per event.
3. Start the run. Rows appear in the dataset as events are read.
4. Export to JSON, CSV or Excel, or read the dataset through the API.

**Search football, pre-match only:**

```json
{
  "mode": "search",
  "sports": ["football"],
  "eventStatus": "line",
  "maxItems": 50
}
```

**Live events with a team keyword:**

```json
{
  "mode": "search",
  "eventStatus": "live",
  "searchTerms": ["Spartak"],
  "maxItems": 20
}
```

**Paste page links:**

```json
{
  "mode": "url",
  "urls": [
    "https://fon.bet/sports/football/46065",
    "https://fon.bet/live/tennis"
  ],
  "maxItems": 40
}
```

#### Output views

The dataset has an Events overview view (title, sport, tournament, start time, live flag, odds count), a Final scores view for result rows and a Changes view for incremental runs.

#### Run it from your code

**Python:**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<ACTOR_ID>").call(run_input={"mode": "search", "sports": ["football"], "maxItems": 20})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["oddsCount"])
```

**JavaScript:**

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

const client = new ApifyClient({ token: "<YOUR_APIFY_TOKEN>" });
const run = await client.actor("<ACTOR_ID>").call({ mode: "search", sports: ["football"], maxItems: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length);
```

#### Tips

- Turn full market detail off to read many events quickly: each row then carries the main odds the site lists on the event line.
- Use Starting within (hours) with Live or pre-match set to pre-match to watch only the next events.
- For recurring monitoring, switch on Incremental changes and keep the same State key between runs.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each row, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify, Settings, Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. If the picker is empty, you have not authorized a connector yet.
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | search = pick sports, tournaments or teams and let the actor build the list of events. url = paste fon.bet or fonbet.ru pages (home, sport, tournament, event, live ...). |
| `sports` | array | - | Only events of these sports. Leave empty for every sport. Only applies when mode = search. |
| `tournaments` | array | - | Only events of tournaments whose name contains one of these words (for example Premier League, UEFA Nations League) or whose numeric tournament id equals one of them. Only applies when mode = search. |
| `searchTerms` | array | - | Only events where a team, the event name, the tournament or the sport contains one of these words. Only applies when mode = search. |
| `eventStatus` | string | `all` | Pre-match lists upcoming events, live lists events in play right now. Only applies when mode = search. |
| `startsWithinHours` | integer | - | Only pre-match events that start within this many hours from now. Live events are always kept. Leave empty or 0 for no limit. Only applies when mode = search. |
| `onlyTopEvents` | boolean | `false` | Only the events the site features as top and top live events. Only applies when mode = search. |
| `language` | string | `ru` | Language of team, tournament and market names. In URL mode, English is used only when every pasted page is an /en/ link; otherwise this Language setting decides for the whole run. |
| `urls` | array | one example of each page type | Paste one or more fon.bet or fonbet.ru pages: the home page, a sport (/sports/football), a tournament (/sports/football/46065), an event (/sports/football/46065/69507114), the live page (/live, /live/football) or the promotions page. Pages that list no events of their own (results, statistics, help) read the whole line. Several URLs are supported. The search fields above are ignored in this mode. Left untouched, URL mode reads one example of each supported page type. |
| `fetchDetails` | boolean | `true` | Fetch every event's complete market list, including the markets of its sub-events (halves, corners, cards, players ...). Turn off for one lighter row per event with the main odds only. |
| `includeResults` | boolean | `false` | Also return the final result of every finished game in your selection (search mode: your sports, tournaments and team terms; URL mode: sport, tournament and home pages) over the last Results days back days. One row per finished game. The live / pre-match, start-window and top-events filters apply to odds rows only. |
| `resultsDaysBack` | integer | `2` | Days back for final scores (1 to 14, Moscow-time days). Only used when Final scores of past games is on. |
| `maxPages` | integer | - | Optional safety stop on how many pasted pages or sport searches are read in total. This does NOT cap the run: leave it empty for unlimited pages and the run is bounded solely by Max items. |
| `maxItems` | integer | `20` | The run's single hard cap: maximum event rows across all searches. Defaults to 20 (also when the field is omitted through the API). Set 0 for unlimited. This is the only default limit; Max pages is unlimited by default and defers to this. |
| `proxy` | object | `{"useApifyProxy": true}` | Connection used for requests. The standard Apify proxy (datacenter) is preselected and served the data in our checks, so no change is needed; Residential is optional. When the selected connection keeps failing, the run may move to a residential connection (with a per-run traffic budget), billed to your Apify plan. |
| `resumeFromRunId` | string | - | Paste a previous run ID or dataset ID to continue a large pull without returning or charging for rows already collected there. For recurring monitoring of the same search, use Incremental changes below instead. |
| `incrementalMode` | boolean | `false` | For recurring runs, return only NEW, UPDATED and REAPPEARED events; events unchanged since the last run are not returned or billed. Each event is compared on every field (sport, tournament, event details, score, odds, sub-events) except the scrape time, the running match clock (live.timer, live.timerSeconds), event.willStartSoon, the market-list sizes (countAll) and publicPromos, which stay in the output but never count as a change. Each row gets changeType, changedFields, firstSeenAt and lastSeenAt; outside incremental mode these four fields are empty. Final-score result rows are compared on their status and final score only, are returned once per game and are never marked expired. The baseline is kept per State key; changing the sports, tournaments or pasted pages starts a new baseline unless State key is set (the final-score settings never start a new baseline). |
| `stateKey` | string | - | Incremental mode only. Optional name for this campaign's saved baseline. Leave empty to derive it from the selected sports, tournaments or pasted pages, so each distinct search keeps its own baseline. |
| `emitUnchanged` | boolean | `false` | Incremental mode only. Also return (and bill as normal rows) events whose values did not change. |
| `emitExpired` | boolean | `false` | Incremental mode only. Return an EXPIRED row for events no longer listed after Expire after missed scans complete scans (billed like any returned row). EXPIRED means the event was not in the scanned list (it started, finished or was withdrawn). Only after a complete scan: a Max items or Max pages cut, a keyword, status, start-window or top-events filter, a resume, an early stop or a failed read disables it. |
| `expireAfterMissedScans` | integer | `1` | Incremental mode only. How many complete scans in a row must miss an event before it is reported EXPIRED. |
| `ignoreFieldsForChanges` | array | - | Incremental mode only. Extra field names (dotted for nested, e.g. odds or live.scores) that never mark a row as UPDATED and are left out of changedFields; they stay in the output. Changing this list re-bases the saved events once without reporting them as changed. live.timer, live.timerSeconds, event.willStartSoon, countAll and publicPromos are always ignored. |
| `mcpConnectors` | array | - | Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com). |
| `notionParentPageUrl` | string | - | URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. Does not affect the dataset. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "rowId": "1000000",
  "recordType": "event",
  "eventId": 1000000,
  "url": "https://fon.bet/sports/football/100000/1000000",
  "title": "Team A - Team B",
  "sportName": "Football",
  "tournamentName": "Country. League",
  "startTimeIso": "2026-01-01T00:00:00Z",
  "isLive": false,
  "oddsCount": 2,
  "subEventCount": 1,
  "sport": {"id": 1, "parentId": null, "kind": "sport", "name": "Football", "alias": "football"},
  "tournament": {"id": 100000, "name": "Country. League", "tournamentInfoId": 100, "caption": "League", "icon": "/icons/league.svg", "sportCategoryId": 2, "geoCategoryId": 50, "regionId": 100},
  "event": {"id": 1000000, "parentId": null, "level": 1, "num": 10000, "sportId": 100000, "kind": 1, "rootKind": 1, "team1Id": 100000, "team2Id": 100001, "team1": "Team A", "team2": "Team B", "team1RegionId": 100, "team2RegionId": 200, "name": "", "startTime": 1790000000, "place": "line", "priority": 6, "state": null, "hasPromos": [], "tv": [], "matchOfTheDay": false, "willStartSoon": false, "statisticsTypes": "++-", "info": null, "url": "https://fon.bet/sports/football/100000/1000000"},
  "live": {"timer": null, "timerSeconds": null, "scoreFunction": null, "scoreComment": null, "scores": null, "liveDelay": null},
  "odds": [
    {"eventId": 1000000, "factorId": 921, "value": 1.5, "param": null, "paramText": null, "marketName": "Outcomes", "outcome": "1", "countAll": 700, "isMain": true},
    {"eventId": 1000000, "factorId": 923, "value": 2.6, "param": null, "paramText": null, "marketName": "Outcomes", "outcome": "2", "countAll": 700, "isMain": true}
  ],
  "subEvents": [
    {"id": 1000001, "parentId": 1000000, "level": 2, "num": 10001, "kind": 100201, "rootKind": 100200, "name": "1st half", "startTime": 1790000000, "priority": 6, "place": "line", "sportId": 100000, "state": null, "odds": []}
  ],
  "publicPromos": ["3"],
  "scrapedAt": "2026-01-01T00:00:00Z",
  "changeType": null,
  "changedFields": null,
  "firstSeenAt": null,
  "lastSeenAt": null
}
```

### Plan Requirement

The actor runs on the standard Apify proxy (datacenter) preselected in the input, which served the data in our checks, so no action is needed; Residential is optional. When the selected connection keeps failing, the run may move to a residential connection (with a per-run traffic budget) that is billed to your Apify plan. Connection handling (exit rotation, retries, dead-exit replacement, a traffic budget per run on residential connections, a backup connection when the selected one is refused for your plan) is built in. When the selected connection is refused for your plan, the log says so, the run continues on the backup connection where it can, and a run that cannot read anything ends as failed with a clear message in the log and the run status; it never reports an empty result.

### FAQ

#### How much does it cost?

Pricing is pay per event: a small charge per run, a charge per event row (a finished-game result row counts as one row) and a small extra charge per event row when full market detail is on. Result rows never carry the full-market-detail charge. See the pricing tab of the actor for the current numbers.

#### Can I get only the changes on a schedule?

Yes. Switch on Incremental changes and keep the same State key. Each run returns only NEW, UPDATED and REAPPEARED events. The match clock, the market-list size and the site-wide promotions list never count as a change.

#### How do I list only live events, or only upcoming ones?

Use Live or pre-match in search mode, or paste the live page link (for example fon.bet/live/football).

#### Which sports and tournaments can I use?

Football, tennis, hockey, basketball, esports, table tennis, volleyball, handball, boxing and more. Tournaments match on a name fragment or a numeric tournament id.

#### Is it legal to scrape fonbet.ru?

The actor collects publicly visible odds and fixtures. You are responsible for using the data in line with the site's terms and the laws that apply to you.

#### How do the final scores work with Max items and incremental mode?

With final scores on, the scores are read first and up to half of Max items is kept for the result rows that will really be delivered (new or changed ones); when there are none, the odds rows keep the whole cap, and results also use whatever the odds rows leave. Result rows are delivered once per game and never reported EXPIRED; a later score correction arrives as one UPDATED row, and the results settings never start a new incremental baseline. Each day of results is a large read, so a 14-day window uses noticeably more connection traffic than a 2-day one. If some days cannot be read the run ends with a partial-results note; if nothing at all can be read and there are no odds rows either, the run ends as failed with a clear message instead of an empty result.

#### Why did my run fail instead of returning an empty dataset?

When no data could be read at all, the run ends as failed with an explanation. An empty selection (no event matched your filters) ends successfully with a status message instead.

#### Can I use it with AI agents or MCP?

Yes. The dataset is available through the Apify API and the Apify MCP server, and the MCP export in the input sends a summary of each row to your connected apps.

### 🔗 Want more sports data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>⚽ <a href="https://apify.com/abotapi/bet365-odds-scraper"><b>bet365 Odds Scraper</b></a><br>Scrape bet365 live in-play and pre-match odds across 20+ sports. Extract fixture...</td><td>⚽ <a href="https://apify.com/abotapi/sofascore-scraper"><b>SofaScore Scraper ⚽ Live Scores, Stats, Players &amp; Odds</b></a><br>Pull structured sports data from SofaScore across football, basketball, tennis, and 20+...</td></tr>
<tr><td>⚽ <a href="https://apify.com/abotapi/sportsbook-odds-scraper"><b>Sportsbook Odds Scraper (1xBet, Melbet, Linebet, Paripulse)</b></a><br>Collect live and prematch betting odds from 1xBet, Melbet, Linebet and Paripulse. Give it...</td><td>⚽ <a href="https://apify.com/abotapi/betmgm-com-odds-scraper"><b>BetMGM Scraper</b></a><br>Scrape BetMGM (betmgm.com) live and upcoming sports betting odds. Extract events...</td></tr>
<tr><td>⚽ <a href="https://apify.com/abotapi/sportsbet-au-scraper"><b>Sportsbet AU Scraper 🏅 Sports Odds &amp; Racing Prices</b></a><br>Scrape sportsbet.com.au odds: events, markets, selections and prices for AFL, NRL...</td><td>⚽ <a href="https://apify.com/abotapi/draftkings-sportsbook-odds-scraper"><b>DraftKings Scraper</b></a><br>Scrape DraftKings Sportsbook odds, game lines, team totals, player and game props...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/fonbet-ru-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

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

search = pick sports, tournaments or teams and let the actor build the list of events. url = paste fon.bet or fonbet.ru pages (home, sport, tournament, event, live ...).

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

Only events of these sports. Leave empty for every sport. Only applies when mode = search.

## `tournaments` (type: `array`):

Only events of tournaments whose name contains one of these words (for example Premier League, UEFA Nations League) or whose numeric tournament id equals one of them. Only applies when mode = search.

## `searchTerms` (type: `array`):

Only events where a team, the event name, the tournament or the sport contains one of these words. Only applies when mode = search.

## `eventStatus` (type: `string`):

Pre-match lists upcoming events, live lists events in play right now. Only applies when mode = search.

## `startsWithinHours` (type: `integer`):

Only pre-match events that start within this many hours from now. Live events are always kept. Leave empty or 0 for no limit. Only applies when mode = search.

## `onlyTopEvents` (type: `boolean`):

Only the events the site features as top and top live events. Only applies when mode = search.

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

Language of team, tournament and market names. In URL mode, English is used when every pasted page is an /en/ link; if any pasted link is not an /en/ link, this Language setting decides.

## `urls` (type: `array`):

Paste one or more fon.bet or fonbet.ru pages: the home page, a sport (/sports/football), a tournament (/sports/football/46065), an event (/sports/football/46065/69507114), the live page (/live, /live/football) or the promotions page. Pages that list no events of their own (results, statistics, help) read the whole line. Several URLs are supported. The search fields above are ignored in this mode. Left untouched, URL mode reads one example of each supported page type.

## `fetchDetails` (type: `boolean`):

Fetch every event's complete market list, including the markets of its sub-events (halves, corners, cards, players ...). Turn off for one lighter row per event with the main odds only.

## `includeResults` (type: `boolean`):

Also return the final result of every FINISHED game in your selection (search mode: your sports, tournaments and team terms; URL mode: sport, tournament and home pages): home and away team, final score, winner, period scores, match statistics where published, sport, league and start time, and the odds event id when the game is still on the line. One row per finished game (record type result); games not played, interrupted or still running are never returned. The live / pre-match, start-window and top-events filters apply to odds rows only. Each result row is one dataset item and counts toward Max items.

## `resultsDaysBack` (type: `integer`):

How many days back to collect final scores (1 to 14, Moscow-time days). Only used when Final scores of past games is on.

## `maxPages` (type: `integer`):

Optional safety stop on how many pasted pages or sport searches are read in total. This does NOT cap the run: leave it empty for unlimited pages and the run is bounded solely by Max items.

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

The run's single hard cap: maximum event rows across all searches. Defaults to 20 (also when the field is omitted through the API). Set 0 for unlimited. This is the only default limit; Max pages is unlimited by default and defers to this.

## `proxy` (type: `object`):

Connection used for requests. The standard Apify proxy (datacenter) is preselected and served the data in our checks, so no change is needed; Residential is optional. When the selected connection keeps failing, the run may move to a residential connection (with a per-run traffic budget), billed to your Apify plan.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large pull without returning or charging for rows already collected there. For recurring monitoring of the same search, use Incremental changes below instead.

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

For recurring runs, return only NEW, UPDATED and REAPPEARED events; events unchanged since the last run are not returned or billed. Each event is compared on every field (sport, tournament, event details, score, odds, sub-events) except the scrape time, the running match clock (live.timer, live.timerSeconds), event.willStartSoon, the market-list sizes (countAll) and publicPromos, which stay in the output but never count as a change. Each row gets changeType, changedFields, firstSeenAt and lastSeenAt; outside incremental mode these four fields are empty. Final-score result rows are compared on their status and final score only, are returned once per game and are never marked expired. The baseline is kept per State key; changing the sports, tournaments or pasted pages starts a new baseline unless State key is set (the final-score settings never start a new baseline).

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

Incremental mode only. Optional name for this campaign's saved baseline. Leave empty to derive it from the selected sports, tournaments or pasted pages, so each distinct search keeps its own baseline.

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

Incremental mode only. Also return (and bill as normal rows) events whose values did not change.

## `emitExpired` (type: `boolean`):

Incremental mode only. Return an EXPIRED row for events no longer listed after Expire after missed scans complete scans (billed like any returned row). EXPIRED means the event was not in the scanned list (it started, finished or was withdrawn). Only after a complete scan: a Max items or Max pages cut, a keyword, status, start-window or top-events filter, a resume, an early stop or a failed read disables it.

## `expireAfterMissedScans` (type: `integer`):

Incremental mode only. How many complete scans in a row must miss an event before it is reported EXPIRED.

## `ignoreFieldsForChanges` (type: `array`):

Incremental mode only. Extra field names (dotted for nested, e.g. odds or live.scores) that never mark a row as UPDATED and are left out of changedFields; they stay in the output. Changing this list re-bases the saved events once without reporting them as changed. live.timer, live.timerSeconds, event.willStartSoon, countAll and publicPromos are always ignored.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "sports": [
    "football"
  ],
  "tournaments": [],
  "searchTerms": [],
  "eventStatus": "all",
  "onlyTopEvents": false,
  "language": "ru",
  "urls": [
    "https://fon.bet/",
    "https://www.fonbet.ru/",
    "https://fon.bet/sports",
    "https://fon.bet/sports/football",
    "https://fon.bet/sports/football/46065",
    "https://fon.bet/sports/football/46065/69507114",
    "https://fon.bet/live",
    "https://fon.bet/live/football",
    "https://fon.bet/results",
    "https://fon.bet/statistic",
    "https://fon.bet/promos/actions",
    "https://fon.bet/apps/android",
    "https://fon.bet/sports/football?utm_source=x&utm_medium=y",
    "https://fon.bet/en/sports/football",
    "https://fon.bet/help-center/vopros-otvet",
    "https://fon.bet/sitemap.xml",
    "https://fonbet.ru/",
    "https://www.fonbet.ru/sports/football/46065/69507114"
  ],
  "fetchDetails": true,
  "includeResults": false,
  "resultsDaysBack": 2,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "expireAfterMissedScans": 1,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `changes` (type: `string`):

No description

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

No description

## `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 = {
    "mode": "search",
    "sports": [
        "football"
    ],
    "tournaments": [],
    "searchTerms": [],
    "urls": [
        "https://fon.bet/",
        "https://www.fonbet.ru/",
        "https://fon.bet/sports",
        "https://fon.bet/sports/football",
        "https://fon.bet/sports/football/46065",
        "https://fon.bet/sports/football/46065/69507114",
        "https://fon.bet/live",
        "https://fon.bet/live/football",
        "https://fon.bet/results",
        "https://fon.bet/statistic",
        "https://fon.bet/promos/actions",
        "https://fon.bet/apps/android",
        "https://fon.bet/sports/football?utm_source=x&utm_medium=y",
        "https://fon.bet/en/sports/football",
        "https://fon.bet/help-center/vopros-otvet",
        "https://fon.bet/sitemap.xml",
        "https://fonbet.ru/",
        "https://www.fonbet.ru/sports/football/46065/69507114"
    ],
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/fonbet-ru-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 = {
    "mode": "search",
    "sports": ["football"],
    "tournaments": [],
    "searchTerms": [],
    "urls": [
        "https://fon.bet/",
        "https://www.fonbet.ru/",
        "https://fon.bet/sports",
        "https://fon.bet/sports/football",
        "https://fon.bet/sports/football/46065",
        "https://fon.bet/sports/football/46065/69507114",
        "https://fon.bet/live",
        "https://fon.bet/live/football",
        "https://fon.bet/results",
        "https://fon.bet/statistic",
        "https://fon.bet/promos/actions",
        "https://fon.bet/apps/android",
        "https://fon.bet/sports/football?utm_source=x&utm_medium=y",
        "https://fon.bet/en/sports/football",
        "https://fon.bet/help-center/vopros-otvet",
        "https://fon.bet/sitemap.xml",
        "https://fonbet.ru/",
        "https://www.fonbet.ru/sports/football/46065/69507114",
    ],
    "maxItems": 20,
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/fonbet-ru-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 '{
  "mode": "search",
  "sports": [
    "football"
  ],
  "tournaments": [],
  "searchTerms": [],
  "urls": [
    "https://fon.bet/",
    "https://www.fonbet.ru/",
    "https://fon.bet/sports",
    "https://fon.bet/sports/football",
    "https://fon.bet/sports/football/46065",
    "https://fon.bet/sports/football/46065/69507114",
    "https://fon.bet/live",
    "https://fon.bet/live/football",
    "https://fon.bet/results",
    "https://fon.bet/statistic",
    "https://fon.bet/promos/actions",
    "https://fon.bet/apps/android",
    "https://fon.bet/sports/football?utm_source=x&utm_medium=y",
    "https://fon.bet/en/sports/football",
    "https://fon.bet/help-center/vopros-otvet",
    "https://fon.bet/sitemap.xml",
    "https://fonbet.ru/",
    "https://www.fonbet.ru/sports/football/46065/69507114"
  ],
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/fonbet-ru-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/fonbet-ru-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/baRowxL3x2Vd2Z6Dl/builds/8AqbEg9FMGFwQtVyD/openapi.json
