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
| Bookmaker | Fonbet (Greece) |
|---|---|
| Company key | fonbet |
| Files | 1: site_livepre_fonbet.json (live and pre-match together) |
| Coverage | Every sport and competition Fonbet lists — around 30 sports, live and pre-match |
| Refresh | About every 1–3 s (live and pre-match in one file) |
| Odds format | Decimal (v), keyed by numeric factor id (f); lines in pt |
| Cross-bookmaker id | None — match on team1, team2 and startTime |
| Schema | events[], sports[] (sports and competition segments), customFactors[] (odds per event), plus live eventMiscs[] and liveEventInfos[] |
| File size | Several megabytes — use gzip and If-Modified-Since |
| Access | RapidAPI, 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).
| File | What's inside | Refresh |
|---|---|---|
site_livepre_fonbet.json | Every 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
| Sport | Markets |
|---|---|
| Soccer | Every market Fonbet lists, keyed by numeric factor id; only 921 / 922 / 923 (home, draw, away) are documented here |
| Basketball | Every market Fonbet lists, by factor id (not documented here) |
| Tennis | Every 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.
| Value | Path |
|---|---|
| Event id | events[].id |
| Teams | events[].team1, .team2 |
| Live or pre-match | events[].place: live or line (pre-match) |
| Competition | sports[] where id == sportId → .name |
| Sport | follow sports[].parentId up to kind: "sport" → .alias (football, basketball…) |
| Start time | events[].startTime (epoch seconds) |
| Match vs sub-event | level 1 = the match; 2–3 = sub-events (corners, cards…) linked by parentId |
| Odds | customFactors[] where e == id → factors[]: f factor id, v decimal odds, pt line |
| Status | eventBlocks[]: 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
}
]
}
]
}
- site_livepre_fonbet.sample.json — trimmed to a few events
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.
| Marketplace | Your key goes in | Base URL and full path |
|---|---|---|
| RapidAPI | X-RapidAPI-Key and X-RapidAPI-Host | Endpoints tab of the listing |
| Zyla API Hub | Authorization: Bearer <access key> | Code sample on the listing |
| JoJ API | X-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_atand aLast-Modifiedheader; sendIf-Modified-Sinceto get304 Not Modifiedwhen 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 (
level2 and 3) share the match's teams and start time; filter onlevel == 1for 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: gzipand sendIf-Modified-Since.
Get Fonbet odds API access
- RapidAPI — Fonbet odds listing
- Zyla API Hub — Fonbet odds listing
- JoJ API — Fonbet odds listing
- Contact ArbPlay for a direct key to
https://api.arbplay.app - Before you buy: direct keys for several bookmakers, trial keys, rate limits and data rights
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.