# ODDS REALTIME

## ODDS\_REALTIME Channel

The ODDS\_REALTIME channel delivers only the odds that have changed, in real-time.

### Availability

| Plan  | Available |
| ----- | --------- |
| BASIC | No        |
| PRO   | No        |
| ULTRA | No        |
| MEGA  | Yes       |

### Update Frequency

Updates are sent **immediately** when odds change (real-time).

### Events

| Event                  | Description       |
| ---------------------- | ----------------- |
| odds\_update\_realtime | Changed odds only |

***

### odds\_update\_realtime

Delivers only the odds that have changed since the last update.

#### Message

```json
{
  "type": "odds_update_realtime",
  "channel": "ODDS_REALTIME",
  "matchId": "12345",
  "leagueId": "67890",
  "ts": 1705314600000,
  "data": {
    "changedOdds": [
      {
        "market": "live1x2",
        "value": "1.75;3.80;4.50"
      },
      {
        "market": "liveOU",
        "value": "2.20;1.65|2.5"
      }
    ]
  }
}
```

#### Data Fields

| Field                  | Type   | Description           |
| ---------------------- | ------ | --------------------- |
| `changedOdds`          | array  | Array of changed odds |
| `changedOdds[].market` | string | Market name           |
| `changedOdds[].value`  | string | New odds value        |

#### Available Markets

| Market Name             | Format                  | Description                 |
| ----------------------- | ----------------------- | --------------------------- |
| `kickoff1x2`            | `"home;draw;away"`      | 1X2 at kickoff              |
| `live1x2`               | `"home;draw;away"`      | Live 1X2                    |
| `starting1x2`           | `"home;draw;away"`      | Opening 1X2                 |
| `kickoffOU`             | `"over;under\|line"`    | O/U at kickoff              |
| `liveOU`                | `"over;under\|line"`    | Live O/U                    |
| `startingOU`            | `"over;under\|line"`    | Opening O/U                 |
| `kickoffAH`             | `"home;away\|handicap"` | AH at kickoff               |
| `liveAH`                | `"home;away\|handicap"` | Live AH                     |
| `startingAH`            | `"home;away\|handicap"` | Opening AH                  |
| `kickoffAsianCorners`   | `"over;under\|line"`    | Asian Corners at kickoff    |
| `liveAsianCorners`      | `"over;under\|line"`    | Live Asian Corners          |
| `kickoff1hAH`           | `"home;away\|handicap"` | 1H AH at kickoff            |
| `live1hAH`              | `"home;away\|handicap"` | Live 1H AH                  |
| `kickoff1hGoals`        | `"over;under\|line"`    | 1H O/U at kickoff           |
| `live1hGoals`           | `"over;under\|line"`    | Live 1H O/U                 |
| `kickoff1hAsianCorners` | `"over;under\|line"`    | 1H Asian Corners at kickoff |
| `live1hAsianCorners`    | `"over;under\|line"`    | Live 1H Asian Corners       |
| `kickoff1hResult`       | `"home;draw;away"`      | 1H Result at kickoff        |
| `live1hResult`          | `"home;draw;away"`      | Live 1H Result              |
| `dropping1x2`           | `"home;draw;away"`      | 1X2 odds change             |

***

### Subscription Examples

#### Subscribe to all real-time odds updates

NO scope "all" allowed

#### Subscribe to a specific match

```json
{"action": "subscribe", "channel": "ODDS_REALTIME", "scope": "match", "id": "b01d28ac92221034"}
```

#### Subscribe to a league

```json
{"action": "subscribe", "channel": "ODDS_REALTIME", "scope": "league", "id": "f2b16fa54cb525d"}
```

***

### Example: Maintaining Local State

```javascript
// Local state for match odds
const matchOdds = {};

function initializeOdds(matchId) {
  matchOdds[matchId] = {
    live1x2: null,
    liveOU: null,
    liveAH: null,
    liveAsianCorners: null,
    live1hAH: null,
    live1hGoals: null
    // ... other markets initialized to null
  };
}

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type !== 'odds_update_realtime') return;

  const matchId = msg.matchId;

  // Initialize if first update for this match
  if (!matchOdds[matchId]) {
    initializeOdds(matchId);
  }

  // Apply delta updates
  msg.data.changedOdds.forEach(change => {
    const oldValue = matchOdds[matchId][change.market];
    matchOdds[matchId][change.market] = change.value;

    console.log(`[${matchId}] ${change.market}: ${oldValue} → ${change.value}`);
  });

  // Now matchOdds[matchId] contains the current state
  console.log('Current odds:', matchOdds[matchId]);
};
```

### Example: Tracking 1X2 Movement

```javascript
const oddsHistory = {};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type !== 'odds_update_realtime') return;

  msg.data.changedOdds.forEach(change => {
    if (change.market === 'live1x2') {
      const matchId = msg.matchId;
      const [home, draw, away] = change.value.split(';').map(parseFloat);

      // Initialize history
      if (!oddsHistory[matchId]) {
        oddsHistory[matchId] = [];
      }

      // Record change with timestamp
      const lastEntry = oddsHistory[matchId][oddsHistory[matchId].length - 1];
      oddsHistory[matchId].push({
        ts: msg.ts,
        home,
        draw,
        away,
        homeChange: lastEntry ? (home - lastEntry.home).toFixed(2) : 0,
        awayChange: lastEntry ? (away - lastEntry.away).toFixed(2) : 0
      });

      // Detect significant movement
      if (lastEntry) {
        const homeMove = home - lastEntry.home;
        const awayMove = away - lastEntry.away;

        if (homeMove < -0.10) {
          console.log(`ALERT: Home odds dropping significantly (${homeMove.toFixed(2)})`);
        }
        if (awayMove < -0.10) {
          console.log(`ALERT: Away odds dropping significantly (${awayMove.toFixed(2)})`);
        }
      }
    }
  });
};
```

### Example: Real-time Odds Display

```javascript
function parse1x2(value) {
  if (!value) return { home: '-', draw: '-', away: '-' };
  const [home, draw, away] = value.split(';');
  return { home, draw, away };
}

function parseOU(value) {
  if (!value) return { over: '-', under: '-', line: '-' };
  const [odds, line] = value.split('|');
  const [over, under] = odds.split(';');
  return { over, under, line };
}

function parseAH(value) {
  if (!value) return { home: '-', away: '-', handicap: '-' };
  const [odds, handicap] = value.split('|');
  const [home, away] = odds.split(';');
  return { home, away, handicap };
}

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type !== 'odds_update_realtime') return;

  msg.data.changedOdds.forEach(change => {
    switch (change.market) {
      case 'live1x2':
        const m1x2 = parse1x2(change.value);
        console.log(`1X2: ${m1x2.home} | ${m1x2.draw} | ${m1x2.away}`);
        break;

      case 'liveOU':
        const ou = parseOU(change.value);
        console.log(`O/U ${ou.line}: Over ${ou.over} | Under ${ou.under}`);
        break;

      case 'liveAH':
        const ah = parseAH(change.value);
        console.log(`AH (${ah.handicap}): ${ah.home} | ${ah.away}`);
        break;
    }
  });
};
```

***

### Comparison: ODDS vs ODDS\_REALTIME

| Feature           | ODDS          | ODDS\_REALTIME |
| ----------------- | ------------- | -------------- |
| Update frequency  | 15-30 seconds | Real-time      |
| Data sent         | Full snapshot | Delta only     |
| Bandwidth usage   | Higher        | Lower          |
| State management  | Not required  | Required       |
| Plan availability | ULTRA, MEGA   | MEGA only      |

### Best Practices

1. **Maintain local state**: Keep a local copy of odds and apply deltas
2. **Handle reconnections**: On reconnect, subscribe to ODDS first for a full snapshot, then switch to ODDS\_REALTIME
3. **Combine channels**: Use ODDS for initial state and ODDS\_REALTIME for updates
4. **Track history**: Store odds history if you need to analyze movement patterns
5. **Handle null values**: Some markets may not be available for all matches

### Notes

* Only changed markets are included in each message
* An empty `changedOdds` array means no changes (rare, but possible)
* For a complete snapshot, use the ODDS channel
* This channel requires client-side state management
* Odds changes can be frequent during live matches, especially near key events


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://info.soccerfootball.info/websocket/channels/odds-realtime.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
