To use the Betfair API from Node.js you log in to get a session token, send it plus your application key as headers, and call the JSON-RPC betting endpoints over HTTPS. Node's async model and the rich JavaScript HTTP ecosystem (fetch, axios) make this clean, and its event loop suits the real-time Stream API especially well. You need a funded account, an activated app key, and to respect the rate limits.
This page contains affiliate links — if you open an account through them we may earn a commission at no cost to you. It never changes our verdict.
- Why Node.js suits the Betfair API
- What you need before you start
- Logging in and the session token
- Calling the betting endpoints
- Async patterns that keep you sane
- From the desk: a Node script listing live prices
- Node and the Stream API
- Rate limits and weight
- Pitfalls specific to Node
- A minimal project structure
- Testing and going live safely
- The verdict
- FAQ
This is a sub of our Betfair API developers' complete guide, written for people who'd rather work in JavaScript than Python. Everything in the pillar — the app key, the session token, the betting operations — applies regardless of language; this page is about doing it idiomatically in Node, where the async model and the JSON-native ecosystem genuinely make some of this nicer than the Python equivalent. If you haven't got an app key yet, start with how to get a Betfair API key, then come back.
Why Node.js suits the Betfair API
Node.js has three properties that fit the Exchange unusually well. First, it's JSON-native — the Betfair betting API speaks JSON-RPC and the Stream API speaks line-delimited JSON, and in JavaScript that's just objects, no serialisation ceremony. Second, it's async-first: the event loop and async/await handle “fire several requests, wait for whichever returns” naturally, which is exactly the shape of a trading bot juggling market data and order management. Third, the Stream API is a socket feed, and Node's event-driven design — built around exactly this kind of non-blocking I/O — is arguably a better conceptual match for streaming than Python's threading model. None of this means Node is “better” than Python for Betfair — Python has more ready-made libraries like betfairlightweight — but if JavaScript is your language, you are not compromising by using it here.
What you need before you start
The prerequisites are identical to any Betfair API work and there are no shortcuts. You need a funded Betfair account (you can't get an app key without one), an activated application key (the delayed key is free and fine for testing; the live key has a one-off cost and gives real-time data), and your login credentials, ideally with a non-interactive login set up via a self-signed certificate for a bot that runs unattended. On the Node side you need a current LTS runtime and, realistically, an HTTP client — the built-in fetch (stable in modern Node) or axios both work fine. That's it to start; you do not need a heavyweight framework. Resist the urge to install ten packages before you've made a single successful API call.
Logging in and the session token
Authentication is the first thing every Betfair developer fights, and it works the same in Node as anywhere. You POST your username and password to the login endpoint, sending your application key in the X-Application header, and you get back a session token. From then on, every API call carries two headers: X-Application (your app key) and X-Authentication (the session token). The token expires after a period of inactivity, so a long-running bot must detect a token failure and re-login — wrap your request layer so that an authentication error triggers a fresh login and a retry, rather than crashing. For unattended bots, use the non-interactive (certificate-based) login so you're not storing a plain password in a script that logs in interactively. Get this layer solid and boring first; everything else depends on it.
Calling the betting endpoints
The betting API is JSON-RPC over HTTPS, which in Node is just a POST with a JSON body. The core operations you'll use are listEventTypes and listMarketCatalogue (to find markets), listMarketBook (to get prices), and placeOrders, cancelOrders and replaceOrders (to bet). Each call is a POST to the betting endpoint with a JSON-RPC envelope naming the method and its params, plus your two auth headers. Because the payloads and responses are JSON, you work directly with JavaScript objects — build the params object, JSON.stringify it into the body, await the response, and parse. A sensible structure is one thin async function per operation (e.g. listMarketBook(marketIds)) that handles the envelope and headers, so your strategy code just calls clean functions and never touches raw HTTP.
Async patterns that keep you sane
This is where Node earns its keep, and also where beginners trip. Use async/await throughout — it reads like synchronous code and keeps your logic legible. When you genuinely need several independent calls at once (say, prices on three unrelated markets), use Promise.all to fire them concurrently rather than awaiting each in series. But — and this matters for Betfair — don't blast unbounded concurrent requests, because you'll hit rate limits and weight penalties; prefer batching market IDs into a single listMarketBook call (it accepts many) over firing one request per market. Always wrap awaits in try/catch so a single failed call doesn't take down the process, and never leave a promise rejection unhandled. The pattern that works: clean async functions per operation, batch where the API allows it, controlled concurrency where it doesn't, and defensive error handling everywhere.
The task: I wanted a small Node tool to print the back/lay prices for the favourite in the next UK race, as a sanity check before wiring anything into a bot. Three steps: login, find the next race's market, get its prices.
What it did: the script logged in (cert-based), called listMarketCatalogue filtered to GB horse-racing WIN markets sorted by start time to grab the next off, then called listMarketBook on that market ID with EX_BEST_OFFERS. For a 2:50 Wolverhampton race it printed the favourite at back 2.96 / lay 3.00 with about £48,000 matched.
The timing: end to end, login plus the two calls returned in roughly 420ms on a UK connection — login is the slow part (~250ms), the data calls were under 90ms each. Fast enough for a monitoring tool; for actual trade execution you'd keep the session alive and only call market data, not re-login each time.
The gotcha that cost me twenty minutes: my first version sent the app key in the wrong header case and got a cryptic INVALID_APP_KEY-style failure. Betfair's auth errors are terse; the fix was matching the exact header names (X-Application, X-Authentication) and confirming the key was the live key, not the delayed one, since I wanted real-time prices. Once the headers were right it worked first time.
The lesson: in Node the HTTP and JSON parts are trivially easy — the friction is entirely in Betfair's auth and the exact header/endpoint details. Get a single read-only call (like listMarketBook) working end to end before you write a line of trading logic. If you can reliably print a live price, you've cleared 80% of the integration pain.
Node and the Stream API
For real-time data, the Exchange Stream API is where Node really shines. The stream is a persistent TLS socket sending line-delimited JSON, and Node's event-driven socket handling fits this like a glove: you open the connection, write the authentication and subscription messages, and attach a data handler that splits incoming bytes on newlines and parses each line as a JSON message. The async, non-blocking model means you can process the flow of market and order updates without threads, maintaining your in-memory order book as deltas arrive. The same discipline from the pillar applies — handle the image-then-deltas logic, heartbeats, conflation, and automatic reconnection — but the mechanics of consuming a socket and dispatching JSON events are about as natural as it gets in JavaScript. If you're building anything latency-sensitive, plan to move from polling listMarketBook to the stream, and read the dedicated streaming guide first.
Rate limits and weight
Betfair's API isn't unlimited and Node's ease of firing concurrent requests makes it easy to overdo. Requests carry a weight based on how much data they ask for, and there are limits on data-request operations; exceed them and you get throttled. The practical rules: request only the fields you need (don't pull full market depth when best offers will do), batch market IDs into single calls, poll at a sensible interval rather than in a tight loop, and switch to the Stream API for anything needing frequent updates — streaming sends only changes and doesn't burn your request allowance the way relentless polling does. There are also limits around order placement; respect them and build backoff into your request layer. Treating the API as a finite shared resource keeps your bot running where a naive Promise.all spamming requests gets throttled.
Pitfalls specific to Node
A few traps catch JavaScript developers in particular. Unhandled promise rejections — an await without a try/catch can silently take down your process; handle every rejection. Floating-point money maths — JavaScript numbers are floats, so be careful computing stakes and liabilities; round prices to valid Betfair ticks and money to two decimals deliberately. Token expiry mid-run — covered above, but it bites Node bots that run for days; auto-relogin. Blocking the event loop — heavy synchronous processing of a stream message stalls everything; keep handlers light. And over-installing packages — you can do all of this with fetch and the standard library; reach for dependencies only when they earn their place. None of these is hard once you know to look for it, but each has cost me real debugging time at some point.
A minimal project structure that scales
Before you write trading logic, lay out the project so it doesn't turn into one giant file. The structure that has served me well in Node mirrors the one I'd use in any language but plays to JavaScript's strengths. Keep an auth module whose only job is login, token storage and automatic re-login — everything else imports a getSession() from it and never thinks about credentials again. Keep an api module of thin async functions, one per Betfair operation (listMarketCatalogue, listMarketBook, placeOrders, and so on), each handling the JSON-RPC envelope, headers and error mapping so callers get clean data or a clean error. Keep a config for your app key, endpoints and limits, loaded from environment variables, never hard-coded — you do not want your live app key committed to a repository. Then keep your strategy code completely separate, importing the api functions and knowing nothing about HTTP. The payoff is that you can unit-test the strategy against fake data, swap polling for streaming without touching strategy logic, and debug auth problems in one place. This separation is the difference between a bot you can maintain for a year and a tangle you rewrite every month.
Testing and going live safely
The biggest difference between Betfair developers who keep their money and those who don't is how seriously they take testing, and Node makes a couple of safe paths easy. First, develop against the delayed app key and small stakes until the logic is proven — the delayed key is free and the data is delayed but structurally identical, so you can build and debug the entire flow without real-time pressure. Second, log every request and response to disk; in Node it's trivial to write a wrapper that records calls, and being able to replay exactly what your bot saw turns “it did something weird” into a reproducible bug. Third, build a kill switch and hard limits — a maximum stake, a maximum loss per session, and a manual stop — before the bot ever places a live bet, because a logic error in an async loop can fire many bets faster than you can react. Fourth, run it live on tiny stakes for far longer than feels necessary; an hour of looking profitable means nothing against a week of real market conditions. The mindset that keeps automated traders solvent is assuming your code is wrong until a long, small-stakes run proves otherwise. Speed is the whole reason to automate, but speed also means a mistaken bot acts on its error instantly and repeatedly — wrap it in logging, limits and patience, and lean on the foundations in the building bots guide.
The verdict
Node.js is a first-class choice for the Betfair API, not a compromise — its JSON-native, async-first design suits both the betting endpoints and especially the real-time Stream API. The hard parts aren't JavaScript; they're Betfair's authentication, the exact headers and endpoints, the rate limits, and the discipline of float-safe money maths and bulletproof error handling. Get a single read-only call working, wrap auth and requests in a defensive layer, batch and rate-limit your calls, then graduate to streaming for real-time work. Ground everything in the API developers' pillar, get set up via getting an API key, compare with the Python tutorial if you're language-agnostic, and turn it into something useful with building Betfair bots and a dashboard.
FAQ
Can I use the Betfair API with Node.js?
Yes. The Betfair betting API is JSON-RPC over HTTPS and the Stream API is a JSON socket feed, both of which Node handles naturally. You authenticate to get a session token, send it with your app key as headers, and call the endpoints. Node's async model suits trading bots well.
Do I need a special library to use Betfair from JavaScript?
No. You can do everything with the built-in fetch (or axios) and the standard library — the API is just JSON over HTTPS. There are community npm packages that wrap the endpoints, but they're optional. Many developers prefer a thin custom wrapper they fully understand.
Is Node.js or Python better for the Betfair API?
Both work well. Python has more mature ready-made libraries (like betfairlightweight); Node is JSON-native and its event-driven model is an excellent fit for the real-time Stream API. Use whichever language you're strongest in — neither is a compromise for Betfair.
How do I handle the session token expiring in a Node bot?
Wrap your request layer so an authentication error triggers a fresh login and retries the call. For unattended bots, use the non-interactive certificate-based login so you're not storing a plain password, and re-authenticate automatically whenever the token lapses or a stream socket reconnects.
What rate limits apply when calling Betfair from Node?
Requests carry a data weight and there are limits on data and order operations. Request only the fields you need, batch market IDs into single calls, poll at sensible intervals, and use the Stream API for frequent updates. Node makes it easy to fire too many concurrent requests, so add controlled concurrency and backoff.
Related reading
Anchor in the API developers' pillar, get set up with getting an API key, and compare languages via the Python getting-started tutorial. For real-time data see the Stream API guide, then build something with building Betfair bots, a dashboard, and the API software guide.
An automated system can lose money faster than a manual trader if it's wrong. Test on tiny stakes with robust error handling before scaling, and never let a bot run unsupervised until you trust it. Most Betfair traders lose money overall; past results don't guarantee future returns. 18+ only; help at BeGambleAware.org.
Get one read-only API call working in Node before you write any trading logic — it clears most of the integration pain.
Building Betfair Bots Open Betfair Account →