- Why Python for a Betfair bot
- Prerequisites and account setup
- Step 1 — Logging in with the betfairlightweight library
- Step 2 — Reading market prices
- Step 3 — Placing a back and a lay
- Step 4 — A complete strategy loop
- Step 5 — Risk controls that save you
- Step 6 — Hosting on a VPS so it doesn't die
- Step 7 — Backtesting before going live
- Mistakes that cost money
- FAQ
Why Python for a Betfair bot
This article sits inside our wider Betfair Automation and Bots pillar, which covers the full landscape — when to automate, who shouldn't, what the off-the-shelf tools are good for, the rules-and-triggers model, the risks and the realistic returns. If you're not yet sure whether automation is right for you, read is bot trading worth it first. This piece is the hands-on Python build.
Python is the dominant language for retail Betfair automation for three reasons. First, the community: there's a mature open-source library called betfairlightweight that wraps the Betfair API into ordinary Python calls — login, list_market_catalogue, list_runner_book, place_orders. Second, the iteration speed: you can write, test and tweak a strategy in a Jupyter notebook faster than in any compiled language. Third, the ecosystem: pandas, NumPy and scikit-learn make analysing historical Betfair data trivial once you've extracted it.
The trade-off is speed. Python is not the language you'd pick for sub-50ms scalping. If you're trying to compete with HFT bots on pre-off horse racing scalps, you'll lose to C++ on the same VPS. For most retail strategies — lay the draw, pre-race trading with one-second decisions, in-play swing trading — Python is comfortably fast enough.
For a head-to-head against off-the-shelf bots like Bet Angel Guardian, see our best Betfair bots 2026 ranking. For the underlying execution model that every bot uses, see automation rules and triggers.
Prerequisites and account setup
Before any code, you need:
- A funded Betfair Exchange account. Open Betfair Account → if you don't have one. Verification can take 24–48 hours.
- A Betfair API App Key. Apply through your account: My Account → API Apps. There are two keys: a "delayed" key (free, prices delayed 1 second) and a "live" key (£299 one-off fee, real-time). Build with the delayed key, switch when your strategy is profitable.
- A non-interactive (NI) certificate pair so your bot can log in without going through 2FA every time. Generate the certs with OpenSSL and upload the public certificate to Betfair via My Account → Security → My Security Keys.
- Python 3.10 or newer. Install betfairlightweight, requests, pandas with pip.
- A .env file with your username, password, app key and the paths to the two certificate files. Never commit this file to git.
The single biggest unforced error in retail Betfair bots is committing the .env file or hard-coded credentials to a public GitHub repo. Bots have been drained inside 30 minutes of a push. Add .env to .gitignore the moment you create the file.
Step 1 — Logging in with the betfairlightweight library
The first script connects to Betfair, gets a session token, and prints your account balance. If this works, the rest is detail.
The conceptual flow is: instantiate an APIClient with your username, password, app key and certificate paths; call .login(); on success the client holds a token in memory and uses it on every subsequent call. Tokens expire after roughly 24 hours of inactivity or after eight hours of activity — wrap calls in a try/except that re-logs in on APIError NO_SESSION.
If the login fails with INVALID_USERNAME_OR_PASSWORD the most common cause is your IP being outside the country your account is registered in. If you're hosting the bot on AWS Frankfurt, register the bot account in Ireland not the UK. If the failure is CERT_AUTH_REQUIRED, the certificate hasn't propagated yet — Betfair takes up to four hours to register a new public key.
Step 2 — Reading market prices
Once logged in, you can ask Betfair for a list of markets, then ask for the price book of any market. There are two API endpoints worth knowing: list_market_catalogue (slower, returns metadata — names, start times, runner IDs) and list_market_book (fast, returns prices and traded volume for a given market ID).
Build your bot so the catalogue call happens once an hour and the book call happens in your fast inner loop. Calling the catalogue every second will get you rate-limited and eventually banned.
| marketId | 1.249118402 | 3.30 Newmarket 2m hurdle |
| selectionId | 37456217 | Tarnhelm |
| lastPriceTraded | 3.40 | £412 matched at this price |
| availableToBack | 3.40 | £86 available |
| availableToLay | 3.45 | £124 available |
| totalMatched | £18,420 | Liquid enough to trade |
The data you'll use 80% of the time: lastPriceTraded (LTP — the price of the most recent matched bet), availableToBack (the best lay-side price and stake size queued), availableToLay (the best back-side price), and totalMatched (a liquidity measure). For the ladder mechanics in detail, see our how to read the Betfair market guide.
Polling rate: list_market_book has a per-request weight cost. The current limit is 200 weight per second per app key, and a normal market_book call costs 1 weight. So you can call ~5 markets every second per app key without paying for streaming. Anything heavier and you need the Streaming API, which is push-based and free of the weight tax — but is a different code path.
Step 3 — Placing a back and a lay
Bets are placed via place_orders. Each order needs: marketId, selectionId, side (BACK or LAY), order type (LIMIT for most strategies), price, size, and a persistence type (LAPSE — cancel at off; PERSIST — keep into in-play; MARKET_ON_CLOSE — match at SP).
The response includes a betId which you keep for cancelling later, and a sizeMatched. If sizeMatched is less than your requested size, the rest is still in the queue waiting to be matched — your order is partially filled.
To lay £20.36 at 3.35 (the green-up bet that locks in profit if the favourite shortens further), the only change is side="LAY". Note that on a lay, the liability is (price - 1) × size — laying £20.36 at 3.35 risks £47.85, not £20.36. Get this maths wrong in your bankroll calculations and you'll wonder why the bot keeps blowing up. The arithmetic of green-up is in green up explained.
For pre-off strategies, always set persistenceType=LAPSE. If your bot crashes and your unmatched LAY at 3.35 sits there at the off, it goes into in-play and could match at a much higher price if the favourite drifts. LAPSE cancels the bet at the off — cheap insurance against your own crash.
Step 4 — A complete strategy loop
A working bot is not just login + read + place. It's a loop that watches markets, decides to enter, places the bet, waits, watches for the exit, places the green-up, and logs the result. A simple version for pre-race scalping:
- Every 60 seconds, get the list of today's UK horse races starting in the next 30 minutes.
- For each race, in the 15-minute window before the off, poll the favourite's price every 2 seconds.
- If LTP drops 2 ticks in 30 seconds and matched volume in that window is over £2,000, place a BACK at LTP for £20.
- The moment the back is matched, place a LAY at LTP+1 tick for the same stake. This is the take-profit.
- If the LAY hasn't matched after 90 seconds, cancel it and place a LAY at LTP-1 tick. This is the stop-loss.
- Log entry price, exit price, P&L, time held, market ID.
This is roughly 80 lines of Python. The structure that matters is the state machine: a market goes from WATCHING → ENTRY_PLACED → IN_TRADE → EXIT_PLACED → CLOSED. Each call from the API updates the state; rule logic depends on the current state. The same model is described from the tool side in automation rules and triggers.
Twenty pence sounds like nothing. Run that 50 times across 30 races a day on a winning system and you have £10 a day at £20 stakes; £100 a day at £200 stakes. The economics of stake size are covered in bankroll management.
Step 5 — Risk controls that save you
These six checks should run inside the bot before every place_orders call. Skip any of them at your peril.
- Max stake per bet. Hardcoded cap — for example, £50. The bot cannot place an order larger than this. Cuts off the runaway-loop scenario where a bug doubles size on every retry.
- Max open liability across all markets. Sum every unmatched + matched liability live; if it exceeds your bankroll-percentage cap (typically 10–20%), refuse new bets.
- Max bets per market. Stops the bot from entering five back trades and one giant lay because of a rule bug.
- Daily loss limit. Track cumulative P&L since midnight. If down £100 (or your chosen number), the bot kills itself and emails you.
- Sanity check on price. Refuse to back at < 1.20 or > 50.0 unless explicitly allowed. The number of bots that have backed 1000.0 in error because the order book was thin is depressing.
- Heartbeat. Every 60 seconds the bot writes a timestamp to a file. A separate process (a cron job, or a watchdog Lambda) reads the file and emails you if it's stale.
If your bot has a bug where the exit logic doesn't fire and it keeps entering new trades, the loss can accumulate fast. £20 trades × 30 in an hour at -1 tick each is -£6 to -£15. Not catastrophic. But the same bug at £500 stakes is -£150 to -£375 in the same hour. Daily loss limits exist because of this.
Step 6 — Hosting on a VPS so it doesn't die
You cannot run a Betfair bot from your laptop. Your laptop sleeps, your home internet drops, your power goes out. The bot needs to live on a server that doesn't.
The standard set-up costs around £10–£20 per month:
- A small Linux VPS — DigitalOcean, Hetzner or Linode. 1 vCPU / 1 GB RAM is enough for most retail bots. Choose a region close to Betfair's API endpoints — Ireland (Dublin) or UK (London) data centres give the best latency.
- A systemd service that runs the bot and restarts it on crash.
- Logs written to a file (rotating with logrotate) and pushed nightly to S3 or Dropbox — you'll need them when something goes wrong.
- A simple uptime monitor like UptimeRobot pinging a healthcheck endpoint your bot exposes. If it's not pinging, you get an email.
Latency from a London VPS to Betfair's API typically sits at 5–15ms. From a US East coast VPS, 80–110ms. For pre-race scalping that gap matters; for in-play LTD it doesn't.
Resist the temptation to run six strategies on one VPS to save £10/month. When one bot crashes with an exception in shared state, all six go down. Costs you more in missed trades than the VPS savings.
Step 7 — Backtesting before going live
Never live-test a Betfair bot. Betfair Historic Data — the official paid feed, around £40/month for the Pro tier — gives you every order book update for every market since 2016. With pandas, you can replay your strategy against months of historical data in minutes.
A useful backtest needs three things: realistic latency assumptions (your bot won't see the data instantly, so assume 200ms delay), realistic fill assumptions (you don't always get matched at the price you see), and out-of-sample testing (train on 2024, test on 2025, never reuse the same data). For the underlying ideas, see Betfair data analysis and modelling.
A strategy that backtests to +£500/month at £20 stakes, when accounting for realistic latency and slippage, typically lives at +£100–£200/month after going live. Backtests overstate performance by 2–4×; budget for it.
Mistakes that cost money
- Trusting the first run. Your bot looks like it works on day one. By day three something edge-case breaks. Paper-trade for 30 days before risking real money.
- Not handling partial fills. You ask to BACK £20 at 3.40, you get matched £6 of it. Your code assumes full fill. Your exit lays £20.07. You're now £14.07 net lay-side, completely wrong direction.
- Ignoring commission. 5% on winnings (or worse if you're on a higher rate) is meaningful at scalp size. Build commission into every P&L calculation. See Betfair commission explained and premium charge.
- Re-using session tokens past expiry. Wrap every API call in a token-refresh handler.
- Not logging. When something goes wrong at 03:00, your only forensic evidence is the log file. Log every decision the bot made, with a timestamp, structured as JSON so you can grep it.
- Scaling stakes before scaling time. A bot that has run profitably for two weeks isn't proven. Six months is proven. Then scale.
If your bot is genuinely profitable at scale you'll eventually hit Betfair's Premium Charge — up to 60% of net winnings above a threshold. Run the bot on accounts that haven't crossed the threshold or on lower-stake accounts that fly under it. Detail in bot risks.
FAQ
Do I need to pay for the Betfair API?
No, not initially. The free Developer key gives you delayed data (1 second) and is fine for building and paper-trading. The £299 one-off Live App Key is needed for real-time data and is worth it once your strategy is profitable on paper.
Can I run my Python bot on Windows?
Technically yes, practically no. Windows VPSs are more expensive, less stable for long-running processes and have weaker tooling for log rotation, restart-on-failure and uptime monitoring. Use Ubuntu LTS.
Is the betfairlightweight library still maintained?
Yes. It's the de facto Python wrapper for the Betfair API and has been actively maintained for over a decade. The official Betfair Developer Forum endorses it.
How long until I can expect to be profitable?
If you already have a profitable manual strategy and are automating it: 1–3 months including a paper-trade window. If you're building a bot in the hope a strategy emerges: years, or never. The bot is execution. The strategy is the edge.
How does this compare to Bet Angel Guardian?
Bet Angel Guardian is a visual rules-and-triggers tool covered in Bet Angel Guardian complete guide. It's faster to set up (no code) and slower to extend. Python is the opposite. Most serious traders end up running both — Guardian for the strategies it expresses cleanly, Python for the ones it can't.
Ready to trade the exchange?
You can build a bot all day — but the bot needs an exchange to trade on. Betfair Exchange is the deepest, most liquid trading market in betting, with API access for developers.
Open Betfair Account →