The IBKR TWS API enforces a hard ceiling of 50 messages per second from client to TWS, plus a separate historical-data pacing regime: no more than 60 historical requests per 10-minute window, no 6+ identical-contract requests within 2 seconds, and no identical request repeated within 15 seconds. All of this is verified against the official TWS API docs on 2026-05-2512. Breaching the message rate eventually drops your connection; breaching historical pacing returns a pacing-violation error. Option chains have a specific gotcha: the old contract-details method is throttled, but reqSecDefOptParams is not3. This is the operational spec you build a resilient IBKR client against. Map it against other brokers in the Broker API Comparator.
TL;DR
- Global message rate: 50 messages/second from client to TWS; over-limit eventually closes the connection1.
- Historical-data pacing (each is a violation)2:
- More than 60 historical requests in any 10-minute period.
- 6+ historical requests for the same contract, exchange, and tick type within 2 seconds.
- An identical historical request repeated within 15 seconds.
- BID_ASK requests count double.
- Max open historical requests: 50 simultaneous2.
- Market-data lines: 100 by default (minimum 100)2.
- Option chains:
reqContractDetailsis throttled;reqSecDefOptParamsavoids the throttle3.
The global message rate
Every other rule sits on top of one ceiling: the client may send at most 50 messages per second to TWS1. Each ticker subscription request and each cancellation counts as one message. This is not a per-minute budget you can burst into; it is a sustained-rate cap. Sustained breaches do not return a clean 429 — TWS eventually closes the socket1. The correct client design paces all outbound traffic under 50/second with a token bucket, treating subscriptions, orders, and data requests as drawing from the same per-second budget.
Historical-data pacing rules
Historical data has its own pacing layer, because backfilling bars is the easiest way to flood the gateway. A pacing violation is triggered by any of these2:
| Rule | Threshold |
|---|---|
| Requests per 10-minute window | More than 60 |
| Same contract/exchange/tick type | 6+ within 2 seconds |
| Identical request repeated | Within 15 seconds |
| BID_ASK requests | Count double toward all limits |
| Max simultaneous open requests | 50 |
All verified on 2026-05-252. The practical reading: when backfilling a universe, stagger requests so you stay under 6 per contract per 2 seconds and under 60 total per 10 minutes, and never re-fire an identical request inside 15 seconds. A queue with a per-10-minute counter and a per-contract debounce is the standard pattern.
What a pacing violation looks like
When you cross a historical-data threshold, TWS returns a pacing-violation error rather than silently dropping data. Recovery is to pause, let the 10-minute window roll, and resume at a slower cadence. Unlike the 50/second message limit (which can kill the connection), a historical pacing violation is recoverable in place — but it stalls your backfill, so prevention beats recovery.
The option-chain gotcha
Polling option chains is where many IBKR integrations accidentally trip pacing. The older approach of enumerating contracts via reqContractDetails is throttled — the more ambiguous the contract definition, the slower and more rate-limited the return3. The fix is the dedicated method: reqSecDefOptParams returns the full list of expirations and strikes for an underlying without the throttling limitation3. For any option-chain workload, use reqSecDefOptParams; reserve reqContractDetails for narrow, fully-specified lookups.
Market-data lines
Separate from pacing, IBKR limits how many instruments you can stream concurrently: 100 market-data lines by default, with a minimum of 1002. Streaming quotes on more than 100 symbols at once requires more lines (which scale with commission activity). A scanner watching a broad universe should rotate subscriptions through the line budget rather than assuming unlimited concurrent streams.
Building a compliant client
- One token bucket at 50/second for all outbound messages: the master constraint.
- Historical queue with a 10-minute rolling counter (cap 60), a per-contract 2-second debounce, and a 15-second identical-request guard.
- Use
reqSecDefOptParamsfor option chains, neverreqContractDetailsin a loop. - Rotate market-data subscriptions through the 100-line budget.
- Treat the 50/second limit as connection-fatal and historical pacing as recoverable-but-stalling.
For the cost side of IBKR (the API is free; you pay commissions and per-exchange data), see Interactive Brokers API Pricing 2026.
Verified figures
The 50 messages/second client limit, the historical-data pacing thresholds (60/10min, 6/2s, 15s identical, BID_ASK double, 50 max open), the 100 default market-data lines, and the reqSecDefOptParams throttle exemption were all verified against the official TWS API documentation on 2026-05-25.
Connects to
- Interactive Brokers API Pricing 2026: the cost side of the same API.
- Alpaca vs Interactive Brokers API 2026: pacing model versus a flat per-minute cap.
- Choosing a Broker API in 2026: the five-broker pillar.
- Broker API Comparator: rate models side by side.
References
Footnotes
-
Interactive Brokers. "TWS API - Introduction" (TWS accepts up to fifty messages per second from the client side; over-limit closes the connection; each subscription/cancellation is one message). interactivebrokers.github.io, verified 2026-05-25. https://interactivebrokers.github.io/tws-api/introduction.html ↩ ↩2 ↩3 ↩4
-
Interactive Brokers. "TWS API - Historical Data Limitations" (60 requests / 10 minutes, 6 same-contract requests / 2 seconds, identical request within 15 seconds, BID_ASK counts double, 50 max simultaneous open requests). verified 2026-05-25. https://interactivebrokers.github.io/tws-api/historical_limitations.html ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Interactive Brokers. "TWS API - Options" (reqSecDefOptParams returns expirations and strikes without the reqContractDetails throttling limitation). verified 2026-05-25. https://interactivebrokers.github.io/tws-api/options.html ↩ ↩2 ↩3 ↩4
Verified engine output
Show the recompute-verified inputs and outputs
| require_futures | 1 |
|---|---|
| max_auth_complexity | 5 |
| filters › require options | false |
|---|---|
| filters › require futures | true |
| filters › require crypto | false |
| filters › require mcp | false |
| filters › require free tier | false |
| filters › max auth complexity | 5 |
| results › row 1 › broker › id | schwab |
| results › row 1 › broker › name | Schwab |
| results › row 1 › broker › url | https://www.schwab.com/ |
| results › row 1 › broker › docs url | https://developer.schwab.com/ |
| results › row 1 › broker › auth | OAuth 2.0 (3-legged) |
| results › row 1 › broker › auth complexity | 4 |
| results › row 1 › broker › order types (9 items) | [...] |
| results › row 1 › broker › rate limits | 120 req/min per endpoint (published tier) |
| results › row 1 › broker › market data › row 1 | Real-time equities + options quotes |
| results › row 1 › broker › market data › row 2 | Historical bars (1m to daily) |
| results › row 1 › broker › market data › row 3 | No exchange depth via API |
| results › row 1 › broker › mcp | none |
| results › row 1 › broker › mcp note | No official or listed community MCP server |
| results › row 1 › broker › assets › stocks | true |
| results › row 1 › broker › assets › options | true |
| results › row 1 › broker › assets › futures | true |
| results › row 1 › broker › assets › crypto | false |
| results › row 1 › broker › assets › forex | true |
| results › row 1 › broker › assets › bonds | true |
| results › row 1 › broker › account minimum | 0 |
| results › row 1 › broker › commission | $0 equities, $0.65/contract options |
| results › row 1 › broker › good for | Established retail, post-TDA API migration |
| results › row 1 › broker › has free tier | true |
| results › row 1 › broker › notes › row 1 | API rebuilt after TD Ameritrade integration; still maturing |
| results › row 1 › broker › notes › row 2 | Requires individual developer registration and app review |
| results › row 1 › broker › notes › row 3 | Token refresh flow is finicky vs Alpaca/Tradier |
| results › row 1 › score | 2 |
| results › row 1 › max score | 2 |
| results › row 1 › fits | true |
| results › row 2 › broker › id | ibkr |
| results › row 2 › broker › name | Interactive Brokers |
| results › row 2 › broker › url | https://www.interactivebrokers.com/ |
| results › row 2 › broker › docs url | https://www.interactivebrokers.com/en/trading/ib-api.php |
| results › row 2 › broker › auth | OAuth + TWS/IB Gateway |
| results › row 2 › broker › auth complexity | 5 |
| results › row 2 › broker › order types (10 items) | [...] |
| results › row 2 › broker › rate limits | ~50 msg/sec per connection; 50 orders/sec burst |
| results › row 2 › broker › market data › row 1 | Global equities via subscription bundles |
| results › row 2 › broker › market data › row 2 | Level-2 depth on most exchanges |
| results › row 2 › broker › market data › row 3 | Historical depth across asset classes |
| results › row 2 › broker › mcp | community |
| results › row 2 › broker › mcp note | Community CLI MCP; audit before production |
| results › row 2 › broker › assets › stocks | true |
| results › row 2 › broker › assets › options | true |
| results › row 2 › broker › assets › futures | true |
| results › row 2 › broker › assets › crypto | true |
| results › row 2 › broker › assets › forex | true |
| results › row 2 › broker › assets › bonds | true |
| results › row 2 › broker › account minimum | 0 |
| results › row 2 › broker › commission | Tiered per-share or fixed; ~$0.0035/sh tiered |
| results › row 2 › broker › good for | Multi-asset-class, international, scale |
| results › row 2 › broker › has free tier | false |
| results › row 2 › broker › notes › row 1 | Requires TWS or IB Gateway running locally |
| results › row 2 › broker › notes › row 2 | Idempotency via client-supplied orderId |
| results › row 2 › broker › notes › row 3 | Fully headless gateway is possible but under-documented |
| results › row 2 › score | 2 |
| results › row 2 › max score | 2 |
| results › row 2 › fits | true |
| results › row 3 › broker › id | alpaca |
| results › row 3 › broker › name | Alpaca |
| results › row 3 › broker › url | https://alpaca.markets/ |
| results › row 3 › broker › docs url | https://alpaca.markets/docs/ |
| results › row 3 › broker › auth | API Key + Secret |
| results › row 3 › broker › auth complexity | 1 |
| results › row 3 › broker › order types (10 items) | [...] |
| results › row 3 › broker › rate limits | 200 req/min (free), higher on paid tiers |
| results › row 3 › broker › market data › row 1 | IEX real-time (free) |
| results › row 3 › broker › market data › row 2 | Full SIP on Algo Trader Plus ($99/mo) |
| results › row 3 › broker › market data › row 3 | Historical bars + trades + quotes |
| results › row 3 › broker › mcp | official |
| results › row 3 › broker › mcp note | Official MCP V2, 61 actions, idempotent order submission |
| results › row 3 › broker › assets › stocks | true |
| results › row 3 › broker › assets › options | true |
| results › row 3 › broker › assets › futures | false |
| results › row 3 › broker › assets › crypto | true |
| results › row 3 › broker › assets › forex | false |
| results › row 3 › broker › assets › bonds | false |
| results › row 3 › broker › account minimum | 0 |
| results › row 3 › broker › commission | $0 (PFOF on equities) |
| results › row 3 › broker › good for | Solo AI operator, paper-to-live parity |
| results › row 3 › broker › has free tier | true |
| results › row 3 › broker › notes › row 1 | Free paper trading with same API surface as live |
| results › row 3 › broker › notes › row 2 | Options require Algo Trader Plus tier |
| results › row 3 › broker › notes › row 3 | Python/Go SDKs mature; rate-limit backoff documented |
| results › row 3 › score | 1 |
| results › row 3 › max score | 2 |
| results › row 3 › fits | false |
| results › row 3 › fail reasons › row 1 | Futures |
| results › row 4 › broker › id | tradier |
| results › row 4 › broker › name | Tradier |
| results › row 4 › broker › url | https://tradier.com/ |
| results › row 4 › broker › docs url | https://developer.tradier.com/ |
| results › row 4 › broker › auth | OAuth 2.0 |
| results › row 4 › broker › auth complexity | 3 |
| results › row 4 › broker › order types (8 items) | [...] |
| results › row 4 › broker › rate limits | 120 req/min market data, 60 req/min trading |
| results › row 4 › broker › market data › row 1 | Real-time equities + options (streaming) |
| results › row 4 › broker › market data › row 2 | Historical OHLC back ~5 years |
| results › row 4 › broker › market data › row 3 | No Level-2 depth |
| results › row 4 › broker › mcp | community |
| results › row 4 › broker › mcp note | Community MCP; idempotency is a manual patch |
| results › row 4 › broker › assets › stocks | true |
| results › row 4 › broker › assets › options | true |
| results › row 4 › broker › assets › futures | false |
| results › row 4 › broker › assets › crypto | false |
| results › row 4 › broker › assets › forex | false |
| results › row 4 › broker › assets › bonds | false |
| results › row 4 › broker › account minimum | 0 |
| results › row 4 › broker › commission | $0 equities (PFOF), $0.35/contract options Pro |
| results › row 4 › broker › good for | Options-first retail, multi-leg strategies |
| results › row 4 › broker › has free tier | true |
| results › row 4 › broker › notes › row 1 | Free sandbox with delayed data |
| results › row 4 › broker › notes › row 2 | Strong options chain + multi-leg order API |
| results › row 4 › broker › notes › row 3 | US-only account eligibility |
| results › row 4 › score | 1 |
| results › row 4 › max score | 2 |
| results › row 4 › fits | false |
| results › row 4 › fail reasons › row 1 | Futures |
| results › row 5 › broker › id | robinhood |
| results › row 5 › broker › name | Robinhood |
| results › row 5 › broker › url | https://robinhood.com/ |
| results › row 5 › broker › docs url | https://docs.robinhood.com/ |
| results › row 5 › broker › auth | OAuth 2.0 (unofficial endpoints) |
| results › row 5 › broker › auth complexity | 4 |
| results › row 5 › broker › order types › row 1 | market |
| results › row 5 › broker › order types › row 2 | limit |
| results › row 5 › broker › order types › row 3 | stop |
| results › row 5 › broker › order types › row 4 | stop-limit |
| results › row 5 › broker › order types › row 5 | gtc |
| results › row 5 › broker › order types › row 6 | ioc |
| results › row 5 › broker › rate limits | Not publicly documented; low throughput |
| results › row 5 › broker › market data › row 1 | Delayed quotes in public tier |
| results › row 5 › broker › market data › row 2 | Limited historical depth |
| results › row 5 › broker › market data › row 3 | No public Level-2 |
| results › row 5 › broker › mcp | none |
| results › row 5 › broker › mcp note | No MCP; unofficial SDKs only |
| results › row 5 › broker › assets › stocks | true |
| results › row 5 › broker › assets › options | true |
| results › row 5 › broker › assets › futures | false |
| results › row 5 › broker › assets › crypto | true |
| results › row 5 › broker › assets › forex | false |
| results › row 5 › broker › assets › bonds | false |
| results › row 5 › broker › account minimum | 0 |
| results › row 5 › broker › commission | $0 (PFOF), $5/mo Gold for margin + extras |
| results › row 5 › broker › good for | Casual retail; not recommended for agents |
| results › row 5 › broker › has free tier | true |
| results › row 5 › broker › notes › row 1 | No officially supported public API in 2026 |
| results › row 5 › broker › notes › row 2 | Community SDKs break on auth changes without notice |
| results › row 5 › broker › notes › row 3 | Paper trading unavailable |
| results › row 5 › score | 1 |
| results › row 5 › max score | 2 |
| results › row 5 › fits | false |
| results › row 5 › fail reasons › row 1 | Futures |
| fitting brokers › row 1 › broker › id | schwab |
| fitting brokers › row 1 › broker › name | Schwab |
| fitting brokers › row 1 › broker › url | https://www.schwab.com/ |
| fitting brokers › row 1 › broker › docs url | https://developer.schwab.com/ |
| fitting brokers › row 1 › broker › auth | OAuth 2.0 (3-legged) |
| fitting brokers › row 1 › broker › auth complexity | 4 |
| fitting brokers › row 1 › broker › order types (9 items) | [...] |
| fitting brokers › row 1 › broker › rate limits | 120 req/min per endpoint (published tier) |
| fitting brokers › row 1 › broker › market data › row 1 | Real-time equities + options quotes |
| fitting brokers › row 1 › broker › market data › row 2 | Historical bars (1m to daily) |
| fitting brokers › row 1 › broker › market data › row 3 | No exchange depth via API |
| fitting brokers › row 1 › broker › mcp | none |
| fitting brokers › row 1 › broker › mcp note | No official or listed community MCP server |
| fitting brokers › row 1 › broker › assets › stocks | true |
| fitting brokers › row 1 › broker › assets › options | true |
| fitting brokers › row 1 › broker › assets › futures | true |
| fitting brokers › row 1 › broker › assets › crypto | false |
| fitting brokers › row 1 › broker › assets › forex | true |
| fitting brokers › row 1 › broker › assets › bonds | true |
| fitting brokers › row 1 › broker › account minimum | 0 |
| fitting brokers › row 1 › broker › commission | $0 equities, $0.65/contract options |
| fitting brokers › row 1 › broker › good for | Established retail, post-TDA API migration |
| fitting brokers › row 1 › broker › has free tier | true |
| fitting brokers › row 1 › broker › notes › row 1 | API rebuilt after TD Ameritrade integration; still maturing |
| fitting brokers › row 1 › broker › notes › row 2 | Requires individual developer registration and app review |
| fitting brokers › row 1 › broker › notes › row 3 | Token refresh flow is finicky vs Alpaca/Tradier |
| fitting brokers › row 1 › score | 2 |
| fitting brokers › row 1 › max score | 2 |
| fitting brokers › row 1 › fits | true |
| fitting brokers › row 2 › broker › id | ibkr |
| fitting brokers › row 2 › broker › name | Interactive Brokers |
| fitting brokers › row 2 › broker › url | https://www.interactivebrokers.com/ |
| fitting brokers › row 2 › broker › docs url | https://www.interactivebrokers.com/en/trading/ib-api.php |
| fitting brokers › row 2 › broker › auth | OAuth + TWS/IB Gateway |
| fitting brokers › row 2 › broker › auth complexity | 5 |
| fitting brokers › row 2 › broker › order types (10 items) | [...] |
| fitting brokers › row 2 › broker › rate limits | ~50 msg/sec per connection; 50 orders/sec burst |
| fitting brokers › row 2 › broker › market data › row 1 | Global equities via subscription bundles |
| fitting brokers › row 2 › broker › market data › row 2 | Level-2 depth on most exchanges |
| fitting brokers › row 2 › broker › market data › row 3 | Historical depth across asset classes |
| fitting brokers › row 2 › broker › mcp | community |
| fitting brokers › row 2 › broker › mcp note | Community CLI MCP; audit before production |
| fitting brokers › row 2 › broker › assets › stocks | true |
| fitting brokers › row 2 › broker › assets › options | true |
| fitting brokers › row 2 › broker › assets › futures | true |
| fitting brokers › row 2 › broker › assets › crypto | true |
| fitting brokers › row 2 › broker › assets › forex | true |
| fitting brokers › row 2 › broker › assets › bonds | true |
| fitting brokers › row 2 › broker › account minimum | 0 |
| fitting brokers › row 2 › broker › commission | Tiered per-share or fixed; ~$0.0035/sh tiered |
| fitting brokers › row 2 › broker › good for | Multi-asset-class, international, scale |
| fitting brokers › row 2 › broker › has free tier | false |
| fitting brokers › row 2 › broker › notes › row 1 | Requires TWS or IB Gateway running locally |
| fitting brokers › row 2 › broker › notes › row 2 | Idempotency via client-supplied orderId |
| fitting brokers › row 2 › broker › notes › row 3 | Fully headless gateway is possible but under-documented |
| fitting brokers › row 2 › score | 2 |
| fitting brokers › row 2 › max score | 2 |
| fitting brokers › row 2 › fits | true |
Computed live at build time.
Frequently asked questions
- What is the IBKR TWS API message rate limit?
- The client may send at most 50 messages per second to TWS. Each ticker subscription and cancellation counts as one message. Exceeding the sustained rate eventually causes TWS to close the connection.
- What triggers an IBKR historical-data pacing violation?
- Any of: more than 60 historical requests in a 10-minute window; 6 or more requests for the same contract, exchange, and tick type within 2 seconds; or an identical request repeated within 15 seconds. BID_ASK requests count double, and you may have at most 50 simultaneous open historical requests.
- How do I poll IBKR option chains without hitting rate limits?
- Use reqSecDefOptParams, which returns the full list of expirations and strikes for an underlying without the throttling limitation. The older reqContractDetails approach is throttled and slows down with ambiguous contract definitions.
- How many instruments can IBKR stream at once?
- 100 market-data lines by default, with a minimum of 100. Streaming more than 100 symbols concurrently requires additional lines, which scale with commission activity.