Sports Odds Scraper: book-by-book betting odds avatar

Sports Odds Scraper: book-by-book betting odds

Pricing

from $0.005 / actor start

Go to Apify Store
Sports Odds Scraper: book-by-book betting odds

Sports Odds Scraper: book-by-book betting odds

Scrape pre-match betting odds bookmaker by bookmaker across seven sports: 1X2 or moneyline, Asian handicap and totals, with the event, league and start time.

Pricing

from $0.005 / actor start

Rating

0.0

(0)

Developer

Michal Pšenčík

Michal Pšenčík

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

Sports Odds Scraper (book-by-book pre-match odds)

What does Sports Odds Scraper do?

This Actor scrapes pre-match betting odds, one row per bookmaker, from BetExplorer, across seven sports: football, basketball, tennis, ice hockey, baseball, volleyball and handball. For every event it returns the sport, the league split into country and competition, the exact start time in UTC, the home and away sides, the event's status, a link back to the event page, a stable event id, the scrape timestamp, and then, for each bookmaker quoting it, the moneyline (1X2 with a draw on three-way sports, home/away on two-way ones), the spread (Asian handicap, with the handicap value) and the total (over/under, with the line).

Because every item carries a scrapedAt timestamp and a stable eventId, running it twice an hour apart gives you line movement without any extra work: join on eventId plus bookmaker and diff the prices.

You choose which country's bookmakers you get, by setting a country on Apify Proxy in proxyConfiguration. Ask for GB and you get the UK books (William Hill, bet365, Paddy Power, Betfred, Betway, bwin and the rest); ask for DE and you get the German ones. Full worked example in Choosing which bookmakers you get below.

Try it from the Input tab: leave everything at its default and hit Start for today's and tomorrow's football card with every bookmaker on it.

Why use Sports Odds Scraper?

  • Line shopping. One item holds every bookmaker's price for the same event, so the best available price and the spread between books fall straight out of the data.
  • Line movement and steam detection. Schedule it every few minutes and diff on scrapedAt. The Actor is cheap per run precisely so that repeated runs are affordable.
  • Arbitrage and value screens. Moneyline, Asian handicap and totals for the same event, from the same snapshot, in one row.
  • Model inputs. Closing odds are the standard benchmark for a sports model. Set status to all to pick up events that have already started or finished.
  • Any bookmaker market you want. Set a country on Apify Proxy and you get that country's licensed books: 15 of them on a GB run, against 4 on an unproxied one.
  • Seven sports from one Actor. No separate integration per sport; change the sport input.
  • No odds-feed contract. Commercial odds APIs are priced for sportsbooks. This reads a public comparison site.

How to use Sports Odds Scraper

  1. Click Try for free (or open the Actor in Apify Console).
  2. On the Input tab, pick a Sport.
  3. Set Days to the day offsets you want. [0, 1] is today and tomorrow, [-1] is yesterday. The source serves seven days either side of today.
  4. Pick the Markets you need. Dropping Spread and Total makes the run about three times cheaper in platform time; the moneyline is always included.
  5. Leave Event status on Scheduled for pre-match odds, or switch to All events for closing odds too.
  6. Set Maximum results to cap the run. The default is 50 events.
  7. Click Start. A 50-event football run takes about 15 seconds.
  8. Open the Output tab (or Storage → Dataset) and export as JSON, CSV, Excel or HTML, or pull it through the Apify API.

To track line movement, use Schedules in Apify Console to run the Actor on a fixed interval and let the dataset accumulate.

Input

All fields are optional; the defaults return today's and tomorrow's football card.

FieldTypeDefaultDescription
sportstringfootballOne of football, basketball, tennis, hockey, baseball, volleyball, handball. One run covers one sport.
daysarray[0, 1]Day offsets from today. 0 today, 1 tomorrow, -1 yesterday. Seven days either side of today are available.
marketsarray["moneyline","spread","total"]Which markets to return per bookmaker. moneyline is always included. Each of the other two adds one request per event.
statusstringscheduledOne of scheduled, all, live, finished. scheduled is what "pre-match" means.
maxItemsinteger50Stop after this many events with odds. 0 means no limit.
proxyConfigurationobjectApify proxy disabledOptional, but it is what selects the bookmaker market. See Choosing which bookmakers you get.

Example input:

{
"sport": "football",
"days": [0, 1],
"markets": ["moneyline", "spread", "total"],
"status": "scheduled",
"maxItems": 50
}

Output

Each event is one dataset item, with every bookmaker nested inside it. Download the dataset as JSON, HTML, CSV or Excel.

{
"eventId": "GzrJ32nL",
"sport": "football",
"country": "Spain",
"competition": "LaLiga",
"league": "Spain: LaLiga",
"home": "Real Sociedad",
"away": "Celta Vigo",
"startTime": "2026-09-03T19:00:00.000Z",
"status": "scheduled",
"eventUrl": "https://www.betexplorer.com/football/spain/laliga/real-sociedad-celta-vigo/GzrJ32nL/",
"moneylineType": "1x2",
"bookmakerCount": 4,
"bookmakers": [
{
"bookmaker": "BetMGM.us",
"moneyline": { "type": "1x2", "home": 1.77, "draw": 3.8, "away": 4.4 },
"spread": { "handicap": -0.5, "home": 1.7, "away": 2 },
"total": { "line": 2.5, "over": 1.77, "under": 1.95 }
},
{
"bookmaker": "Fanduel",
"moneyline": { "type": "1x2", "home": 1.77, "draw": 3.7, "away": 4.6 },
"spread": null,
"total": null
},
{
"bookmaker": "Stake.com",
"moneyline": { "type": "1x2", "home": 1.79, "draw": 3.8, "away": 4.6 },
"spread": { "handicap": -0.5, "home": 1.79, "away": 2.05 },
"total": { "line": 2.5, "over": 1.8, "under": 1.98 }
},
{
"bookmaker": "bet365.us",
"moneyline": { "type": "1x2", "home": 1.75, "draw": 3.9, "away": 4.75 },
"spread": { "handicap": -0.5, "home": 1.73, "away": 2.08 },
"total": { "line": 2.5, "over": 1.8, "under": 1.95 }
}
],
"scrapedAt": "2026-09-03T17:15:51.597Z"
}

A smaller competition is often quoted by one bookmaker, and a bookmaker that only posts a moneyline gets null for the markets it does not price:

{
"eventId": "YVt4vuKl",
"sport": "football",
"country": "Algeria",
"competition": "Ligue 1",
"league": "Algeria: Ligue 1",
"home": "El Biar",
"away": "Olympique Akbou",
"startTime": "2026-09-03T20:00:00.000Z",
"status": "scheduled",
"eventUrl": "https://www.betexplorer.com/football/algeria/ligue-1/js-el-biar-olympique-akbou/YVt4vuKl/",
"moneylineType": "1x2",
"bookmakerCount": 1,
"bookmakers": [
{
"bookmaker": "BetMGM.us",
"moneyline": { "type": "1x2", "home": 2.45, "draw": 2.87, "away": 2.7 },
"spread": null,
"total": { "line": 2.5, "over": 2.4, "under": 1.49 }
}
],
"scrapedAt": "2026-09-03T17:15:51.597Z"
}

On tennis, basketball, baseball and volleyball there is no draw, so moneylineType is home-away and draw is always empty.

Data fields

FieldTypeDescription
eventIdstringThe source's event id. Stable across days and reruns, so use it as your primary key.
sportstringThe sport this run covered.
countrystring | nullCountry or region of the competition, e.g. Spain.
competitionstring | nullCompetition name, e.g. LaLiga.
leaguestring | nullThe two joined as the source prints them, e.g. Spain: LaLiga.
homestringHome side.
awaystringAway side.
startTimestring | nullScheduled start, ISO 8601 in UTC.
statusstringscheduled, live or finished. Postponed and cancelled events count as finished.
eventUrlstringLink to the event page on BetExplorer.
moneylineTypestring1x2 on three-way sports, home-away on two-way ones.
bookmakerCountnumberHow many bookmakers quoted the event. Always 1 or more; unquoted events are not returned.
bookmakersarrayOne object per bookmaker, see below.
scrapedAtstringWhen this run read the odds, ISO 8601 in UTC. Diff on this to get line movement.

Each entry of bookmakers:

FieldTypeDescription
bookmakerstringBookmaker name as the source prints it.
moneylineobject | null{ type, home, draw, away } as decimal odds. draw is null on two-way sports.
spreadobject | null{ handicap, home, away }. handicap is applied to the home side: -0.5 means home gives half a goal.
totalobject | null{ line, over, under }, the over/under line and both prices.

All odds are decimal. Divide 1 by an odd to get the implied probability before the bookmaker's margin.

Choosing which bookmakers you get

The source shows a visitor the bookmakers licensed in their own country, and it decides that from the IP making the request. This Actor passes your proxy settings straight through, so the country you set on Apify Proxy is the bookmaker market you get back.

Set it in proxyConfiguration:

{
"sport": "football",
"days": [0, 1],
"markets": ["moneyline"],
"maxItems": 5,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "GB"
}
}

Three runs of the same fixture, Real Sociedad v Celta Vigo on 2026-09-03, differing only in that setting:

apifyProxyCountryBookmakers returned
none (Apify's own datacenter IP)Stake.com, BetMGM.us, bet365.us, Fanduel
GB10bet, 7BetUK, AllBritishCasino, BetUK, BetVictor, Betano.uk, Betfred, Betway, LeoVegasUK, Midnite, Paddy Power, Unibetuk, William Hill, bet365, bwin
DEBet365.de, Betano.de, Interwetten.de, Neobet, bet-at-home.de

The GB run is the one to copy if you want depth: 15 bookmakers on one event, quoting the home side anywhere between 1.73 and 1.80, which is exactly the spread a line-shopping screen exists to find. Note the price is still $0.0025 for that event, the same as the four-bookmaker one, because you are charged per event and not per quote.

Only GB and DE were tested through Apify Proxy. The mechanism is the same for any country code, but how deep the list goes is the source's business and varies a lot by market, as the GB and DE rows show. Running the same request from a Czech ISP (no proxy) returns Betano.cz, Chance.cz, iFortuna.cz and Tipsport.cz, which is the same behaviour arriving by a different route.

Two practical notes. Country selection needs Apify Proxy's residential group, which is metered by traffic on your Apify plan, so keep markets short and maxItems sensible when you use it. And if a country turns out to be served no bookmakers at all, every event is dropped and the run logs a warning naming this as the cause rather than failing silently.

How much does it cost to scrape betting odds?

This Actor uses pay per event pricing: $0.0025 per event returned, plus $0.005 per run start. Platform usage is included, so those two numbers are the whole bill.

An event here is a whole odds grid: every bookmaker, and up to three markets each. The run behind the examples returned 50 events carrying 92 bookmaker rows and 255 individual market quotes, for $0.13. Comparable Store Actors charge $0.0025 to $0.012 per odds row, so the same data costs an order of magnitude more there. A GB run widens that further, because 15 bookmakers on an event costs the same $0.0025 as 4 do.

You are never charged for an event no bookmaker quotes. Those are dropped before they reach the dataset, so maxItems counts events that actually carry odds.

To cap spending on a single run, set a maximum cost in the run options, or use maxItems.

Tips and advanced options

  • Line movement needs two runs, not a special setting. Schedule the same input every 5 or 15 minutes. Join the dataset on eventId + bookmaker and order by scrapedAt.
  • Cut the bill. Set markets to ["moneyline"] for a pure line-shopping feed. It is one request per event instead of three, and the item is smaller.
  • Closing odds. Set status to finished and days to [-1] for yesterday's closing prices.
  • One run covers many days. days: [0, 1, 2] costs one actor start, not three.
  • Which line you get on spreads and totals. Bookmakers quote a dozen handicaps and totals per event. The Actor publishes the main line: the one the most bookmakers quote on both sides, with ties going to the most balanced pair of prices. That is the line a comparison site shows by default.
  • Not every event has every market. Small competitions frequently have a moneyline and nothing else, and the matching fields come back null rather than guessed.
  • Pick the country before you pick the sport. A GB proxy turns a four-bookmaker event into a fifteen-bookmaker one at the same price per event, so it is the single biggest lever on how much data a run returns.

FAQ, disclaimers and support

Does this Actor need a login or an API key? No. It reads public pages, with no account of any kind.

Are the odds live in-play odds? No. These are the pre-match prices published for an upcoming event, which is what status: scheduled selects. With status: live you get events already under way, but the prices are still the ones the comparison site publishes, not a live in-play feed.

Why do two runs minutes apart show different prices? Because bookmakers move their lines. That is the point of scrapedAt. If the bookmakers themselves changed between two runs, that is the proxy country changing, not the odds: see Choosing which bookmakers you get.

Can I get a specific bookmaker, like bet365 or William Hill? Indirectly. Set the proxy country to a market that bookmaker is licensed in and it appears in bookmakers; there is no per-bookmaker filter, and filtering the output on your side is cheaper anyway, since the price is per event.

Are the odds decimal, American or fractional? Decimal, always, whatever the bookmaker's own site shows.

Is scraping betting odds legal? This Actor reads publicly available pages and collects match facts and published prices, not personal data. Scraping publicly accessible information is generally legal in the EU and the US, but you are responsible for how you use the output, including the source's Terms of Service and any database rights that apply where you operate, and for the gambling regulations in your jurisdiction. Talk to a lawyer if you plan to redistribute the data commercially.

Why do I get fewer events than I asked for? Events no bookmaker quotes are dropped and not billed, and maxItems caps the rest. Small tennis and basketball circuits in particular are often listed with no odds at all.

Found a bug, or need something else? Open an issue on the Issues tab of this Actor and it will be picked up. If you need a market this Actor does not return (double chance, both teams to score, draw no bet), a different sport, or every handicap line rather than the main one, say so in an issue.