Bookmakers pay to acquire customers. In the UK a new account is worth so much to them that “Bet £10, get £30 in free bets” is a normal sign-up offer, and there are dozens of licensed bookies and casinos competing with offers like it. Bookies price those offers expecting you to gamble the free bets away and keep betting for years.
Matched betting takes the bonus without gambling. Every bet you place at the bookmaker (a “back” bet) gets cancelled out by an opposite “lay” bet on a betting exchange like Betfair or Smarkets. Whatever happens in the match, you end up roughly flat on the qualifying bet, then you do the same thing with the free bet and keep around 70 to 80% of its face value as cash.
It is legal in the UK, and HMRC does not tax gambling winnings for individuals. Bookies hate it and will restrict (“gub”) your account once they notice. That tension is the whole game: extract as much as possible before you get limited.
This guide covers the math, a Python scanner that finds the best back/lay matches using The Odds API, a real cost and earnings breakdown, and the risks, including the one most guides skip: this only works if you legally live in a country where it works.
Who this works for (read first)
- UK: the best market by far. Lots of licensed bookies, big sign-up offers, liquid exchanges, tax-free winnings.
- Ireland: works, but the Gambling Regulation Act 2024 restricts inducements and the rules are phasing in. Expect fewer, smaller offers.
- Australia: most states now restrict sign-up inducements. Thin pickings.
- US: state-by-state. Some people do it with sportsbook promos in legal states, but exchanges are few and thin (Prophet and Sporttrade in a handful of states, plus newer CFTC-regulated prediction markets), so most people hedge between sportsbooks instead and lose more on each offer.
- Indonesia and most of Southeast Asia: online gambling is illegal (in Indonesia under the ITE Law, Article 27(2) as amended by UU 1/2024, plus the new KUHP’s gambling articles 426 and 427, in force since 2 January 2026). Do not do this from here. Using a VPN to open UK accounts also fails at KYC: UK bookies verify your ID, address and a UK bank account, and when they catch a non-resident they void winnings and keep the balance. If you are not a resident of a country where this is legal, stop here. The scanner code is still useful for learning odds APIs, but do not place bets.
How the money works
The qualifying bet
You back Team A at a bookmaker at decimal odds 3.0 with £10. On the exchange, you lay Team A (you act as the bookmaker and bet against it) at 3.1, with 2% commission.
The lay stake that balances both outcomes:
lay_stake = back_stake × back_odds / (lay_odds − commission)
= 10 × 3.0 / (3.1 − 0.02) = £9.74
- Team A wins: bookie pays +£20.00, you lose the lay liability £9.74 × 2.1 = −£20.45. Net −£0.45.
- Team A does not win: you lose your £10 at the bookie, the exchange pays £9.74 minus 2% = +£9.55. Net −£0.45.
You lose 45p either way. That is the “qualifying loss”, and it unlocks £30 in free bets.
The free bet
Free bets are usually “stake not returned” (SNR): if a £10 free bet wins at 6.0, you get £50, not £60. So the formula changes:
lay_stake = free_bet × (back_odds − 1) / (lay_odds − commission)
Free bets convert best at higher odds (roughly 4.0 to 8.0). Example: £30 free bet, back at 6.0, lay at 6.2, 2% commission:
lay_stake = 30 × 5 / (6.2 − 0.02) = £24.27
- Back wins: +£150 from the bookie, −£24.27 × 5.2 = −£126.21 on the exchange. Net +£23.79
- Back loses: £0 at the bookie, +£24.27 × 0.98 = +£23.78. Net +£23.78
Offer total: −£0.45 + £23.78 = £23.33 locked in, whatever the result. Repeat across every bookie.
What you need
| Item | Cost | Notes |
|---|---|---|
| Betting exchange account | Free | Smarkets (2% commission) or Betfair Exchange (2%, 5% or 8% depending on the rewards tier you choose; 5% is the usual default). Open both, use whichever has the better lay price |
| Bookmaker accounts | Free | One per bookie, in your own name, verified with your own ID and bank card |
| Bankroll | £200 minimum, £1,000 comfortable | Lay bets need liability. Laying £24 at 6.2 ties up £126 until the match ends |
| The Odds API key | Free (500 credits/month), paid from $30/month (20,000 credits) | About 20 UK bookmakers plus Betfair, Smarkets and Matchbook. The free plan covers “most” bookmakers, not all: check their bookmaker list |
| Python 3.10+ | Free | pip install requests |
| Separate bank account | Free | Keeps betting transactions off your main account (matters for mortgages, see risks) |
| Spreadsheet | Free | Track every offer, bet and balance. Non-negotiable |
| Paid matched betting site (optional) | ~£25 to £30/month | OddsMonkey, Outplayed and similar: offer calendars, oddsmatchers, step-by-step guides. Worth it after the easy sign-ups if you want reload offers without hunting them yourself |
Time: about 30 to 60 minutes per sign-up offer at first, 10 to 15 minutes once you know the routine.
Step 1: Get an API key and see what is covered
Sign up at the-odds-api.com, grab the key from the email, then list the sports that currently have markets:
export ODDS_API_KEY="your_key_here"
curl -s "https://api.the-odds-api.com/v4/sports?apiKey=$ODDS_API_KEY" \
| python3 -c "import sys,json; [print(s[\"key\"], \"-\", s[\"title\"]) for s in json.load(sys.stdin) if s[\"active\"]]"
You will see keys like soccer_epl, soccer_efl_champ, tennis_atp_..., basketball_nba. Listing sports does not cost credits. Pulling odds costs 1 credit per market per region. Exchange lay prices come back automatically with h2h under a separate h2h_lay market key, so one h2h request in the uk region costs 1 credit and gives you both back and lay prices. On the free plan that is up to 500 scans a month (requests that return no events are free), plenty for sign-up offers.
Step 2: The scanner
Save as scanner.py. It pulls odds for one sport, finds the best back price at each bookie and the best lay price on any exchange for every outcome, then works out the qualifying loss for a £10 bet and the profit from a £30 SNR free bet.
import os
import sys
import requests
API = "https://api.the-odds-api.com/v4/sports/{sport}/odds"
KEY = os.environ["ODDS_API_KEY"]
# Exchange commission rates. Check your own account: Betfair varies by market.
EXCHANGES = {"betfair_ex_uk": 0.05, "smarkets": 0.02, "matchbook": 0.02}
def qualifying_loss(stake, back, lay, comm):
lay_stake = stake * back / (lay - comm)
return stake * (back - 1) - lay_stake * (lay - 1), lay_stake
def free_bet_profit(fb, back, lay, comm):
lay_stake = fb * (back - 1) / (lay - comm)
return lay_stake * (1 - comm), lay_stake, lay_stake * (lay - 1)
def scan(sport, min_odds=1.5, max_odds=10.0):
r = requests.get(API.format(sport=sport), params={
"apiKey": KEY,
"regions": "uk",
"markets": "h2h", # lay prices arrive automatically as h2h_lay
"oddsFormat": "decimal",
}, timeout=20)
r.raise_for_status()
print(f"credits remaining: {r.headers.get('x-requests-remaining')}")
rows = []
for event in r.json():
backs, lays = {}, {}
for bm in event["bookmakers"]:
for market in bm["markets"]:
for o in market["outcomes"]:
name, price = o["name"], o["price"]
if market["key"] == "h2h" and bm["key"] not in EXCHANGES:
backs.setdefault(name, []).append((price, bm["title"]))
elif market["key"] == "h2h_lay" and bm["key"] in EXCHANGES:
comm = EXCHANGES[bm["key"]]
# effective lay odds after commission: lower is better
eff = 1 + (price - 1) / (1 - comm)
best = lays.get(name)
if best is None or eff < best[3]:
lays[name] = (price, comm, bm["title"], eff)
for name, lay in lays.items():
lay_odds, comm, exch, _ = lay
for back_odds, book in backs.get(name, []):
if not min_odds <= back_odds <= max_odds:
continue
ql, _ = qualifying_loss(10, back_odds, lay_odds, comm)
fb, fb_lay, liab = free_bet_profit(30, back_odds, lay_odds, comm)
rows.append({
"match": f"{event['home_team']} v {event['away_team']}",
"start": event["commence_time"][:16],
"pick": name, "book": book, "back": back_odds,
"exch": exch, "lay": lay_odds,
"rating": back_odds / lay_odds * 100,
"ql10": ql, "fb30": fb, "liab": liab,
})
return rows
if __name__ == "__main__":
sport = sys.argv[1] if len(sys.argv) > 1 else "soccer_epl"
book_filter = sys.argv[2].lower() if len(sys.argv) > 2 else ""
rows = [x for x in scan(sport) if book_filter in x["book"].lower()]
rows.sort(key=lambda x: x["rating"], reverse=True)
print(f"{'match':32} {'pick':18} {'book':14} {'exch':10} back lay rating QL£10 FB£30 liab")
for x in rows[:20]:
print(f"{x['match'][:32]:32} {x['pick'][:18]:18} {x['book'][:14]:14} {x['exch'][:10]:10} "
f"{x['back']:<5} {x['lay']:<5} {x['rating']:6.1f}% "
f"{x['ql10']:6.2f} {x['fb30']:6.2f} {x['liab']:6.0f}")
Run it:
pip install requests
python3 scanner.py soccer_epl # every covered bookie
python3 scanner.py soccer_epl "william" # only matches at one bookie
Rating is back odds divided by lay odds. 100% means the bookie price is as good as the exchange: no qualifying loss before commission. Above 100% is an arb (rare, and it usually disappears within minutes). For qualifying bets look for 95%+. For free bets, sort by the FB£30 column instead and stay in the 4.0 to 8.0 back-odds range where liability is manageable.
The liab column is the cash the exchange will lock up. If it is bigger than your exchange balance, you cannot place the lay, so skip it.
Step 3: Run your first offer (the exact routine)
- Pick one bookie with a simple “bet X, get Y in free bets” offer. Read the full terms: minimum odds (often evens, 2.0), qualifying markets, free bet expiry (usually 7 days), whether free bets are SNR.
- Open and verify the account in your own name. Deposit by debit card. Many bookies exclude e-wallets (PayPal, Skrill) from welcome offers. Check the terms.
- Run the scanner filtered to that bookie. Pick a match starting within a few hours, back odds above the minimum, rating 95%+.
- Check the price live on both sites. API odds can be a few minutes old. If the lay price moved, recalculate with the formulas above.
- Place the back bet first, then the lay bet immediately. If the lay price drifts while you do it, take the small hit rather than waiting.
- Wait for the free bet to credit (sometimes after the qualifying bet settles).
- Convert the free bet: rerun the scanner, sort by
FB£30, use the bookie that gave you the free bet, back + lay at 4.0 to 8.0. - Log everything in the spreadsheet: bookie, date, stakes, odds, P/L, balances. Withdraw your winnings from the bookie once the offer is done.
Do one offer end to end before you open a second account.
Honest cost breakdown
| Item | Month 1 | Ongoing |
|---|---|---|
| The Odds API | $0 (free tier) | $0 to $30 |
| Matched betting site | £0 (optional) | £0 to £30 |
| Qualifying losses | ~£0.30 to £1 per offer | same |
| Bankroll | £200 to £1,000 (tied up, not spent) | same |
| Cash cost | under £20 | £0 to £55 |
The real cost is time and the bankroll you lock up.
Realistic earnings
- Sign-up offers: one offer like the example above nets about £20 to £25. UK matched betting communities commonly report £500 to £1,000+ total from working through the sports and casino welcome offers. This is one-off money per person. Once you have signed up everywhere, it is gone.
- Reload offers (weekly free bets, acca insurance, price boosts, “bet £X get £Y” for existing customers): community reports vary widely, typically a few hundred pounds a month for someone putting in 1 to 2 hours a day, and it shrinks as accounts get gubbed. Treat any specific monthly figure you read (including in paid-site marketing) as a best case.
- Casino offers: riskier because they involve expected value rather than locked-in profit. Some months up, some down. UKGC rules that took effect on 19 January 2026 cap bonus wagering requirements at 10x, which makes them more attractive than they were. The same rules ban mixed-product offers (for example “bet on football, get free spins”), so sports and casino welcome offers are now separate.
- Advanced (where the bigger numbers live): experienced people move to value betting and arbing: betting when a bookie price is above the “true” price (estimated from the exchange or sharp books). This is where the bigger claimed numbers come from, but none of them are verifiable, it needs a bankroll in the thousands, it has real variance (losing weeks and months), and accounts get limited much faster than with plain matched betting.
Bottom line: a few hundred pounds, up to around £1,000, from sign-ups in the first two to three months is realistic if you are thorough. £5,000 a month from plain matched betting is not. Treat it as a high-paying side hustle with a built-in expiry date, and put the profit into something that scales.
Risks: gubbing, ToS and the stuff nobody tells you
Gubbing. Bookies profile accounts. Bet only on promos, always at exchange-matched prices, odd stakes like £17.43, withdraw right after: you get restricted fast. Restrictions range from “promotions no longer available” to stake limits of a few pence. It is not illegal and they can still keep your account open, but your offers stop.
How matched bettors slow it down (this breaks no law, but it is what bookies are trying to detect):
- Round stakes (£10, £25), even if the match is slightly worse.
- Bet on popular markets (Premier League match odds, big horse races), not obscure ones.
- Place an occasional small normal bet (“mug bet”) without an offer attached.
- Do not withdraw every penny the moment an offer finishes.
Multi-accounting and “gnoming”. The only way to scale past one person is more people, and that is where it stops being grey. Opening accounts in a partner or friend’s name and running them yourself breaks every bookie’s terms (one account per person, often per household or IP), and bookies void the winnings and keep the money. Using someone’s identity to open an account is fraud. The legal version: a family member opens and operates their own accounts with their own money and ID. You can teach them; you cannot run them.
Mortgages and loans. UK lenders read your bank statements. Dozens of gambling transactions can get an application questioned or declined even if you are profitable. Use a separate account, and stop at least three to six months before you apply.
Execution mistakes are your biggest risk. Wrong lay stake, laying the wrong team, back bet voided but lay bet stands, price moved before you laid: one mistake can cost more than five offers make. Always double-check before you press confirm.
Problem gambling. You are depositing into gambling sites daily. If you catch yourself placing unmatched bets “just this once” to recover a loss, stop. GamStop (UK) self-exclusion takes five minutes.
Reality check: what does not work
- “Free money forever.” Sign-up offers run out and reload income shrinks as you get gubbed. Most people’s monthly numbers drop after six months.
- Using a VPN or a fake UK address. KYC (ID, proof of address, bank account in your name) catches it, usually at the first withdrawal, and that is when they keep your balance.
- Trusting stale API odds. The free tier is fine for finding candidates, not for executing. Always confirm prices on both sites.
- Thin bankrolls. With £100 you will skip half the offers because you cannot cover liability.
- Skipping the terms. “Free bet credited only if the qualifying bet loses”, “excludes e-wallet deposits”, “min odds 1.5 per leg”: missed terms cost you the whole offer.
- Fully automating bet placement. Most bookie terms ban bots and automated betting, and auto-betting is a fast way to get closed. Automate the scanning and maths, not the clicks.
- Scaling with other people’s accounts. Covered above. That is the line between grey and fraud.
Start today
- Confirm you legally live in a country where this is allowed (UK is the easy case).
- Get a free The Odds API key (and open a Smarkets account once you are ready to bet).
- Run
scanner.pyon tonight’s football to get a feel for ratings and liability. No money needed. - Pick one bookie, read the terms, and run one full offer.
- Log it, withdraw, and repeat with the next bookie.
The scanner costs nothing to run. The first £20 tells you whether this is worth your next hundred hours.