29 Jun 2026
Talking to Interactive Brokers from Python: the API, the libraries, and how to actually use it
Photo: Chris Ried / Unsplash
Interactive Brokers has one of the most capable APIs in retail brokerage, and one of the most confusing on-ramps. There are two completely different APIs, a couple of competing Python libraries, and a running application you have to keep alive in the background. Here's the map, so you don't waste a weekend on the wrong path.
First: there are two different IBKR APIs
This trips up almost everyone.
- The TWS API (also called the "native" API). Your Python code talks over a socket to a running copy of Trader Workstation (TWS) or the lighter, headless IB Gateway. That local app holds the authenticated session and relays everything to IB's servers. This is the mature, full-featured path, and what most retail automation uses.
- The Client Portal Web API (the "Web API"). A REST and WebSocket API. You run a small Client Portal Gateway (a Java process) that you log into, or, for third-party apps serving other users, you use OAuth. No TWS required. Better suited to web apps and multi-user services.
For a solo investor scripting their own account, the TWS API is almost always the right choice. The rest of this guide focuses there.
The moving parts you have to set up
The TWS API only works while TWS or IB Gateway is running and logged in. Your script is a client that connects to it.
- Install and log into TWS or IB Gateway. Gateway is the better choice for automation: lighter, no charting UI, meant to run unattended.
- Enable the API. In Settings > API > Settings, tick Enable ActiveX and Socket Clients, confirm the socket port, and add
127.0.0.1to Trusted IPs. Consider ticking Read-Only API while you're learning, so a bug can't fire a live order. - Know your port. The defaults are worth memorizing:
- TWS live:
7496, TWS paper:7497 - IB Gateway live:
4001, IB Gateway paper:4002
- TWS live:
- Always start on the paper account. Same API, fake money. There is no reason to debug against real cash.
Which Python library to use in 2026
This is the part with a landmine.
ibapi(official). IBKR's own library, bundled with the TWS API download. It's low-level and callback-driven: you subclassEWrapperandEClient, run a network thread, and handle every response as an incoming event. It's complete and it's what the docs are written against, but it's verbose and awkward for simple tasks.ib_insync(legacy). For years this was the library: a clean, high-level layer overibapithat made everything readable. Its author, Ewald de Wit, sadly passed away, and the original project is no longer maintained. You'll still find it in countless tutorials, but don't start a new project on it.ib_async(recommended). A community-maintained fork ofib_insync, kept alive and updated. It's essentially a drop-in replacement with the same ergonomics. For new work, this is the one to install.
There's also ibind, a third-party client if you decide to go the Client Portal Web API route instead. Handy to know it exists.
A working example with ib_async
Install it, make sure IB Gateway (paper) is running with the API enabled, and:
from ib_async import IB, Stock
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1) # 7497 = TWS paper
# Resolve an ambiguous ticker into a fully-specified contract
apple = Stock('AAPL', 'SMART', 'USD')
ib.qualifyContracts(apple)
# What do I hold?
for pos in ib.positions():
print(pos.contract.symbol, pos.position, pos.avgCost)
# Daily bars for the last 30 days
bars = ib.reqHistoricalData(
apple,
endDateTime='',
durationStr='30 D',
barSizeSetting='1 day',
whatToShow='TRADES',
useRTH=True,
)
for b in bars[-5:]:
print(b.date, b.close)
ib.disconnect()
A few things this snippet quietly teaches:
clientIdmatters. Each connected client needs a distinct id. Reuse one that's already connected and you'll be rejected.- Contracts must be qualified.
AAPLalone is ambiguous (which exchange, which currency);qualifyContractsfills in theconId, IB's unique instrument identifier. Keying everything on theconIdrather than the ticker is the single best habit you can build, because tickers are not unique across exchanges. ib_asynchides the event loop. Under the hood it's all async, but for scripts you can call things synchronously as shown.
The two things that will bite you
- Market data needs subscriptions. Live quotes require the right market-data subscriptions on your account. Without them you'll get nothing or an error. For testing, ask for delayed data with
ib.reqMarketDataType(3)(delayed) or4(delayed-frozen) before requesting a quote. - Pacing limits are real. IB caps you at roughly 50 messages per second, and historical-data requests have their own throttles (hammer the same contract and you'll get pacing violations). Batch your requests, add small delays, and cache what you've already pulled. Respecting the pacing window is the difference between a script that runs for months and one that gets throttled or disconnected.
What this has to do with Cresori
Cresori connects to the same Interactive Brokers API to pull your trades, positions, dividends, and cash automatically, then turns them into performance attribution, dividend forecasts, and tax reporting, without you writing or maintaining any of the code above. Think of this guide as the do-it-yourself path: great for a custom script or a personal robot, but a lot of plumbing (contract resolution, pacing, reconnection, corporate actions, split adjustments) to own yourself. If you'd rather skip straight to the analysis, that's the part Cresori handles.
Sources and further reading: the IBKR TWS API documentation, the ib_async repository, and the Client Portal Web API docs.
More from Learn
22 Jun 2026
The Wheel, explained: covered calls, cash-secured puts, and where the risk hides
The wheel is an income strategy that sells options for premium instead of buying them. Simpler than it sounds, and the risk isn't where beginners think.
15 Jun 2026
Is your dividend income sustainable? Payout, debt, and the yield trap
A high yield is often a dividend cut the market already priced in. Three checks, payout ratio, balance sheet, and the yield itself, spot durable income.
8 Jun 2026
The dividend you'll actually receive: withholding, pay lag, and the anchor date
The headline yield and the cash reaching your account differ. Three things sit between: withholding tax, the ex-date to pay-date lag, and payment timing.