ib_async: Python Connectivity for Interactive Brokers
Python sync/async framework for Interactive Brokers API (replaces ib_insync)
At a glance
- What is it?
- ib_async replaces the separate IB-provided `ibapi` integration with a synchronous and asyncio-based Python framework for TWS and IB Gateway. It fits developers building market data, order management, account monitoring, and research tools, but it still depends on a configured and running Interactive Brokers application.
- Who is it for?
- Python developers building applications against a local TWS or IB Gateway session should evaluate ib_async when asyncio integration and automatic IB object synchronization matter to the design. Developers seeking a hosted brokerage API, a turnkey execution service, or support for Python versions below 3.10 should choose another approach.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why ib_async Sits Above TWS and IB Gateway
ib_async addresses the client-side complexity of writing Python applications around Interactive Brokers' socket API. TWS and IB Gateway expose the trading platform through a binary protocol, connection settings, client IDs, request limits, callbacks, and state that applications must keep aligned. The README says ib_async implements that protocol internally, so users do not also have to install the separate `ibapi` package. Its intended users are Python developers creating market data applications, trading systems, portfolio monitors, contract research tools, and exposure controls.
The library is not a brokerage account or an order-routing service. It still needs a running IB Gateway or a TWS instance with API mode enabled. This boundary matters for evaluation. ib_async can structure requests and synchronize the objects returned by Interactive Brokers, but authentication, account access, data entitlements, and the availability of live or historical data remain tied to IBKR and the configured application. A basic script follows a direct connection, application work, and disconnection sequence, as documented here:
from ib_async import *
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)
# Your code here
ib.disconnect()The local host and TWS port in this example reflect the README's documented default TWS setup. A Gateway deployment uses a different documented port, so copying the wrong connection endpoint is an avoidable failure.
The IB Object and Event Model
The central abstraction is the `IB` client. It represents the application-side connection to TWS or IB Gateway and exposes operations for market data, historical data, orders, positions, and account information. The README states that this component automatically stays synchronized with TWS or Gateway. That design is important because the underlying application can change as orders fill, positions change, account values move, and contract metadata arrives.
At the concurrency layer, `pyproject.toml` declares dependencies on `aeventkit`, `nest_asyncio`, and `tzdata`, while the package supports Python 3.10 and newer. The README describes the framework as asyncio-based. Its documentation also includes a synchronous `connect` method and an asynchronous `connectAsync` method. That gives application authors a choice at the connection boundary rather than requiring every program to adopt one application structure.
The event-oriented dependencies also fit applications that need updates without repeatedly polling every remote object. However, the README does not expose the full synchronization algorithm or guarantee the consistency behavior of every object type. That makes the API documentation and application-specific tests more important than assuming that every Interactive Brokers callback has been normalized into identical semantics.
Jupyter receives a distinct startup path. The README calls `util.startLoop()` there and says it is required for notebooks. It also says no `ib.run()` call is needed in that notebook pattern. These instructions should not be copied blindly into a normal service: notebook event-loop setup and a production application lifecycle are separate concerns.
Installing ib_async and Connecting to TWS
The package installation is a single pip operation, but a successful import does not by itself produce an API connection. Install Python 3.10 or newer, start TWS or IB Gateway, enable API access, and confirm that the port matches the application in use. The README identifies 7497 for TWS and 4001 for Gateway. It also calls for `127.0.0.1` to be included in Trusted IPs for local connections and for `Download open orders on connection` to be checked.
Install the published package with:
pip install ib_asyncAfter configuring TWS or IB Gateway, this basic script connects to the documented TWS endpoint, selects the first managed account, requests its summary, prints each returned tag and value, and disconnects:
from ib_async import *
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)
account = ib.managedAccounts()[0]
summary = ib.accountSummary(account)
for item in summary:
print(f"{item.tag}: {item.value}")
ib.disconnect()The reader should see account summary entries printed only after TWS or IB Gateway is running and configured to accept the connection. If `ib.connect` cannot reach the service, first compare the configured API port with the port in the script. If a second program connects while using the same client ID, assign each connection a different documented value.
There is no automated broker setup in the Python code. The settings are applied in the Interactive Brokers application under `Configure -> API -> Settings`, outside the library. This keeps installation short, but it also means a deployment has two configuration surfaces that must agree.
Async Services and Notebook Event Loops
For an asyncio application, the README uses `IB`, `connectAsync`, and `asyncio.run`. The documented shape is:
import asyncio
from ib_async import *
async def main():
ib = IB()
await ib.connectAsync('127.0.0.1', 7497, clientId=1)
# Your async code here
ib.disconnect()
asyncio.run(main())This pattern is relevant when market data or account changes must share an event loop with other asynchronous components. The package's declared asyncio dependencies and separate asynchronous connection method support that use case. They do not, by themselves, prove that every synchronous convenience method should be called from inside an async task. The README does not document a complete rule for mixing blocking and asynchronous calls, so an application should follow the API documentation for methods that perform I/O.
Notebooks use a different event-loop entry point:
from ib_async import *
util.startLoop() # Required for notebooks
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)
# Your code here - no need to call ib.run()The practical difference is the host process. A notebook requires the documented event-loop startup, while the async example owns its loop through `asyncio.run`. Moving code between those environments without changing startup behavior can leave the application without the event processing it expects.
Client IDs remain part of the network configuration in either model. The README states that every connection needs a unique client ID and uses `clientId=1` for a single connection. Parallel scripts, workers, or notebooks must not all assume that one number is available.
Market Data Entitlements, Memory, and Timeout Constraints
ib_async requests data through IBKR, but access is governed by the account and market data mode. The README provides three documented requests: `3` for delayed data, `4` for delayed frozen data, and `1` for real-time data. It states that real-time data requires a subscription. That distinction should be made explicit in an application's operational expectations. A successful library connection does not imply permission to receive live quotes.
# For free delayed data (no subscription required)
ib.reqMarketDataType(3) # Delayed
ib.reqMarketDataType(4) # Delayed frozen
# For real-time data (requires subscription)
ib.reqMarketDataType(1) # Real-timeThese calls select the documented market data type, but the README does not promise unlimited requests or identical behavior for every instrument. Interactive Brokers subscriptions, exchange details, pacing, and account permissions remain external conditions.
The README also recommends increasing Java memory to 4096 MB minimum under `Configure -> Settings -> Memory Allocation` to prevent Gateway crashes while loading bulk data. It separately advises increasing API timeout settings if large data requests lead to disconnections. These are operating requirements rather than ib_async defaults. Bulk contract or market-data workflows can therefore consume time in configuration and capacity planning even though the Python API is concise.
A practical failure chain is easy to construct: select real-time data without the proper entitlement, wait for expected callbacks that do not arrive, and mistake the absence of quotes for a synchronization defect. Debug permissions and subscription state before changing Python code.
Release Metadata, Dependencies, and Maintenance Scope
The repository is not archived, and the last push was on 2026-10-15. The release history lists `v2.0.1` from 2025-06-22, while `pyproject.toml` declares version `2.1.0`. That difference should be checked against the package index and the source checkout being adopted. The README's installation command installs the available package rather than pinning a release, which makes that distinction operationally relevant.
The project declares Python `>=3.10`, with classifiers for Python 3.10 through 3.13. Direct dependencies are `aeventkit ^2.1.0`, `nest_asyncio`, and `tzdata ^2025.2`. Development tooling includes pytest, pytest-asyncio, pandas, ruff, and mypy; the documentation group adds Sphinx-related packages. For a source checkout, the README provides separate Poetry commands for the library and the documentation and development groups:
poetry install
poetry install --with=docs,devThe first command installs the library project. The second enables the optional documentation and development environment. Type checking is available through:
poetry run mypy ib_asyncThis supports a review of type-related changes before an internal upgrade, although the README does not describe a compatibility policy for every Interactive Brokers release. Upgrade cost is therefore tied to Python-version compatibility, dependency changes, TWS or Gateway behavior, and any adjustments required by an application's sync and async lifecycle.
The repository identifies the license as BSD, and the project metadata specifies BSD-2-Clause. The `LICENSE` file governs the actual terms. This is an identification of the stated license, not legal advice about distribution, attribution, or obligations in a particular deployment.
When a Direct IBKR Integration Is the Better Choice
ib_async is a sensible fit for code that wants Python objects, synchronization, notebook support, or asyncio around a local TWS or IB Gateway session. It is less suitable as a replacement for an independently hosted REST or streaming brokerage interface. The README requires a running gateway or TWS API session and documents local ports rather than a remote service endpoint. Applications designed around independent regional gateways, horizontal service deployment, or cloud secrets management must account for that operating model.
It is also the wrong level of abstraction for a local indicator script that only needs occasional historical bars and has no use for synchronized IB objects. The documented library offers broader trading, portfolio, research, and risk functionality, which adds an external runtime and connection lifecycle to a task that might otherwise be small. The README does not provide a lightweight offline mode, and the binary protocol implementation still depends on the Interactive Brokers application.
A direct implementation of IB's `ibapi` callbacks is another approach, but it requires the caller to manage callback complexity and IB-side object synchronization directly. That route may fit an existing low-level TWS integration or a team that requires complete control over raw requests. ib_async instead removes the separate `ibapi` installation and presents a Python-oriented interface, at the cost of adding another abstraction between application code and the protocol.
Editorial conclusion
Python developers building applications against a local TWS or IB Gateway session should evaluate ib_async when asyncio integration and automatic IB object synchronization matter to the design. Developers seeking a hosted brokerage API, a turnkey execution service, or support for Python versions below 3.10 should choose another approach. Before adoption, verify the installed package version, connection behavior against the intended TWS or Gateway configuration, available market data subscriptions, and compatibility with the operations the application will automate.
Frequently asked questions
How do I install ib_async?
Use `pip install ib_async` with Python 3.10 or newer. You also need a running IB Gateway or TWS with API mode enabled.
Which port should I use to connect ib_async to TWS or IB Gateway?
The README documents port 7497 for TWS and port 4001 for IB Gateway. The Python endpoint must match the application configuration.
Does ib_async require the separate ibapi package?
No. The README states that ib_async implements the full IBKR API binary protocol internally.
Does ib_async provide real-time market data without an Interactive Brokers subscription?
The README distinguishes free delayed modes from real-time data and states that real-time data requires a subscription.
What is the difference between connect and connectAsync in ib_async?
The synchronous examples use `connect`, while the asyncio example uses `await ib.connectAsync`. Notebook examples also use `util.startLoop()` as documented.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ib-api-reloaded-ib-async)Was this useful?