# Scalping through the IBKR API: what the TWS API can and cannot do

> IBKR API scalping, from building a trading app on the TWS API: market data lines, Level 2 and tick-by-tick caps, pacing, scanner limits, pre-market stops.

Source: https://scalpeltrade.com/blog/tws-api-scalping
By Scalpel Team. Published 2026-09-23, last changed 2026-10-15. 12 min read.

**In short:**

You can scalp through the Interactive Brokers TWS API: orders, Level 2, tick-by-tick prints and IBKR's market scanner all work, including in the pre-market. The limits are what shape the tool. A default account gets 100 market data lines, only 3 Level 2 books and 5 tick-by-tick streams at once, 50 API requests a second, and 10 scanner subscriptions of 50 rows each. Stop orders cannot protect a pre-market trade, so a scalping app has to watch its own exits.

We built Scalpel, a Rust desktop trading cockpit, on the TWS API. Every quote, Level 2 row, print, scan and LIVE order in it goes through the API socket of TWS or IB Gateway on the trader's own machine. This post is what we learned: the documented limits that matter for a scalper, the undocumented behavior we hit, and the design choices they forced. The scanner findings come from a live TWS session in October 2026; the limits were checked against IBKR's documentation on October 15, 2026. Scalpel is independent and not affiliated with or endorsed by Interactive Brokers.

## How the TWS API works

The TWS API is not a web API. Your program opens a TCP socket to TWS or IB Gateway, which must be running and logged in, and those programs talk to IBKR's servers for you. Three consequences follow:

- **The API can only do what TWS can do.** IBKR says so plainly in its [API limitations](https://www.interactivebrokers.com/docs/tws-api/doc/notes-limitations/tws-api-limitations): if a feature is not in TWS, it is not in the API. Every check and every rejection happens in TWS or on IBKR's servers, not in your code.
- **A human logs in.** IBKR states that a headless session is not supported: someone types the username and password and approves two-factor. Both programs are built to restart daily, and you re-authenticate once a week ([details](https://www.interactivebrokers.com/docs/tws-api/doc/architecture/the-trader-workstation/the-ib-gateway)).
- **The API starts closed.** You tick **Enable ActiveX and Socket Clients** in TWS and untick **Read-Only API** before any program can place an order. The [enable TWS API guide](https://scalpeltrade.com/guides/enable-tws-api) has every setting.

Default socket ports are 7496 (TWS live), 7497 (TWS paper), 4001 (IB Gateway live) and 4002 (IB Gateway paper). From the API's point of view TWS and IB Gateway are identical; IB Gateway just has no trading screens. We compare them for day trading in [IB Gateway vs TWS](https://scalpeltrade.com/blog/ib-gateway-vs-tws).

## IB API market data limits: the 100-line budget

Everything you stream costs a market data line, and lines are shared across TWS's own windows and every API connection on the same username. IBKR's [market data lines page](https://www.interactivebrokers.com/docs/general/market-data-subscriptions/market-data-lines/introduction) gives the example: 50 symbols in a TWS watchlist plus 25 on one API connection leaves 25 for a second connection. Go over and requests fail with error 101, "Max number of tickers has been reached".

Every user starts with 100 lines. After the first month the allowance is the greater of 100, monthly commissions in USD divided by 8, or equity times 100 divided by $1,000,000 ([how lines are allocated](https://www.interactivebrokers.com/docs/general/market-data-subscriptions/market-data-lines/how-market-data-is-allocated)). For a small account that means 100. The other way up is a Quote Booster pack: IBKR's [market data pricing page](https://www.interactivebrokers.com/en/pricing/market-data-pricing.php) lists them at USD 30.00 a month for 100 more lines (price checked on October 15, 2026).

To see how many lines you are using, press `Ctrl`+`Alt`+`=` in TWS on Windows.

### Level 2 and tick-by-tick are capped much harder

Depth of book and tick-by-tick prints get their own, much smaller caps, both tied to your line count. From IBKR's [specialized market data lines table](https://www.interactivebrokers.com/docs/general/market-data-subscriptions/market-data-lines/specialized-market-data-lines):

| Market data lines | Tick-by-tick streams | Level 2 books |
| --- | --- | --- |
| 100 (the default) | 5 | 3 |
| 101 to 200 | 10 | 3 |
| 401 to 500 | 25 | 4 |
| 601 to 700 | 35 | 6 |
| 1001 to 1100 | 55 | 10 |

Tick-by-tick scales at 5% of your lines. Level 2 is roughly one book per 100 lines, never fewer than 3. The pricing page adds that each Quote Booster pack brings one more depth-of-book symbol, which the table does not show, so after you change anything, check the real count in TWS rather than trusting either page.

The depth cap counts unique symbols: several windows or requests on the same stock use one slot. Ask for a fourth symbol on a default account and you get error 309, "Max number (3) of market depth requests has been reached".

For a scalper this is the number that decides your layout. A cockpit with one Level 2 per symbol can show three symbols with full depth on a default account. Scalpel runs up to six desks; on a default account the desks past the cap show **Depth unavailable** and keep their quote, chart and tape ([market data guide](https://scalpeltrade.com/guides/ibkr-market-data-for-day-trading)).

### Level 1 is sampled, depth and tick-by-tick are not

This surprises people. The ordinary streaming quote you get from `reqMktData` is not every tick: IBKR's docs describe it as "aggregate snapshots taken several times per second", every 250 ms for US stocks. Market depth "is sent without sampling or filtering", and tick-by-tick data is the same feed as TWS's Time and Sales window.

That matters for exit logic. A pre-market small cap can print through your level and back inside 250 ms: tick-by-tick sees that print, the Level 1 last price may not. Which one you trigger on is a design choice. Tick-by-tick costs one of only 5 streams on a default account; Level 1 is cheap and ignores single-print wicks. Scalpel's desks use tick-by-tick for the tape, SMART depth for the ladder, and the Level 1 stream for the quote line and the last price its stops check. Two more rules from the [tick-by-tick docs](https://www.interactivebrokers.com/docs/tws-api/doc/md/live-ticks): no more than one tick-by-tick request per instrument every 15 seconds, and odd lots are not in the depth feed.

## Pacing violations and the 50 requests a second rule

IBKR paces requests, not data. A subscription costs one request when you open it, however much data it then streams. The current [pacing rule](https://www.interactivebrokers.com/docs/tws-api/doc/pacing-limitations/introduction) is your market data lines divided by 2, per second: 50 requests a second on the default 100 lines.

What happens when you break it is a setting in TWS and IB Gateway, under **API > Settings**: "Reject messages above maximum allowed message rate vs applying pacing". Ticked, you get error 100, and the third breach ends the API session. Unticked, TWS queues your requests and slows you down quietly ([pacing behavior](https://www.interactivebrokers.com/docs/tws-api/doc/pacing-limitations/pacing-behavior)). For an app that also places orders, a quiet queue in front of a sell order is not what you want, so do not lean on it: stay well under the rate.

Historical data has older, stricter rules for bars of 30 seconds or less ([pacing violations for small bars](https://www.interactivebrokers.com/docs/tws-api/doc/market-data-historical/historical-data-limitations/pacing-violations-for-small-bars-30-secs-or-less)):

- No identical historical requests within 15 seconds.
- No six or more requests for the same contract, exchange and tick type within 2 seconds.
- No more than 60 requests in any 10-minute period.
- BID_ASK requests count twice, and bars this small are only kept for six months.

Error 162 is the historical data service error you see when one of these trips. The practical lesson: a trader flipping symbols on a desk can burn 60 history requests in ten minutes without trying. Scalpel loads the 1-minute series first because it is the usual view and the VWAP source, fetches other timeframes in turn, falls back to a shorter span if IBKR rejects the first, and gives background feeds a lighter history (1-minute and 5-minute only) so they do not eat the budget the trader's desks need.

## The IBKR API market scanner: what we found

IBKR's [market scanner over the API](https://www.interactivebrokers.com/docs/tws-api/doc/market-scanner/introduction) is the same engine as TWS's Advanced Market Scanner. It costs nothing extra, which is why Scalpel's scanner is built on it ([set up the IBKR scanner](https://scalpeltrade.com/guides/set-up-ibkr-scanner)). Here is what we found running it against a live account before the open in October 2026.

| What | What we found |
| --- | --- |
| Rows per scan | 50 at most, as documented |
| Simultaneous scans | 10 at a time. The 11th failed with error 322, IBKR's generic "Server error when processing an API client request", not a clear limit message |
| Refresh | About every 30 seconds |
| What comes back | Contracts only: no price, change or volume. You enrich each one with a market data request, which uses a line |
| Pre-market gainers | `TOP_PERC_GAIN` with `priceAbove` and `priceBelow` filters returned real pre-market gainers |
| Gap scans before the open | Open-gap scans such as `HIGH_OPEN_GAP` returned nothing: there is no open yet. They fill at 09:30 ET |
| Float | Refused. `floatSharesBelow` returned error 10360, "Scan filter floatSharesBelow is not allowed" |
| Error 165 | TWS sends it alongside scanner results, sometimes before the data |

Three of those rows cost us time.

**Float is not available.** For a small-cap momentum scanner that hurts, because float is the first thing a trader asks about. The scanner does accept a shares-outstanding cap (`numSharesBelow`), and shares outstanding is never below the float, so it works as a ceiling. For the number shown next to each name, Scalpel reads shares outstanding from SEC EDGAR filings, which are free.

**Contracts only means lines.** A 50-row scan is 50 symbols with no numbers. To rank them live you need quotes, and every quote is a line. Scalpel's list defaults to 30 names for that reason: it leaves room in the 100-line budget for the desks.

**Error 165 can end your stream.** Error 165 is officially the "Historical market Data Service query message", and TWS also sends it with scanner results, as an "N items retrieved" notice. Some client libraries treat any error on a scanner request as the end of the stream. The open-source Rust client we use did, except for the "no items retrieved" form, so the 3-minute volume and halted scans never delivered a single row. We carry a one-line patch that treats every 165 on a scanner request as informational. If your scans connect and then go quiet, check this first.

A minimal pre-market gainers request in IBKR's Python client looks like this:

```python
from ibapi.scanner import ScannerSubscription
from ibapi.tag_value import TagValue

sub = ScannerSubscription()
sub.instrument = "STK"
sub.locationCode = "STK.US.MAJOR"
sub.scanCode = "TOP_PERC_GAIN"
sub.numberOfRows = 50

filters = [TagValue("priceAbove", "1"), TagValue("priceBelow", "20")]
app.reqScannerSubscription(7001, sub, [], filters)
```

Scalpel runs five scans side by side (top gainers, 3-minute volume spikes, halted, hot by volume and gappers) and merges them, so it uses half of the 10-scan allowance. Anything else on the same login that runs API scans shares the rest.

*Screenshot: The IBKR scanner panel in Scalpel: IBKR names the symbols, live quotes supply the change, ranking and volume between IBKR's refreshes. Demo data.*

## Client ids and multiple connections

One TWS or IB Gateway session accepts up to 32 API connections at once, each identified by a client id you choose ([connectivity docs](https://interactivebrokers.github.io/tws-api/connection.html)). Reuse an id that is already connected and TWS turns you away with error 326, "Unable to connect as the client id is already in use".

We use that headroom on purpose: one connection per job.

| Connection | Client id | Carries |
| --- | --- | --- |
| Account | 1 | Account summary, positions, P&L |
| Orders | 2 | LIVE order placement, order status, fills, commissions |
| Desks | 10 and up, one per desk | That desk's Level 2, tick-by-tick prints, quote and bars |
| Scanner quotes | 70 | Level 1 for the names on the scanner list |
| News | 71 | Headlines on the account's IBKR news feeds |
| Scanner | 72 | IBKR's market scans |

The reason is head-of-line blocking. Level 2 on an active small cap is a firehose of inbound messages. If orders shared a socket with it, a sell could sit behind a depth burst. On its own connection, an order message never waits for anyone else's data, and a desk that loses its feed can be torn down and rebuilt without touching orders. Each connection reconnects on its own with capped backoff, so one failure does not take down the rest.

![TWS or IB Gateway linked to six API connections by client id: 1 account, 2 orders, 10 and up for desks, 70 scanner quotes, 71 news and 72 scanner](https://scalpeltrade.com/images/blog/tws-api-scalping/connections.webp)

*One API connection per job, so an order never waits behind a burst of Level 2 data. Splitting sockets adds no data: every connection shares the same limits.*

Two warnings if you do the same. Connections share the account's line, depth and tick-by-tick limits: splitting sockets does not buy you more data. And another API tool on the same machine must not use your client ids, or the two will keep knocking each other off.

## Order types and outsideRth for TWS API day trading

The API can place essentially every order type TWS can: limit, market, stop, stop-limit, trailing, brackets, one-cancels-all groups and IBKR's algos. For extended hours, each order carries an `outsideRth` flag, the API version of TWS's "Fill outside RTH" box. Without it, a limit order sent at 07:00 ET waits for the open.

Before 09:30 and after 16:00 ET, US exchanges run limit-only sessions: every order needs a price ([extended hours](https://scalpeltrade.com/guides/glossary#extended-hours)). Scalpel sends only [marketable limit](https://scalpeltrade.com/guides/glossary#marketable-limit) orders: a buy priced at or above the ask, a sell at or below the bid, with `outsideRth` set when the trader allows extended-hours fills. The same order type works at 06:00 and at 11:00.

Two more things from building the order path:

- **TWS precautions can hold API orders.** TWS has its own size and price warnings. Under **API > Precautions** you can bypass them for API orders. If you do, put your own caps in the app; Scalpel has a fat-finger notional cap and a position cap.
- **Never send an order that waited out a disconnect.** If the order connection drops, an order queued during the gap was priced off a market that has since moved. Scalpel refuses any order that has been waiting more than 2 seconds and tells the trader, rather than sending a stale limit.

## Why stop orders do not work pre-market

This is the single biggest constraint for a pre-market scalper, and the reason Scalpel's stops work the way they do.

A [stop order](https://scalpeltrade.com/guides/glossary#stop-order) becomes a market order when it triggers, and there are no market orders before the open. A [stop-limit](https://scalpeltrade.com/guides/glossary#stop-limit-order) can be set to work outside regular hours, but in a thin pre-market book price can gap straight through its limit, and the order then sits unfilled while the stock falls. We walk through that failure, and what you can do about it in TWS alone, in [why your stop did not trigger in the pre-market](https://scalpeltrade.com/blog/premarket-stop-loss-ibkr).

The API way around it is an app-monitored exit. The app holds the stop, watches the last trade price, and when price trades through the level it sends a marketable limit sell with `outsideRth` set, which the exchange accepts at any session. In Scalpel's LIVE mode that exit is a sell limit 5 cents under the last trade, re-priced if the market runs away from it ([pre-market stops guide](https://scalpeltrade.com/guides/premarket-stops)).

*Screenshot: Price fell through the stop's first exit: that SELL reads Cancelled, and the re-priced SELL sent a second later is Working. Demo data.*

**This can cost you money.**

An app-monitored stop only works while the app runs and its data feed is live. If TWS restarts, the network drops or the app closes, nothing at IBKR protects the position, and no fill is guaranteed even when the exit fires. Anyone building this needs a plan for the link going down, and the trader needs to know where to flatten by hand.

## Latency: what actually affects it

We will not quote a millisecond figure: it depends on your machine, your connection and the stock. What we can say is where the time goes.

1. **Your connection to IBKR.** TWS connects to an IBKR server region; distance and your ISP matter more than anything in your code.
2. **TWS or IB Gateway in the middle.** Every message passes through a Java application on your machine. IBKR suggests a larger **Memory Allocation** for API users (Global Configuration, General) on a machine that can spare it; a starved TWS stalls.
3. **What you subscribe to.** Level 1 arrives as 250 ms snapshots. If your stop logic reads it, that sampling is your floor. Tick-by-tick and depth are not sampled.
4. **Your own queue.** Pacing, a busy shared socket, or a UI thread that handles every depth message before the next order all add delay you control. Scalpel draws the latest book at most about 16 times a second rather than every update, and keeps orders on their own connection.
5. **The route and the book.** An order goes from TWS to IBKR, through its router to a venue. In the pre-market, the book itself is the bigger risk: thin size means your fill price moves more than any processing delay.

For a human scalper reading Level 2, the API path is not the bottleneck. Hesitation, a modal dialog or a mouse is.

## Where Scalpel fits

If you would rather trade than build, Scalpel is this design, finished: up to six desks with Level 2, tape and chart, hotkey entries sized by shares, dollars or risk, app-monitored stops dragged on the chart, IBKR's scanner pre-market included, and SIM against the live book. It is long only, uses only IBKR data and free public sources, and never trades for you. It runs next to TWS or IB Gateway on the same computer: [connect Scalpel to Interactive Brokers](https://scalpeltrade.com/guides/connect-interactive-brokers) walks through it.

If you want a full trading interface without writing code, TWS itself does all of this by hand, and our pillar on [day trading on Interactive Brokers](https://scalpeltrade.com/blog/day-trading-interactive-brokers) covers that setup end to end.

*Trading carries a significant risk of loss. Nothing here is financial advice.*

## Questions

**Can you scalp with the Interactive Brokers API?**

Yes. The TWS API gives you orders, Level 2, tick-by-tick prints and IBKR's scanner, including in the pre-market. The constraints are market data limits, pacing, and the fact that broker stop orders cannot protect a pre-market trade.

**How many market data lines does IBKR give you?**

Every user starts with 100. After the first month it is the greater of 100, monthly commissions divided by 8, or equity times 100 divided by $1,000,000. Quote Booster packs add 100 lines each for a monthly fee.

**How many Level 2 books can I stream through the IBKR API?**

Three on a default account of 100 market data lines. The cap grows with your lines, roughly one book per 100 lines, and counts unique symbols, so several requests for the same stock use one slot.

**What is an IBKR API pacing violation?**

Sending requests faster than IBKR allows: by default 50 requests a second, plus stricter rules for historical data such as no more than 60 historical requests in 10 minutes. TWS either rejects the excess with error 100 or slows your requests down, depending on a setting.

**Can the IBKR API scanner filter by float?**

No. IBKR refuses float as an API scan filter with error 10360. The scanner accepts a shares outstanding cap instead, and shares outstanding can be read from SEC EDGAR filings for free.

**Do stop orders work in the pre-market through the IBKR API?**

Not as protection. A stop becomes a market order, which exchanges do not accept before the open, and a stop-limit can be jumped in a thin book. Pre-market exits need marketable limit orders with outsideRth set, sent by an app that watches the price.
