{"id":3707,"date":"2026-09-02T10:00:00","date_gmt":"2026-09-02T10:00:00","guid":{"rendered":"https:\/\/oddspapi.io\/blog\/?p=3707"},"modified":"2026-09-07T14:01:45","modified_gmt":"2026-09-07T14:01:45","slug":"brasileirao-odds-api","status":"publish","type":"post","link":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/","title":{"rendered":"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals"},"content":{"rendered":"<p>Point a script at the Brasileir\u00e3o S\u00e9rie A board and 164 bookmakers come back on a single fixture. Ten of them are Brazilian. One of those ten, KTO, prices the three-way at a 4.05% margin and beats Pinnacle&#8217;s 4.66% across a full round.<\/p>\n<p>That result is real, and it is also a trap. KTO ships a byte-identical 1X2 to two Swedish operators on 10 of 10 fixtures. Dedupe the board first and the Brazilian set shrinks from ten brands to three prices.<\/p>\n<p>This post walks the whole pull in Python: tournament discovery, the round board, the dedupe pass, the margin ranking, and a coverage test that stops you concluding &#8220;Pinnacle does not price corners here&#8221; when it does. Every number below came off the free tier on 25 August 2026.<\/p>\n<h2>What you actually get, and what the raw board tells you<\/h2>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Question<\/th>\n<th>Raw board says<\/th>\n<th>After the checks in this post<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Books on one Brasileir\u00e3o fixture<\/td>\n<td>164<\/td>\n<td>88 independent prices (42.1% collapse)<\/td>\n<\/tr>\n<tr>\n<td>Brazilian books per fixture<\/td>\n<td>10 on 10 of 10<\/td>\n<td>3 priced independently<\/td>\n<\/tr>\n<tr>\n<td>Tightest Brazilian three-way<\/td>\n<td><code>kto<\/code> 4.05%, rank 4 of 160<\/td>\n<td>Shared feed. Real local best is <code>betano.bet.br<\/code> 4.78%<\/td>\n<\/tr>\n<tr>\n<td>Does Pinnacle price corners?<\/td>\n<td>Zero corner markets live<\/td>\n<td>8 corner families on 6 of 6 played fixtures<\/td>\n<\/tr>\n<tr>\n<td>Books on the following round<\/td>\n<td>8<\/td>\n<td>~5 independent, two of them placeholder-priced<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>OddsPapi aggregates 350+ bookmakers behind one JSON endpoint, and the free tier includes the historical price history that makes the coverage test below possible. Competitors charge for that history and carry roughly 40 books.<\/p>\n<h2>Step 1: Authentication<\/h2>\n<p>The API key is a query parameter. It is not a header, and code that sends it as one gets a 401.<\/p>\n<pre class=\"wp-block-code\"><code>import requests, time\n\nAPI_KEY = \"YOUR_API_KEY\"\nBASE_URL = \"https:\/\/api.oddspapi.io\/v4\"\n\ndef get(path, **params):\n    params[\"apiKey\"] = API_KEY\n    for _ in range(4):\n        r = requests.get(f\"{BASE_URL}{path}\", params=params, timeout=180)\n        if r.status_code == 200:\n            return r.json()\n        if r.status_code == 404:           # empty fixture window, not an error\n            return []\n        wait = r.json().get(\"error\", {}).get(\"retryMs\", 2000) \/ 1000\n        time.sleep(wait + 0.5)\n    r.raise_for_status()\n\nprint(len(get(\"\/sports\")), \"sports\")<\/code><\/pre>\n<p>The free tier rate-limits per endpoint and returns a structured 429 with a <code>retryMs<\/code> field. Honour it. Do not thread <code>\/odds<\/code> calls across fixtures, because concurrency at any worker count gets almost everything rejected.<\/p>\n<h2>Step 2: Find the Brasileir\u00e3o, past 18 decoys<\/h2>\n<p>Brazil lists 133 soccer competitions in the catalogue. Nineteen of them have &#8220;Serie A&#8221; in the name, and only six carry fixtures. A substring match picks up Ga\u00facho S\u00e9rie A2, four Paulista tiers, and a fistful of under-20 state leagues.<\/p>\n<pre class=\"wp-block-code\"><code>tours  = get(\"\/tournaments\", sportId=10)\nbrazil = [t for t in tours if t.get(\"categoryName\") == \"Brazil\"]\nserie_a = [t for t in brazil if \"serie a\" in t[\"tournamentName\"].lower()]\n\nprint(\"Brazil competitions:\", len(brazil))                              # 133\nprint(\"named 'Serie A':\", len(serie_a),                                 # 19\n      \"| with fixtures:\", sum(1 for t in serie_a if t.get(\"futureFixtures\")))   # 6\n\ntop = max(serie_a, key=lambda t: t.get(\"futureFixtures\") or 0)\nTOURNAMENT_ID = top[\"tournamentId\"]\nprint(TOURNAMENT_ID, top[\"tournamentName\"], top[\"futureFixtures\"])\n# 325 Brasileiro Serie A 142<\/code><\/pre>\n<p>Brasileir\u00e3o S\u00e9rie A is <strong><code>tournamentId<\/code> 325<\/strong>, slug <code>brasileiro-serie-a<\/code>, 142 future fixtures. S\u00e9rie B is 390 with 144. Read <code>futureFixtures<\/code> before you pick an ID, the same rule that applies to <a href=\"https:\/\/oddspapi.io\/blog\/us-open-odds-api\/\">Grand Slam tennis draws<\/a>.<\/p>\n<h3>Pull the round<\/h3>\n<pre class=\"wp-block-code\"><code>fixtures = get(\"\/fixtures\", sportId=10, tournamentId=TOURNAMENT_ID,\n               **{\"from\": \"2026-08-29\", \"to\": \"2026-09-01\"})\n\nfor f in fixtures:\n    print(f[\"fixtureId\"], f[\"startTime\"], f[\"participant1Name\"], \"v\", f[\"participant2Name\"])\n# 10 fixtures, 29-31 Aug<\/code><\/pre>\n<p>Two things bite here. The <code>to<\/code> parameter is a midnight-UTC instant, so set it to the day <em>after<\/em> your last match day or the final day looks empty. And an empty window returns HTTP 404 with a <code>FIXTURE_NOT_FOUND<\/code> body rather than an empty array, which kills any loop that calls <code>raise_for_status()<\/code>.<\/p>\n<h2>Step 3: Read the board and dedupe it<\/h2>\n<p>A no-filter <code>\/odds<\/code> call on a Brasileir\u00e3o fixture returns 15 to 20 MB. Across the 29 to 31 August round: <strong>median 164.5 books, 521,364 prices, 85.2% of them active, median 522 distinct market IDs per fixture<\/strong>.<\/p>\n<p>Prices live four levels down, and <code>active<\/code> sits on the price object rather than the outcome. Three guards belong in every parser: skip internal test feeds, skip suspended books, and require all three legs of the three-way.<\/p>\n<pre class=\"wp-block-code\"><code>import collections\n\nFIXTURE = \"id1000032566886958\"          # Flamengo v Palmeiras, 30 Aug 2026\nTEST_FEEDS = (\"demo\", \"pinnacle+\", \"singbet-b\")\n\ndef live_price(outcome):\n    \"\"\"Game lines sit under players['0']. Return the price only if it is active.\"\"\"\n    p = outcome.get(\"players\", {}).get(\"0\")\n    return p.get(\"price\") if p and p.get(\"active\") else None\n\nbooks = get(\"\/odds\", fixtureId=FIXTURE)[\"bookmakerOdds\"]\nprint(\"books in payload:\", len(books))                    # 164\n\nquotes = {}\nfor slug, book in books.items():\n    if slug.startswith(TEST_FEEDS) or book.get(\"suspended\"):\n        continue\n    market = book.get(\"markets\", {}).get(\"101\")            # Full Time Result\n    if not market:\n        continue\n    prices = [live_price(market[\"outcomes\"].get(str(o), {})) for o in (101, 102, 103)]\n    if any(p is None for p in prices):                     # partial or dead 1X2\n        continue\n    quotes[slug] = tuple(prices)\n\ngroups = collections.defaultdict(list)\nfor slug, tup in quotes.items():\n    groups[tup].append(slug)\n\nprint(\"complete live 1X2:\", len(quotes))                   # 152\nprint(\"independent quotes:\", len(groups))                  # 88\nprint(\"collapse: %.1f%%\" % (100 * (1 - len(groups) \/ len(quotes))))   # 42.1%<\/code><\/pre>\n<p>Sixty-four of the 152 quotes are duplicates of another slug. The largest group on this fixture runs 17 brands deep and includes <code>ballybet<\/code>, <code>betparx<\/code>, <code>casumo<\/code>, <code>fourwinds<\/code>, <code>grosvenor<\/code> and <code>jacks.nl<\/code>. None of them carries a <code>cloneOf<\/code> flag. The flag tracks catalogue lineage, not feed reality, so dedupe on the price tuple per fixture instead of trusting a static clone list.<\/p>\n<p>The <code>pinnacle+<\/code> guard matters more than it looks. <code>pinnacle<\/code>, <code>pinnacle+5<\/code> and <code>pinnacle+30<\/code> all shipped a 4.66% median margin over the round. Count them and you count Pinnacle three times.<\/p>\n<h2>Step 4: Rank the Brazilian books honestly<\/h2>\n<p>Sort the deduped quotes by bookmaker margin and the Brazilian brands land all over the table.<\/p>\n<pre class=\"wp-block-code\"><code>def margin(prices):\n    return (sum(1 \/ p for p in prices) - 1) * 100\n\nfor slug, tup in sorted(quotes.items(), key=lambda kv: margin(kv[1]))[:6]:\n    print(f\"{slug:22s} {tup} {margin(tup):5.2f}%\")<\/code><\/pre>\n<p>Across all ten fixtures, 160 books carried a complete live three-way on at least seven of them. Median margins:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Slug<\/th>\n<th>Median 1X2 margin<\/th>\n<th>Rank of 160<\/th>\n<th>Ships the same prices as<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>kto<\/code><\/td>\n<td>4.05%<\/td>\n<td>4<\/td>\n<td><code>atg.se<\/code>, <code>svenskaspel<\/code> (10\/10)<\/td>\n<\/tr>\n<tr>\n<td><code>pinnacle<\/code><\/td>\n<td>4.66%<\/td>\n<td>8<\/td>\n<td>Independent<\/td>\n<\/tr>\n<tr>\n<td><code>betano.bet.br<\/code><\/td>\n<td>4.78%<\/td>\n<td>12<\/td>\n<td><strong>Independent<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>superbet.bet.br<\/code><\/td>\n<td>5.27%<\/td>\n<td>18<\/td>\n<td><code>napoleonsports.be<\/code>, <code>superbet.ro<\/code>, <code>superbet.rs<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>betmgm.bet.br<\/code><\/td>\n<td>5.94%<\/td>\n<td>29<\/td>\n<td><code>expekt.dk<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>betboo.bet.br<\/code><\/td>\n<td>5.97%<\/td>\n<td>35<\/td>\n<td><code>betmgm<\/code>, <code>borgata<\/code>, <code>bwin<\/code> and 5 more<\/td>\n<\/tr>\n<tr>\n<td><code>betnacional<\/code><\/td>\n<td>5.99%<\/td>\n<td>46<\/td>\n<td><strong>Independent<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>stake.bet.br<\/code><\/td>\n<td>6.72%<\/td>\n<td>55<\/td>\n<td><code>bingoal.be<\/code> (9\/10)<\/td>\n<\/tr>\n<tr>\n<td><code>estrelabet<\/code><\/td>\n<td>7.44%<\/td>\n<td>92<\/td>\n<td><strong>Independent<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>bet365.bet.br<\/code><\/td>\n<td>8.94%<\/td>\n<td>111<\/td>\n<td><code>bet365<\/code> and 4 regional skins<\/td>\n<\/tr>\n<tr>\n<td><code>sportingbet.bet.br<\/code><\/td>\n<td>no three-way<\/td>\n<td>n\/a<\/td>\n<td>See below<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Ten Brazilian slugs, three Brazilian prices. KTO&#8217;s 4.05% is a genuine number and a genuine best-of-board price, and it is not a local price: ATG and Svenska Spel quote it to the decimal on every fixture in the round. The tightest independently-priced Brazilian book is <strong><code>betano.bet.br<\/code> at 4.78%<\/strong>, which sits 0.12 percentage points behind Pinnacle.<\/p>\n<p>That lands where the <a href=\"https:\/\/oddspapi.io\/blog\/la-liga-odds-api\/\">La Liga<\/a> and <a href=\"https:\/\/oddspapi.io\/blog\/serie-a-odds-api\/\">Serie A<\/a> boards landed. Locally licensed books turn up in force and none of them beats the sharp on the three-way. Brazil comes closer than Spain, Italy, Germany or France, and it still does not clear the bar.<\/p>\n<h3>Two slugs that look like the same book and are not<\/h3>\n<p><code>betano<\/code> and <code>betano.bet.br<\/code> are separate feeds with separate prices. The global brand posts 5.95% (rank 31); the Brazilian licence posts 4.78% (rank 12). Query the wrong one and you are 1.17 percentage points off on every fixture.<\/p>\n<h2>Step 5: Three catalogue traps that return silence<\/h2>\n<h3>The licensed brand is often a clone that never ships<\/h3>\n<p>Eleven slugs end in <code>.bet.br<\/code>, the suffix for a Brazilian federal licence. Two of the biggest are dead ends:<\/p>\n<pre class=\"wp-block-code\"><code>cat = {b[\"slug\"]: b for b in get(\"\/bookmakers\")}\nfor s in (\"kto\", \"kto.bet.br\", \"estrelabet\", \"estrelabet.bet.br\", \"pixbet\", \"blaze.bet.br\"):\n    b = cat[s]\n    print(f\"{s:20s} live={b['liveOdds']!s:5s} cloneOf={b['cloneOf']}\")\n\n# kto                  live=True  cloneOf=None\n# kto.bet.br           live=True  cloneOf=kto\n# estrelabet           live=True  cloneOf=None\n# estrelabet.bet.br    live=True  cloneOf=estrelabet\n# pixbet               live=True  cloneOf=bcgame\n# blaze.bet.br         live=True  cloneOf=blaze<\/code><\/pre>\n<p><code>kto.bet.br<\/code> and <code>estrelabet.bet.br<\/code> are flagged as clones of their parents, and clone-flagged slugs never appear in an <code>\/odds<\/code> payload. The feed ships under <code>kto<\/code> and <code>estrelabet<\/code>. Pixbet is stranger: it clones <code>bcgame<\/code>, and on this round <code>bcgame<\/code>, <code>betfury<\/code>, <code>blaze<\/code>, <code>gamdom<\/code>, <code>megadice<\/code> and <code>rainbet<\/code> all quoted one identical tuple.<\/p>\n<p>Filtering <code>\/odds<\/code> with <code>bookmakers=kto.bet.br<\/code> returns an empty payload, not an error. Check the slug against <code>\/bookmakers<\/code> before you build a pipeline on it.<\/p>\n<h3><code>liveOdds: false<\/code> means pre-match only<\/h3>\n<p><code>bet365.bet.br<\/code> and <code>betnacional<\/code> both carry <code>liveOdds: false<\/code>, and both quoted a complete three-way on all ten fixtures. The flag marks in-play coverage. Treat it as a pre-match book, not a missing one.<\/p>\n<h3>A book can carry 87 markets and skip the headline one<\/h3>\n<p><code>sportingbet.bet.br<\/code> appeared on 10 of 10 fixtures with 87 markets across 57 families, including totals, European handicaps, team totals and exact score. It priced the Full Time Result on none of them. Soccer keeps the three-way under a single market ID (101), so there is no second ID hiding the quote. Handle the gap rather than assuming a book that shows up prices the main line.<\/p>\n<h2>Step 6: Rank per market family, not per book<\/h2>\n<p>On six European competitions, sharp books price the Asian handicap tighter than their own three-way and soft books widen it. KTO breaks the pattern in the other direction.<\/p>\n<pre class=\"wp-block-code\"><code>MARKET_NAME = {str(m[\"marketId\"]): m[\"marketName\"] for m in get(\"\/markets\", sportId=10)}\n\nfor slug in (\"pinnacle\", \"kto\", \"betano.bet.br\", \"estrelabet\"):\n    book = books.get(slug)\n    three_way, handicaps = None, []\n    for market_id, market in book[\"markets\"].items():\n        prices = [p for p in (live_price(o) for o in market[\"outcomes\"].values()) if p]\n        if market_id == \"101\" and len(prices) == 3:\n            three_way = margin(prices)\n        elif MARKET_NAME.get(market_id) == \"Asian Handicap\" and len(prices) == 2:\n            handicaps.append(margin(prices))\n    print(f\"{slug:16s} 1X2 {three_way:5.2f}%  best AH {min(handicaps):5.2f}%  \"\n          f\"ratio {min(handicaps)\/three_way:.2f}x\")<\/code><\/pre>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Book<\/th>\n<th>Median 1X2<\/th>\n<th>Median best handicap<\/th>\n<th>Ratio<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>pinnacle<\/code><\/td>\n<td>4.66%<\/td>\n<td>3.40%<\/td>\n<td>0.73x<\/td>\n<\/tr>\n<tr>\n<td><code>sharpbet<\/code><\/td>\n<td>4.65%<\/td>\n<td>3.42%<\/td>\n<td>0.74x<\/td>\n<\/tr>\n<tr>\n<td><code>betano.bet.br<\/code><\/td>\n<td>4.78%<\/td>\n<td>3.69%<\/td>\n<td>0.77x<\/td>\n<\/tr>\n<tr>\n<td><code>kto<\/code><\/td>\n<td>4.05%<\/td>\n<td>5.36%<\/td>\n<td><strong>1.32x<\/strong><\/td>\n<\/tr>\n<tr>\n<td><code>superbet.bet.br<\/code><\/td>\n<td>5.27%<\/td>\n<td>6.52%<\/td>\n<td>1.24x<\/td>\n<\/tr>\n<tr>\n<td><code>estrelabet<\/code><\/td>\n<td>7.44%<\/td>\n<td>5.90%<\/td>\n<td>0.79x<\/td>\n<\/tr>\n<tr>\n<td><code>draftkings<\/code><\/td>\n<td>7.91%<\/td>\n<td>9.93%<\/td>\n<td>1.26x<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>KTO beats Pinnacle by 0.61 points on the three-way and loses to it by 1.96 points on the handicap. Whatever is behind that feed prices the market Brazilian recreational money uses and gives ground on the one it does not. Benchmark <a href=\"https:\/\/oddspapi.io\/blog\/why-sharps-bet-asian-handicap\/\">handicaps against a sharp<\/a> and shop three-ways separately.<\/p>\n<p>Pinnacle&#8217;s handicap ladder runs nine rungs on a Brasileir\u00e3o fixture, margin lowest near the true line at 3.41% and widening to 4.55% at the ends. Its <code>limit<\/code> field decodes to a flat base: <code>base = limit if price >= 2 else limit * (price - 1)<\/code> returned <strong>$300 on 89 of 90 rungs<\/strong> across the round. La Liga runs $1,500 and Serie A $1,000 at the same distance from kickoff, so Pinnacle takes a fifth of the position on Brazil that it takes on Spain.<\/p>\n<h2>Step 7: The coverage test that stops you publishing a false negative<\/h2>\n<p>Pinnacle priced <strong>zero corner markets<\/strong> on all ten upcoming fixtures. It would be easy to write &#8220;Pinnacle skips Brazilian corners&#8221; and ship it. That conclusion is wrong, and the reason is the clock.<\/p>\n<p>Test coverage on a fixture that has already been played. Live prices drop after the whistle, but <code>\/historical-odds<\/code> keeps the full menu.<\/p>\n<pre class=\"wp-block-code\"><code>import datetime as dt, statistics\n\nPLAYED  = \"id1000032566886948\"      # Cruzeiro v Flamengo, played 22 Aug 2026\nKICKOFF = dt.datetime.fromisoformat(\"2026-08-22T23:30:00+00:00\")\n\nmarkets = get(\"\/historical-odds\", fixtureId=PLAYED,\n              bookmakers=\"pinnacle\")[\"bookmakers\"][\"pinnacle\"][\"markets\"]\nprint(\"market IDs over the fixture's life:\", len(markets))     # 156\n\ndef family(name):\n    if \"Corner\" in name:  return \"corners\"\n    if \"Booking\" in name: return \"bookings\"\n    if name in (\"Full Time Result\", \"Asian Handicap\", \"Over Under Full Time\"):\n        return \"core\"\n    return \"derivatives\"\n\nopens = collections.defaultdict(list)\nfor market_id, market in markets.items():\n    group = family(MARKET_NAME.get(market_id, \"\"))\n    for outcome in market[\"outcomes\"].values():\n        for snapshots in outcome[\"players\"].values():\n            pre = [s for s in snapshots if\n                   dt.datetime.fromisoformat(s[\"createdAt\"].replace(\"Z\", \"+00:00\")) < KICKOFF]\n            if not pre:\n                continue\n            first = dt.datetime.fromisoformat(pre[0][\"createdAt\"].replace(\"Z\", \"+00:00\"))\n            opens[group].append((KICKOFF - first).total_seconds() \/ 86400)\n\nfor group in (\"core\", \"derivatives\", \"corners\", \"bookings\"):\n    print(f\"{group:12s} opened T-{max(opens[group]):.2f}d\")<\/code><\/pre>\n<pre class=\"wp-block-code\"><code>market IDs over the fixture's life: 156\ncore         opened T-6.03d\nderivatives  opened T-3.26d\ncorners      opened T-1.69d\nbookings     opened T-1.13d<\/code><\/pre>\n<p>Pinnacle priced <strong>8 corner families and 5 booking families on 6 of 6 played fixtures<\/strong> from that round: full-time and first-half corner totals, per-team corners, a corners handicap, bookings 1X2, a bookings handicap and bookings totals. It priced 156 market IDs across the fixture's life against the 36 visible live four days out.<\/p>\n<p>The wave is clean and it repeats. Core markets open around a week out, derivatives follow at three days, corners at 1.5 to 2.5 days, bookings inside 30 hours. European leagues open corners at almost exactly three days, so <strong>Brazil runs about a day later<\/strong>. A coverage audit at T-4d reports no corner data on the Brasileir\u00e3o and is wrong every time. Poll <a href=\"https:\/\/oddspapi.io\/blog\/corners-cards-odds-api\/\">side markets<\/a> from two days out.<\/p>\n<p>Live corner coverage on the round is deep once the window opens: 83 books on <code>Corners - Over Under Full Time<\/code>, 78 on <code>Corners - 1X2<\/code>, 70 on first-half corner totals. Cards stay narrow, with 14 books on <code>Player To Be Carded<\/code> and 10 on <code>Bookings - 1X2<\/code>.<\/p>\n<h2>Step 8: What the round after this one looks like<\/h2>\n<p>Books open the Brasileir\u00e3o one round at a time. The 29 to 31 August round carried 154 to 166 books per fixture. A 2 September fixture, three days later, carried eight.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Slug<\/th>\n<th>Markets<\/th>\n<th>1X2<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>superbet.bet.br<\/code><\/td>\n<td>137<\/td>\n<td>1.32 \/ 4.70 \/ 8.60<\/td>\n<\/tr>\n<tr>\n<td><code>napoleonsports.be<\/code><\/td>\n<td>65<\/td>\n<td>1.32 \/ 4.70 \/ 8.60<\/td>\n<\/tr>\n<tr>\n<td><code>superbet.ro<\/code><\/td>\n<td>118<\/td>\n<td>1.25 \/ 5.45 \/ 9.40<\/td>\n<\/tr>\n<tr>\n<td><code>superbet.rs<\/code><\/td>\n<td>126<\/td>\n<td>1.25 \/ 5.45 \/ 9.40<\/td>\n<\/tr>\n<tr>\n<td><code>superbet.pl<\/code><\/td>\n<td>112<\/td>\n<td>1.24 \/ 5.30 \/ 8.90<\/td>\n<\/tr>\n<tr>\n<td><code>bet99<\/code><\/td>\n<td>14<\/td>\n<td>1.263 \/ 5.75 \/ 11.00<\/td>\n<\/tr>\n<tr>\n<td><code>polymarket<\/code><\/td>\n<td>60<\/td>\n<td>1.22 \/ 2.174 \/ 2.381<\/td>\n<\/tr>\n<tr>\n<td><code>kalshi<\/code><\/td>\n<td>1<\/td>\n<td>1.25 \/ 1.538 \/ 1.493<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Five Superbet-family slugs, two of them identical, plus two prediction markets quoting nonsense. Kalshi's three legs sum to a 112% margin and Polymarket's to 62%, which is what an empty book looks like when it has posted a placeholder. Every one of these fixtures reports <code>hasOdds: true<\/code>. The flag says a book has touched the fixture, and it says nothing about depth.<\/p>\n<h2>Step 9: The payoff<\/h2>\n<p>Best price per outcome on the worked fixture, against Pinnacle:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Outcome<\/th>\n<th>Pinnacle<\/th>\n<th>Best on board<\/th>\n<th>Gain<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Flamengo<\/td>\n<td>1.408<\/td>\n<td>1.45 (<code>atg.se<\/code>)<\/td>\n<td>+2.98%<\/td>\n<\/tr>\n<tr>\n<td>Draw<\/td>\n<td>5.06<\/td>\n<td>5.333 (<code>apuestatotal<\/code>)<\/td>\n<td>+5.40%<\/td>\n<\/tr>\n<tr>\n<td>Palmeiras<\/td>\n<td>6.97<\/td>\n<td>8.30 (<code>balkanbet.rs<\/code>)<\/td>\n<td>+19.08%<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>The 19% on the away side is where a wide board earns its keep, and it is also where you check your work. Confirm the quote is <code>active<\/code>, confirm the book is not <code>suspended<\/code>, and confirm no other slug is shipping the same tuple. See <a href=\"https:\/\/oddspapi.io\/blog\/line-shopping-python-best-odds\/\">line shopping in Python<\/a> for the full best-price loop and <a href=\"https:\/\/oddspapi.io\/blog\/vig-calculator-python-sportsbook-margin\/\">the vig calculator<\/a> for the margin maths.<\/p>\n<h3>Player props<\/h3>\n<p>Brasileir\u00e3o prop coverage is the deepest of any league board measured: <strong>Anytime Goal Scorer on 91 books<\/strong>, First Goal Scorer 86, Player Goals 72, Last Goal Scorer 46, Player Assists 43, Shots on Goal totals 32. Prop markets key <code>players<\/code> by player ID rather than <code>\"0\"<\/code>, so the game-line parser above returns nothing on them. Iterate the dict and skip the <code>\"0\"<\/code> key.<\/p>\n<h2>The checklist<\/h2>\n<ol>\n<li>Resolve <code>tournamentId<\/code> 325 by <code>futureFixtures<\/code>, not by name.<\/li>\n<li>Set <code>to<\/code> on <code>\/fixtures<\/code> to the day after your last match day.<\/li>\n<li>Treat a 404 from <code>\/fixtures<\/code> as an empty window.<\/li>\n<li>Filter <code>demo<\/code>, <code>pinnacle+<\/code> and <code>singbet-b<\/code> out of any census.<\/li>\n<li>Test <code>active<\/code> on the price object, and <code>suspended<\/code> on the book.<\/li>\n<li>Dedupe on the price tuple per fixture. Ignore <code>cloneOf<\/code> for this.<\/li>\n<li>Check a slug exists before filtering on it. A missing slug returns empty, not an error.<\/li>\n<li>Rank margins per market family.<\/li>\n<li>Test coverage on a played fixture through <code>\/historical-odds<\/code>, never on an upcoming one.<\/li>\n<li>Sleep 1 second between same-endpoint calls, 4.5 seconds after <code>\/historical-odds<\/code>, and never parallelise.<\/li>\n<\/ol>\n<h2>FAQ<\/h2>\n<h3>What is the Brasileir\u00e3o tournament ID in the OddsPapi API?<\/h3>\n<p>Brasileir\u00e3o S\u00e9rie A is <code>tournamentId<\/code> 325 (slug <code>brasileiro-serie-a<\/code>) and S\u00e9rie B is 390. Nineteen Brazilian competitions have \"Serie A\" in the name, so resolve by <code>futureFixtures<\/code> rather than string matching.<\/p>\n<h3>Which Brazilian bookmakers ship live odds?<\/h3>\n<p>Ten appeared on every fixture of the 29 to 31 August 2026 round: <code>kto<\/code>, <code>betano.bet.br<\/code>, <code>superbet.bet.br<\/code>, <code>betmgm.bet.br<\/code>, <code>betboo.bet.br<\/code>, <code>betnacional<\/code>, <code>stake.bet.br<\/code>, <code>estrelabet<\/code>, <code>bet365.bet.br<\/code> and <code>sportingbet.bet.br<\/code>. Only <code>betano.bet.br<\/code>, <code>betnacional<\/code> and <code>estrelabet<\/code> price independently. The rest share a feed with a non-Brazilian brand.<\/p>\n<h3>Does any Brazilian bookmaker price tighter than Pinnacle?<\/h3>\n<p><code>kto<\/code> posts a 4.05% median three-way margin against Pinnacle's 4.66%, but it ships identical prices to <code>atg.se<\/code> and <code>svenskaspel<\/code> on every fixture, so it is not a locally-priced book. The tightest independent Brazilian quote is <code>betano.bet.br<\/code> at 4.78%, which is 0.12 points wider than Pinnacle.<\/p>\n<h3>Why does the API return no odds for kto.bet.br?<\/h3>\n<p><code>kto.bet.br<\/code> carries <code>cloneOf: kto<\/code>, and clone-flagged slugs never appear in an <code>\/odds<\/code> payload. The feed ships under the parent slug. The same applies to <code>estrelabet.bet.br<\/code> and <code>blaze.bet.br<\/code>. Filtering on a clone slug returns an empty payload rather than an error.<\/p>\n<h3>Does Pinnacle price corners on the Brasileir\u00e3o?<\/h3>\n<p>Yes. It prices 8 corner families and 5 booking families, verified on 6 of 6 played fixtures through <code>\/historical-odds<\/code>. Corner markets open 1.5 to 2.5 days before kickoff, so a live call four days out returns none of them.<\/p>\n<h3>How many bookmakers cover one Brasileir\u00e3o fixture?<\/h3>\n<p>A no-filter <code>\/odds<\/code> call returned 154 to 166 books per fixture across the round, with a median of 164.5 and 522 distinct market IDs. After deduping on the price tuple, 152 complete three-ways collapsed to 88 independent quotes.<\/p>\n<p><script type=\"application\/ld+json\">\n{\"@context\":\"https:\/\/schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[\n{\"@type\":\"Question\",\"name\":\"What is the Brasileir\u00e3o tournament ID in the OddsPapi API?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Brasileir\u00e3o S\u00e9rie A is tournamentId 325 (slug brasileiro-serie-a) and S\u00e9rie B is 390. Nineteen Brazilian competitions have 'Serie A' in the name, so resolve by futureFixtures rather than string matching.\"}},\n{\"@type\":\"Question\",\"name\":\"Which Brazilian bookmakers ship live odds?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Ten appeared on every fixture of the 29 to 31 August 2026 round: kto, betano.bet.br, superbet.bet.br, betmgm.bet.br, betboo.bet.br, betnacional, stake.bet.br, estrelabet, bet365.bet.br and sportingbet.bet.br. Only betano.bet.br, betnacional and estrelabet price independently.\"}},\n{\"@type\":\"Question\",\"name\":\"Does any Brazilian bookmaker price tighter than Pinnacle?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"kto posts a 4.05% median three-way margin against Pinnacle's 4.66%, but it ships identical prices to atg.se and svenskaspel on every fixture, so it is not a locally-priced book. The tightest independent Brazilian quote is betano.bet.br at 4.78%, which is 0.12 points wider than Pinnacle.\"}},\n{\"@type\":\"Question\",\"name\":\"Why does the API return no odds for kto.bet.br?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"kto.bet.br carries cloneOf: kto, and clone-flagged slugs never appear in an \/odds payload. The feed ships under the parent slug. The same applies to estrelabet.bet.br and blaze.bet.br.\"}},\n{\"@type\":\"Question\",\"name\":\"Does Pinnacle price corners on the Brasileir\u00e3o?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Yes. It prices 8 corner families and 5 booking families, verified on 6 of 6 played fixtures through \/historical-odds. Corner markets open 1.5 to 2.5 days before kickoff, so a live call four days out returns none of them.\"}},\n{\"@type\":\"Question\",\"name\":\"How many bookmakers cover one Brasileir\u00e3o fixture?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"A no-filter \/odds call returned 154 to 166 books per fixture across the round, with a median of 164.5 and 522 distinct market IDs. After deduping on the price tuple, 152 complete three-ways collapsed to 88 independent quotes.\"}}]}\n<\/script><\/p>\n<h2>Get the data<\/h2>\n<p>Every figure in this post came off the free tier, including the historical snapshots behind the open-clock study. The free key covers 350+ bookmakers, the full Brazilian licensed set, and price history with no extra charge. <a href=\"https:\/\/oddspapi.io\/\">Grab your free API key<\/a> and run the census on your own round.<\/p>\n<p>Next: <a href=\"https:\/\/oddspapi.io\/blog\/football-odds-api-soccer-data\/\">the general soccer odds API guide<\/a>, <a href=\"https:\/\/oddspapi.io\/blog\/odds-database-python-sqlite\/\">storing odds in SQLite<\/a>, or <a href=\"https:\/\/oddspapi.io\/blog\/brazil-betting-api-estrelabet-betano-brasileirao\/\">the Brazilian arbitrage scanner<\/a>.<\/p>\n<p><!--\nFocus Keyphrase: Brasileir\u00e3o odds API\nSEO Title: Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals\nMeta Description: Pull Brasileir\u00e3o odds from 164 bookmakers in Python. Betano is the tightest Brazilian book at 4.78%, 0.12 points behind Pinnacle on the same round.\nSlug: brasileirao-odds-api\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pull Brasileir\u00e3o odds from 164 bookmakers in Python. Betano is the tightest Brazilian book at 4.78%, 0.12 points behind Pinnacle on the same round.<\/p>\n","protected":false},"author":2,"featured_media":3708,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[8,9,11,15,10],"class_list":["post-3707","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to-guides","tag-free-api","tag-odds-api","tag-python","tag-soccer","tag-sports-betting-api"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals | OddsPapi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals | OddsPapi Blog\" \/>\n<meta property=\"og:description\" content=\"Pull Brasileir\u00e3o odds from 164 bookmakers in Python. Betano is the tightest Brazilian book at 4.78%, 0.12 points behind Pinnacle on the same round.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/\" \/>\n<meta property=\"og:site_name\" content=\"OddsPapi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-02T10:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-07T14:01:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1429\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Odds API Writer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/oddspapi.io\/logo-v2.webp\" \/>\n<meta name=\"twitter:creator\" content=\"@oddspapiapi\" \/>\n<meta name=\"twitter:site\" content=\"@oddspapiapi\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Odds API Writer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/\"},\"author\":{\"name\":\"Odds API Writer\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\"},\"headline\":\"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals\",\"datePublished\":\"2026-09-02T10:00:00+00:00\",\"dateModified\":\"2026-09-07T14:01:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/\"},\"wordCount\":1971,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp\",\"keywords\":[\"Free API\",\"Odds API\",\"Python\",\"Soccer\",\"Sports Betting API\"],\"articleSection\":[\"How To Guides\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/\",\"name\":\"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals | OddsPapi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp\",\"datePublished\":\"2026-09-02T10:00:00+00:00\",\"dateModified\":\"2026-09-07T14:01:45+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#primaryimage\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp\",\"width\":2560,\"height\":1429,\"caption\":\"Brasileir\u00e3o Odds API - OddsPapi API Blog\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/oddspapi.io\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#website\",\"url\":\"https:\/\/oddspapi.io\/blog\/\",\"name\":\"OddsPapi\",\"description\":\"Sports Odds API Tutorials &amp; Guides\",\"publisher\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\"},\"alternateName\":\"Odds Papi\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/oddspapi.io\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#organization\",\"name\":\"OddsPapi\",\"url\":\"https:\/\/oddspapi.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png\",\"contentUrl\":\"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png\",\"width\":135,\"height\":135,\"caption\":\"OddsPapi\"},\"image\":{\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/oddspapiapi\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13\",\"name\":\"Odds API Writer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g\",\"caption\":\"Odds API Writer\"},\"url\":\"https:\/\/oddspapi.io\/blog\/author\/andy-lavelle\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals | OddsPapi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/","og_locale":"en_US","og_type":"article","og_title":"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals | OddsPapi Blog","og_description":"Pull Brasileir\u00e3o odds from 164 bookmakers in Python. Betano is the tightest Brazilian book at 4.78%, 0.12 points behind Pinnacle on the same round.","og_url":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/","og_site_name":"OddsPapi Blog","article_published_time":"2026-09-02T10:00:00+00:00","article_modified_time":"2026-09-07T14:01:45+00:00","og_image":[{"width":2560,"height":1429,"url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp","type":"image\/webp"}],"author":"Odds API Writer","twitter_card":"summary_large_image","twitter_image":"https:\/\/oddspapi.io\/logo-v2.webp","twitter_creator":"@oddspapiapi","twitter_site":"@oddspapiapi","twitter_misc":{"Written by":"Odds API Writer","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#article","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/"},"author":{"name":"Odds API Writer","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13"},"headline":"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals","datePublished":"2026-09-02T10:00:00+00:00","dateModified":"2026-09-07T14:01:45+00:00","mainEntityOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/"},"wordCount":1971,"commentCount":0,"publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp","keywords":["Free API","Odds API","Python","Soccer","Sports Betting API"],"articleSection":["How To Guides"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/","url":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/","name":"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals | OddsPapi Blog","isPartOf":{"@id":"https:\/\/oddspapi.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#primaryimage"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#primaryimage"},"thumbnailUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp","datePublished":"2026-09-02T10:00:00+00:00","dateModified":"2026-09-07T14:01:45+00:00","breadcrumb":{"@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#primaryimage","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2026\/08\/brasileirao-odds-api-scaled.webp","width":2560,"height":1429,"caption":"Brasileir\u00e3o Odds API - OddsPapi API Blog"},{"@type":"BreadcrumbList","@id":"https:\/\/oddspapi.io\/blog\/brasileirao-odds-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/oddspapi.io\/blog\/"},{"@type":"ListItem","position":2,"name":"Brasileir\u00e3o Odds API: 164 Books, and Betano Leads the Locals"}]},{"@type":"WebSite","@id":"https:\/\/oddspapi.io\/blog\/#website","url":"https:\/\/oddspapi.io\/blog\/","name":"OddsPapi","description":"Sports Odds API Tutorials &amp; Guides","publisher":{"@id":"https:\/\/oddspapi.io\/blog\/#organization"},"alternateName":"Odds Papi","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/oddspapi.io\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/oddspapi.io\/blog\/#organization","name":"OddsPapi","url":"https:\/\/oddspapi.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png","contentUrl":"https:\/\/oddspapi.io\/blog\/wp-content\/uploads\/2025\/11\/oddspapi.png","width":135,"height":135,"caption":"OddsPapi"},"image":{"@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/oddspapiapi"]},{"@type":"Person","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/b6f21e649c4f556f0a95c23a0f1efa13","name":"Odds API Writer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/oddspapi.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/33b204f24af3d02e35b25ae730c0536121ca6a783fdb196e7611c9e49fcd13eb?s=96&d=mm&r=g","caption":"Odds API Writer"},"url":"https:\/\/oddspapi.io\/blog\/author\/andy-lavelle\/"}]}},"_links":{"self":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3707","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/comments?post=3707"}],"version-history":[{"count":3,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3707\/revisions"}],"predecessor-version":[{"id":3890,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/posts\/3707\/revisions\/3890"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media\/3708"}],"wp:attachment":[{"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/media?parent=3707"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/categories?post=3707"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/oddspapi.io\/blog\/wp-json\/wp\/v2\/tags?post=3707"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}