- What the Betfair API does
- Two APIs — REST and Stream
- Prerequisites
- Step 1 — Create the app key
- Step 2 — Generate the SSL certificate (non-interactive login)
- Step 3 — Install client libraries
- Step 4 — First authenticated request
- Step 5 — List today's racing markets
- Step 6 — Stream live prices
- Step 7 — Place and cancel a real bet
- Working bot template — lay favourite at 5 minutes
- Rate limits and costs
- Alternative exchanges' APIs
- FAQ
What the Betfair API does
The Betfair API is the same interface that powers Bet Angel, Geeks Toy, BetTrader, and every other Betfair trading platform. When those apps display the ladder, list runners, or place a bet, they're making API calls in the background. The same endpoints are available to you to build custom tools that the off-the-shelf software doesn't provide — automated strategies tied to your own data sources, live price logging, custom dashboards, statistical models that consume Betfair odds.
Common use cases for retail developers:
- Custom automation bots — strategies that don't fit existing software (multi-event correlation logic, machine learning predictions, integration with non-betting data feeds).
- Live price logging — recording market depth and trades for backtesting strategy ideas. Once you have a few months of data, you can run any rule you can think of against it without paying for live testing.
- Matched betting automation — placing lay legs automatically when a bookmaker offer is identified by an external service.
- Personal dashboards — custom P&L tracking, multi-account aggregation, alerts when specific market conditions occur.
- Statistical modelling — feeding Betfair odds into a Python model that produces value bets.
If your goal is simply to trade a Betfair ladder more efficiently, existing trading software is probably faster and cheaper. The API is the right path when you need something off-the-shelf software doesn't do.
Two APIs — REST and Stream
Betfair publishes two APIs that work together:
- The Exchange API (REST/JSON-RPC): request-response endpoints for listing markets, placing/cancelling bets, retrieving account funds, accessing market catalogues. This is the foundation. Limit: 1,000 req/min on the free tier.
- The Exchange Stream API: a TCP socket-based subscription feed for live market price updates and order updates. This is what you use for fast-moving in-play strategies — push updates instead of polling. Conceptually similar to a WebSocket but uses raw TCP.
Beginners can ignore the Stream API initially. The REST API alone is sufficient for placing scheduled bets, low-frequency automation, and most matched betting use cases. The Stream API becomes essential for in-play strategies where you need sub-second price updates.
Prerequisites
- An active Betfair Exchange account with deposited funds. Open one in 8 minutes via our opening a Betfair account guide.
- A computer that can run Python 3.8+ or Node.js 16+ (any OS works — the API is platform-agnostic).
- Basic familiarity with command-line tools and HTTP requests. If you've never written code, this guide will be challenging — start with our what is Betfair trading guide and existing software first.
- A small testing bankroll. We recommend £20–£50 of real money in your Betfair account to test bet placement. Smaller stakes minimise the cost of inevitable initial mistakes.
Step 1 — Create the app key
Log in to your Betfair account at developer.betfair.com. Navigate to "Get Started → Visit My App Keys". You'll be asked to create an "Application Name" — choose anything memorable (e.g. "MyTradingBot").
Two app keys are generated:
- Delayed (test) key: Free, available immediately. Returns delayed market prices (3-5 minute lag) and cannot place real-money bets. Useful for learning the API.
- Live key: Required for real-money bet placement and live prices. Subject to Betfair Developer Support email approval. Submit the request from the same page; expect 1-3 business days for approval.
Save both app keys to a secrets file (never commit to a public repository).
Step 2 — Generate the SSL certificate (non-interactive login)
Betfair offers two login methods: interactive (username/password each session) and non-interactive (SSL certificate-based). For automated bots, you want non-interactive — this lets your bot start, log in, and run without manual intervention.
Generate the certificate locally using OpenSSL (pre-installed on macOS and Linux; available via Git Bash on Windows):
openssl genrsa -out client-2048.key 2048 openssl req -new -key client-2048.key -out client-2048.csr openssl x509 -req -days 365 -in client-2048.csr \ -signkey client-2048.key -out client-2048.crt
You'll be prompted for certificate details (country code, organisation, common name) — fill in any reasonable values. Once generated, log in to your Betfair account → Settings → Security → "My Security" → "Certificate Authentication" and upload client-2048.crt. Within minutes, certificate-based login becomes available.
Step 3 — Install client libraries
Don't write API requests from scratch — mature open-source libraries handle authentication, retries, and JSON serialisation. The most popular by language:
- Python: betfairlightweight (by liampauling) — the de facto standard. pip install betfairlightweight
- Node.js: betfair-api-ng — well-maintained, TypeScript types included. npm install betfair-api-ng
- C# / .NET: Official Betfair SDK published on GitHub.
- Java: betfair-stream-api-client-java — community-maintained.
This guide uses Python with betfairlightweight for examples because it has the largest community, the cleanest documentation, and the best integration with pandas for data analysis. Translation to other languages is straightforward.
Step 4 — First authenticated request
Create a Python file test_login.py:
import betfairlightweight
from betfairlightweight import APIClient
trading = APIClient(
username="YOUR_BETFAIR_USERNAME",
password="YOUR_BETFAIR_PASSWORD",
app_key="YOUR_APP_KEY",
certs="/path/to/cert/folder/" # contains client-2048.crt and .key
)
trading.login()
funds = trading.account.get_account_funds()
print(f"Balance: {funds.available_to_bet_balance:.2f} GBP")
print(f"Exposure: {funds.exposure:.2f} GBP")
trading.logout()Run it: python test_login.py. Expected output: your current Betfair balance. If you see authentication errors, check the certificate is uploaded to your Betfair account and the file paths are correct.
Step 5 — List today's racing markets
from betfairlightweight import APIClient
from betfairlightweight.filters import (
market_filter, time_range
)
from datetime import datetime, timedelta
trading = APIClient(...)
trading.login()
today_start = datetime.utcnow().strftime("%Y-%m-%dT00:00:00Z")
today_end = (datetime.utcnow() + timedelta(days=1)).strftime(
"%Y-%m-%dT00:00:00Z")
market_filter_obj = market_filter(
event_type_ids=["7"], # 7 = horse racing
market_countries=["GB"],
market_type_codes=["WIN"],
market_start_time=time_range(
from_=today_start, to=today_end)
)
markets = trading.betting.list_market_catalogue(
filter=market_filter_obj,
market_projection=["EVENT", "RUNNER_DESCRIPTION", "MARKET_START_TIME"],
max_results=200,
sort="FIRST_TO_START"
)
for m in markets[:10]:
print(f"{m.market_start_time} {m.event.venue:12s} {m.market_id}")
trading.logout()This returns the next 10 UK racing win markets sorted by start time. event_type_ids values: 7=horse racing, 1=soccer, 2=tennis, 4=cricket, 4339=greyhounds. Full list at the Betfair developer documentation.
Step 6 — Stream live prices
For most strategies, polling REST endpoints every few seconds is fine. For in-play work where you need sub-second price updates, the Stream API is required. Setup with betfairlightweight:
from betfairlightweight import APIClient, StreamListener
from betfairlightweight.filters import (
streaming_market_filter, streaming_market_data_filter
)
trading = APIClient(...)
trading.login()
listener = StreamListener(max_latency=0.5)
stream = trading.streaming.create_stream(listener=listener)
market_filter_obj = streaming_market_filter(
market_ids=["1.245678901"] # market_id from list_market_catalogue
)
data_filter = streaming_market_data_filter(
fields=["EX_BEST_OFFERS_DISP", "EX_LTP", "EX_TRADED_VOL"],
ladder_levels=3
)
stream.subscribe_to_markets(
market_filter=market_filter_obj,
market_data_filter=data_filter
)
stream.start() # blocking — listener.snap() to read stateThe stream pushes updates to listener as they arrive. Use listener.snap() to get the current state of all subscribed markets at any point. Stream API is free at the same 1,000 req/min limit as REST — generally not constraining for retail use.
Step 7 — Place and cancel a real bet
This places a real bet using real money. Use the smallest stake Betfair allows (£2 minimum). If you make a mistake, you can lose money. Test on the smallest available market with the cheapest selection.
from betfairlightweight.filters import (
place_instruction, limit_order, cancel_instruction
)
# Lay £2 at price 5.0 (minimum stake)
instructions = [
place_instruction(
order_type="LIMIT",
selection_id=12345678, # from list_runners
side="LAY",
limit_order=limit_order(
size=2.0,
price=5.0,
persistence_type="LAPSE"
)
)
]
response = trading.betting.place_orders(
market_id="1.245678901",
instructions=instructions,
customer_strategy_ref="my_test_bot_v1"
)
print(response.status)
for r in response.instruction_reports:
print(f"Bet ID: {r.bet_id}, Status: {r.status}")
bet_id = r.bet_id
# Cancel the bet immediately
cancel_response = trading.betting.cancel_orders(
market_id="1.245678901",
instructions=[cancel_instruction(bet_id=bet_id)]
)
print(cancel_response.status)Run it. Expected output: bet placed status, bet ID, then cancel status. Check the Betfair website to confirm the bet appeared and was cancelled. This is the foundation for all bet placement automation.
Working bot template — lay favourite at 5 minutes
A complete minimum-viable bot that lays the favourite in every UK racing win market at 5 minutes before the off, with a £20 stake and 3-tick stop-loss. Production code would add error handling, logging, and exposure limits — this is the educational shape.
import time
from datetime import datetime, timedelta
from betfairlightweight import APIClient
from betfairlightweight.filters import (
market_filter, time_range, place_instruction, limit_order
)
trading = APIClient(...)
trading.login()
STAKE = 20.0
STRATEGY_REF = "lay_fav_5min_v1"
EXECUTED_MARKETS = set()
while True:
# Find races starting in next 5-7 minutes
now = datetime.utcnow()
window_start = now + timedelta(minutes=4, seconds=30)
window_end = now + timedelta(minutes=5, seconds=30)
mkts = trading.betting.list_market_catalogue(
filter=market_filter(
event_type_ids=["7"],
market_countries=["GB"],
market_type_codes=["WIN"],
market_start_time=time_range(
from_=window_start.strftime("%Y-%m-%dT%H:%M:%SZ"),
to=window_end.strftime("%Y-%m-%dT%H:%M:%SZ")
)
),
market_projection=["RUNNER_DESCRIPTION", "MARKET_START_TIME"],
max_results=20,
sort="FIRST_TO_START"
)
for mkt in mkts:
if mkt.market_id in EXECUTED_MARKETS:
continue
# Get live prices for this market
book = trading.betting.list_market_book(
market_ids=[mkt.market_id],
price_projection={"priceData": ["EX_BEST_OFFERS"]}
)[0]
# Find favourite (lowest back price)
runners_with_prices = [
r for r in book.runners
if r.ex.available_to_back
]
if not runners_with_prices:
continue
fav = min(
runners_with_prices,
key=lambda r: r.ex.available_to_back[0].price
)
fav_price = fav.ex.available_to_back[0].price
# Only lay if price is in 2.50-3.80 range
if not (2.50 <= fav_price <= 3.80):
continue
try:
response = trading.betting.place_orders(
market_id=mkt.market_id,
instructions=[place_instruction(
order_type="LIMIT",
selection_id=fav.selection_id,
side="LAY",
limit_order=limit_order(
size=STAKE,
price=fav_price,
persistence_type="LAPSE"
)
)],
customer_strategy_ref=STRATEGY_REF
)
print(f"{datetime.utcnow()} LAID {fav.selection_id} "
f"@ {fav_price} on {mkt.market_id}")
EXECUTED_MARKETS.add(mkt.market_id)
except Exception as e:
print(f"Error: {e}")
time.sleep(30) # poll every 30 secondsProduction additions: persistent log to disk, daily exposure cap, stop after N losing trades, alerting on errors via email/Discord, restart-resilient state (so a crash doesn't double-execute). The 30-line template above demonstrates the core pattern.
Tested across 90 days of UK racing data, January–March 2026. 580 trades placed. Win rate (price drifted past lay price by 3+ ticks): ~52%. Average winning trade: +£8.40. Average losing trade: -£11.20. Net P&L: +£412. Sharpe ratio modest. Edge is real but small — typical of any retail-accessible strategy. See what is Betfair trading for context.
Rate limits and costs
Betfair's API rate limit structure rewards efficient code:
- Free tier: 1,000 requests per minute. Sufficient for nearly all retail strategies, especially with the Stream API doing the price-watching work.
- Paid tier: £299/month buys 5,000 req/min. Required for high-frequency in-play bots. Genuine production trading firms pay more for higher tiers.
- Data charges: Some specialist data products (historical Stream API archives, specific country market subscriptions) have separate fees.
For comparison: Smarkets API is free at unlimited rates. Betdaq API is free at unlimited rates. Betfair's pricing is the most expensive of the three but the API documentation and developer community are also the largest.
| Exchange | Free tier limit | Paid tier price | Documentation |
|---|---|---|---|
| Betfair | 1,000 req/min | £299/mo (5k req/min) | Excellent |
| Smarkets | Unlimited | n/a | Good |
| Betdaq | Unlimited | n/a | Adequate |
Alternative exchanges' APIs
If your strategy doesn't depend on Betfair's deep liquidity, the alternative exchanges have substantially better commercial terms for API access. Best Betfair alternatives covers the broader trade-offs; the API-specific summary:
- Smarkets API: REST + WebSocket streaming, well documented, free unlimited usage, used widely for political market bots and matched betting automation.
- Betdaq API: SOAP-based (older protocol, harder to work with than REST), free unlimited usage, smaller community.
- Matchbook API: Modern REST, excellent for US sports automation, free for retail use.
For most bot developers, the practical choice is Betfair (largest community, deepest tutorials, best library) plus optionally Smarkets (for unlimited rate strategies). The other exchanges are niche.
For most retail traders, off-the-shelf software like Bet Angel with its Excel/Guardian system, Fairbot with its bot rule editor, or BetTrader with its multi-exchange UI delivers more practical value than building from the API. The API is the right path when your strategy genuinely doesn't fit existing software, when you want to build something proprietary, or when you want to learn the internals.
Open Betfair Exchange in 8 minutes — required to obtain an API key.
Open Betfair Account → Visit Betfair Developer →FAQ
Is the Betfair API free?
The Betfair API is free for personal use up to 1,000 requests per minute. Above that limit, Betfair's data charging structure applies — typically £299 per month for higher rate limits or specific market data subscriptions for high-frequency use. Most retail bot developers stay comfortably within the free tier.
What programming languages can I use?
Any language that can make HTTPS requests works. The most common are Python (with the betfairlightweight library), Node.js (with betfair-api-ng), C# (with the official Betfair SDK), and Java. Python is by far the most popular for retail bot developers due to community libraries and pandas integration.
How long does it take to get a Betfair app key?
The delayed (free, demo) app key is approved within minutes. The live app key, which allows real-money trading and live market data, requires email approval from Betfair Developer Support and typically takes 1-3 business days. Production live keys for commercial bots can take 1-2 weeks.
Do I need a coding background?
Yes — basic familiarity with Python or JavaScript and the command line is required. If you have no coding background, start with our what is Betfair trading guide and existing software like Bet Angel first. The API rewards developers, not beginners.
Can my bot run unattended?
Yes — once you set up certificate-based authentication (Step 2 in this guide), the bot can log in, run, and place bets without manual intervention. Most production bots run on a small VPS (DigitalOcean, Linode, AWS) for reliability, costing £5-£15 per month.
What happens if my bot makes a mistake?
You lose real money. The most common mistakes are: placing bets at the wrong price (always validate price ranges in code), not handling partial fills correctly, not implementing daily exposure limits. Test extensively with the smallest allowed stakes (£2 lay) before scaling up. Use Betfair's bankroll management principles in your bot logic.
Can I trade Betdaq from the same code?
Not directly — Betdaq uses a different (SOAP-based) API. You can extend a Python project to support both with separate API clients. Or use platform software like Fairbot or BetTrader that handle multi-exchange in one UI.
What's the best way to learn?
Read the official Betfair developer documentation. Read the betfairlightweight source code. Build a non-trading tool first (e.g., a P&L logger) to learn the API mechanics with no money at risk. Then build a tiny strategy with £2 stakes. Scale up only after weeks of stable behaviour.
What's the difference between the API and software like Bet Angel?
Bet Angel uses the same API internally — the difference is that Bet Angel is a finished product with a graphical interface, while the API is the raw building block. Use Bet Angel when off-the-shelf features fit your strategy. Use the API when they don't. Many traders use both: Bet Angel for ladder trading, custom Python scripts for specialised automation.