arbplay

Fonbet Odds API

The ArbPlay Fonbet odds API serves Fonbet's own JSON over HTTPS as one combined file: every sport and competition Fonbet lists, live and pre-match together, rewritten every few seconds. Odds are keyed by numeric factor ids rather than market names; ids 921, 922 and 923 are the home, draw and away prices.

The data comes from Fonbet's Greek website.

Key facts

Fonbet odds API at a glance.
BookmakerFonbet (Greece)
Company keyfonbet
Files1: site_livepre_fonbet.json (live and pre-match together)
CoverageEvery sport and competition Fonbet lists — around 30 sports, live and pre-match
RefreshAbout every 1–3 s (live and pre-match in one file)
Odds formatDecimal (v), keyed by numeric factor id (f); lines in pt
Cross-bookmaker idNone — match on team1, team2 and startTime
Schemaevents[], sports[] (sports and competition segments), customFactors[] (odds per event), plus live eventMiscs[] and liveEventInfos[]
File sizeSeveral megabytes — use gzip and If-Modified-Since
AccessRapidAPI, Zyla API Hub or JoJ API listing, or a direct X-API-Key from ArbPlay

Files and what's inside

Every file is Fonbet's own JSON, served unchanged inside the API envelope. Refresh: about every 1–3 s (live and pre-match in one file).

FileWhat's insideRefresh
site_livepre_fonbet.jsonEvery Fonbet event of every sport, live (place: "live") and pre-match (place: "line"), with odds in customFactors≈1⁠–⁠3 s

Pre-match markets by sport

SportMarkets
SoccerEvery market Fonbet lists, keyed by numeric factor id; only 921 / 922 / 923 (home, draw, away) are documented here
BasketballEvery market Fonbet lists, by factor id (not documented here)
TennisEvery market Fonbet lists, by factor id (not documented here)

Every bookmaker compared: sports and markets per bookmaker.

Field map: where each value lives

Paths start at data. The same file holds live and pre-match events; place tells them apart.

ValuePath
Event idevents[].id
Teamsevents[].team1, .team2
Live or pre-matchevents[].place: live or line (pre-match)
Competitionsports[] where id == sportId → .name
Sportfollow sports[].parentId up to kind: "sport" → .alias (football, basketball…)
Start timeevents[].startTime (epoch seconds)
Match vs sub-eventlevel 1 = the match; 2–3 = sub-events (corners, cards…) linked by parentId
OddscustomFactors[] where e == id → factors[]: f factor id, v decimal odds, pt line
StatuseventBlocks[]: eventId with state blocked or partial (we don't document what a partial block covers)
Live score (live events)eventMiscs[] (score1, score2), liveEventInfos[] (timer, scores)

Real sample

An abridged record from site_livepre_fonbet.json: real values, most fields left out so the structure is readable. The downloads below keep every field.

{
  "sports": [
    {
      "id": 1,
      "kind": "sport",
      "name": "Football",
      "alias": "football"
    },
    {
      "id": 46065,
      "parentId": 1,
      "kind": "segment",
      "name": "UEFA Nations League. Division A. Group stage"
    }
  ],
  "events": [
    {
      "id": 67736383,
      "level": 1,
      "sportId": 46065,
      "team1": "Denmark",
      "team2": "Wales",
      "startTime": 1790524800,
      "place": "line"
    }
  ],
  "customFactors": [
    {
      "e": 67736383,
      "factors": [
        {
          "f": 921,
          "v": 1.45
        },
        {
          "f": 922,
          "v": 4.6
        },
        {
          "f": 923,
          "v": 6.9
        }
      ]
    }
  ]
}

Each download is a complete GET /v1/data/{filename} response cut down to a few events, with every id reference still resolving. All samples are listed in samples/index.json.

Extract match-result (1X2) odds in Python

This function is tested against the samples on this page. Pass it the parsed JSON response.

# Fonbet has no market names: odds are numeric factor ids per event.
# 921/922/923 = home / draw / away (inferred; checked against other books).
HOME, DRAW, AWAY = 921, 922, 923


def match_result(payload):
    """(event, 1, X, 2) rows for football matches in site_livepre_fonbet.json."""
    data = payload["data"]
    sports = {s["id"]: s for s in data.get("sports", [])}

    def sport_alias(segment_id):  # competition segment -> parent sport
        while segment_id in sports and sports[segment_id]["kind"] != "sport":
            segment_id = sports[segment_id].get("parentId")
        return sports.get(segment_id, {}).get("alias")

    factors = {cf["e"]: {f["f"]: f["v"] for f in cf["factors"]} for cf in data.get("customFactors", [])}
    rows = []
    for ev in data.get("events", []):
        odds = factors.get(ev["id"], {})
        if ev.get("level") == 1 and HOME in odds and sport_alias(ev["sportId"]) == "football":
            rows.append((f'{ev["team1"]} - {ev["team2"]}', odds.get(HOME), odds.get(DRAW), odds.get(AWAY)))
    return rows

Fetch Fonbet odds

With a direct key

# 1. which files can this key read?
curl -sS --compressed -H "X-API-Key: YOUR_API_KEY" \
  https://api.arbplay.app/v1/files

# 2. download one file (JSON envelope: company, file, updated_at, data)
curl -sS --compressed -H "X-API-Key: YOUR_API_KEY" \
  https://api.arbplay.app/v1/data/site_livepre_fonbet.json -o site_livepre_fonbet.json
import requests  # pip install requests

resp = requests.get(
    "https://api.arbplay.app/v1/data/site_livepre_fonbet.json",
    headers={"X-API-Key": "YOUR_API_KEY"},  # gzip is negotiated automatically
    timeout=60,
)
resp.raise_for_status()
payload = resp.json()
print(payload["updated_at"], payload["file"])
for event, home, draw, away in match_result(payload):  # the function above
    print(f"{event}: {home} / {draw} / {away}")
// Node 18+ (server-side: the API sends no CORS headers)
const res = await fetch("https://api.arbplay.app/v1/data/site_livepre_fonbet.json", {
  headers: { "X-API-Key": process.env.ARBPLAY_API_KEY },
});
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).detail}`);
const { company, file, updated_at, data } = await res.json();
console.log(file, "updated", updated_at);

Through a marketplace

On RapidAPI, Zyla API Hub or JoJ API you call the marketplace's gateway with that marketplace's key. The two endpoints and the JSON they return are the same; copy the base URL and path from the listing.

MarketplaceYour key goes inBase URL and full path
RapidAPIX-RapidAPI-Key and X-RapidAPI-HostEndpoints tab of the listing
Zyla API HubAuthorization: Bearer <access key>Code sample on the listing
JoJ APIX-JoJAPI-Key (or Authorization: Bearer)Code sample on the listing

Freshness, gaps and caveats

  • Refresh: about every 1–3 s (live and pre-match in one file). Every response carries updated_at and a Last-Modified header; send If-Modified-Since to get 304 Not Modified when nothing changed.
  • There are no market names in the file. Factor ids 921, 922 and 923 are home, draw and away — we verified them against other bookmakers' prices for the same matches. Other factor ids (totals, handicaps, double chance — they carry a line in pt) are not documented here.
  • Sub-events (level 2 and 3) share the match's teams and start time; filter on level == 1 for the match itself.
  • No Betradar id — cross-bookmaker matching needs team names and start time.
  • This is a large file: request it with Accept-Encoding: gzip and send If-Modified-Since.

Get Fonbet odds API access

Plans and quotas are set on each marketplace listing. More in the API reference and the API hub.

Frequently asked questions

Is this the official Fonbet API?

No. ArbPlay is independent and is not affiliated with or endorsed by Fonbet or its operator. It collects the odds Fonbet publishes on its public website and serves them unchanged as JSON for informational use. ArbPlay does not place bets.

Which Fonbet files can I download?

One: site_livepre_fonbet.json. It combines every sport, live and pre-match, in a single file; events[].place is live for in-play events and line for pre-match.

How do I read Fonbet odds without market names?

Each event's odds are in customFactors, keyed by numeric factor id. For a match (level 1), factor 921 is the home win, 922 the draw and 923 the away win; the decimal price is v and any line is in pt. We verified the 1X2 ids against other bookmakers' prices for the same matches.

How often are Fonbet odds updated?

The file is rewritten about every 1 to 3 seconds during active hours. Every response carries updated_at and a Last-Modified header, and If-Modified-Since returns 304 when nothing changed.

Can I match Fonbet events with other bookmakers?

Fonbet does not publish a Betradar id, so match on team1, team2 and startTime (epoch seconds). Normalise team names and allow a few minutes of start-time tolerance.

How do I get access to the Fonbet odds API?

Subscribe to the Fonbet listing on RapidAPI, Zyla API Hub or JoJ API and call it with that marketplace's key; plans and quotas are set on each listing. For a direct key to https://api.arbplay.app (header X-API-Key), contact ArbPlay.

ArbPlay is independent and not affiliated with or endorsed by Fonbet or its operator. Odds are collected from publicly available bookmaker odds and served unchanged for informational use; ArbPlay does not place bets. 21+.
Other bookmakers: Stoiximan · Novibet · Superbet · Elabet · OPAP · Bwin. Machine-readable: /openapi.json · /llms.txt. Guide: Greek bookmaker odds API.

Build on Fonbet odds

RapidAPI · Zyla API Hub · JoJ API · direct key