📖 Guides

Interactive Brokers TWS API: 'Market Data Not Subscribed' — How to Fix Every Cause (2026)

⚠️ Disclosure: Some links on this page are affiliate links. If you sign up through them, I may earn a commission — at no extra cost to you. I only review tools I actually use.

The Error That Stops Every IB Bot Builder

You write your first reqMktData call. You connect to TWS or IB Gateway. And instead of streaming prices, you get this:

Error 354: Requested market data is not subscribed.
Delayed market data is available.

Or the even more cryptic variant:

Error 10167: Requested market data is not subscribed.
Displaying delayed market data.

I have been running a production USDJPY momentum strategy on IB Gateway for months. I have hit both of these errors — during initial setup, after account changes, and when switching between paper and live environments. Every time, the root cause was one of six specific things.

This guide covers all of them, in order of how likely they are to be your problem.

---

Quick Diagnosis: Which Error Are You Getting?

Before diving into fixes, identify your exact situation:

Error CodeMessageMost Likely Cause
354"Requested market data is not subscribed"Missing market data subscription for that exchange
10167"Requested market data is not subscribed. Displaying delayed market data"Same as 354, but TWS is falling back to delayed data
10168"Market data farm connection is inactive"TWS/Gateway not connected to data servers
2104"Market data farm connection is OK"Not an error — this is a status message confirming connection
If you are seeing 354 or 10167, keep reading. If you are seeing 10168, skip to the connection issues section.

---

Fix 1: You Actually Need a Market Data Subscription (Most Common)

This is the cause 80% of the time. Interactive Brokers requires active market data subscriptions for most exchanges — and the subscriptions you need depend on *what* you are trading.

How to Check Your Current Subscriptions

1. Log in to Client Portal

2. Go to Settings → User Settings → Market Data Subscriptions 3. You will see a list of your active subscriptions (or an empty list if you have none)

What You Need by Asset Class

US Stocks (NYSE, NASDAQ, ARCA):
SubscriptionMonthly CostWhat It Covers
US Securities Snapshot & Futures Value Bundle$10.00NYSE, NASDAQ, AMEX, ARCA — streaming L1
US Equity and Options Add-On Streaming Bundle$4.50Adds streaming (vs snapshot-only)
Total for most US stock traders$14.50Or $0 if you trade actively enough
Forex (my setup):

Here is the part that trips up a lot of algo traders: forex market data on IB is free. You do not need to subscribe to anything. IBKR provides IDEAL Pro forex quotes at no charge for funded accounts.

My Python trading bot connects to IB Gateway, calls reqMktData for USDJPY, and gets real-time streaming prices without paying for any market data subscription. Total monthly cost for forex data: $0.00.

But you still need a funded account with at least $500 USD (or equivalent).

Futures (ES, NQ, CL):
SubscriptionMonthly CostWhat It Covers
CME Market Data (Non-Professional)$1.00E-mini S&P 500, E-mini NASDAQ, Micro contracts
NYMEX Market Data$1.00Crude oil (CL), natural gas (NG)
Total for basic futures$2.00Non-professional classification required
Options:

US options data comes bundled with the US Securities Snapshot bundle ($10/mo). No separate subscription needed.

The Free Data Waiver

If you generate at least $30 USD/month in commissions, IB waives up to $30/month in market data fees. For active algo traders, this often means your data subscriptions are effectively free.

Check your commission spend: Client Portal → Reports → Activity → look at monthly commission totals.

---

Fix 2: Paper Trading Account Without Subscriptions

This catches almost every beginner.

The problem: Paper trading accounts on IB do not automatically inherit your live account's market data subscriptions. If you subscribed to US equities data on your live account but are testing your bot on a paper account, you will get error 354. The fix:

Paper accounts get free delayed data (15-20 minutes delayed) by default. To use it in your API code, you need to explicitly request delayed data:

# Python — ib_insync
from ib_insync import *

ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)  # 7497 = paper trading port

# Tell the API to accept delayed data
ib.reqMarketDataType(3)  # 3 = delayed data

contract = Stock('AAPL', 'SMART', 'USD')
ib.qualifyContracts(contract)
ticker = ib.reqMktData(contract)
ib.sleep(2)
print(ticker)

# Python — ibapi (official TWS API)
from ibapi.client import EClient
from ibapi.wrapper import EWrapper

class MyWrapper(EWrapper):
    def error(self, reqId, errorCode, errorString, advancedOrderRejectJson=""):
        print(f"Error {errorCode}: {errorString}")

    def tickPrice(self, reqId, tickType, price, attrib):
        print(f"Price: {price}")

class MyClient(EClient):
    def __init__(self, wrapper):
        EClient.__init__(self, wrapper)

app = MyWrapper()
client = MyClient(app)
client.connect("127.0.0.1", 7497, clientId=1)

# Request delayed market data
client.reqMarketDataType(3)  # 1=live, 2=frozen, 3=delayed, 4=delayed-frozen

Market data types explained:

TypeCodeDescriptionRequires Subscription?
Live1Real-time streamingYes
Frozen2Last available price when market closedYes
Delayed315-20 min delayedNo
Delayed Frozen4Last delayed price when market closedNo
Pro tip: Always call reqMarketDataType *before* your first reqMktData. If you call it after, you may need to cancel and re-request the data.

---

Fix 3: Wrong Contract Definition

The API is extremely picky about contract specifications. A slightly wrong contract will return error 354 even if your subscriptions are correct.

Common mistakes:

# WRONG — missing exchange
contract = Contract()
contract.symbol = "AAPL"
contract.secType = "STK"
contract.currency = "USD"
# Missing: contract.exchange = "SMART"

# WRONG — wrong secType for forex
contract = Contract()
contract.symbol = "USD"
contract.secType = "STK"  # Should be "CASH"
contract.exchange = "IDEALPRO"
contract.currency = "JPY"

# CORRECT — US stock
contract = Contract()
contract.symbol = "AAPL"
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"

# CORRECT — forex pair (how I request USDJPY)
contract = Contract()
contract.symbol = "USD"
contract.secType = "CASH"
contract.exchange = "IDEALPRO"
contract.currency = "JPY"

# CORRECT — E-mini S&P 500 futures
contract = Contract()
contract.symbol = "ES"
contract.secType = "FUT"
contract.exchange = "CME"
contract.currency = "USD"
contract.lastTradeDateOrContractMonth = "202606"  # Must specify expiry

💡 Interactive Brokers

Like what you're reading? Try it yourself — this link supports ChartedTrader at no cost to you.

Open an IBKR Account →

The debug trick: Use reqContractDetails to verify IB recognizes your contract before requesting market data:

# ib_insync
from ib_insync import *

ib = IB()
ib.connect('127.0.0.1', 7496, clientId=1)

contract = Stock('AAPL', 'SMART', 'USD')
details = ib.reqContractDetails(contract)

if details:
    print(f"Found: {details[0].contract.symbol} on {details[0].contract.exchange}")
    print(f"Market data requires: check subscriptions for {details[0].contract.primaryExchange}")
else:
    print("Contract not found — fix your contract definition first")

If reqContractDetails returns nothing, your contract definition is wrong. Fix that before troubleshooting subscriptions.

---

Fix 4: Professional vs Non-Professional Classification

This is the silent budget killer. IB classifies users as either Professional or Non-Professional for market data pricing. The difference is massive:

Data BundleNon-ProfessionalProfessional
US Securities Snapshot & Futures Value Bundle$10/mo$125/mo
CME Real-Time Data$1/mo$85/mo
NASDAQ TotalView (Level 2)$1.50/mo$25/mo
When you first open your IB account, you are asked to fill out a market data questionnaire. If you answer "yes" to any of these, IB classifies you as Professional: How to check: Client Portal → Settings → User Settings → Market Data Subscriber Status If you were wrongly classified as Professional: Contact IB support to re-classify. You may need to fill out a new non-professional questionnaire. This alone can save you $100+/month.

---

Fix 5: Exceeded Market Data Lines Limit

IB limits the number of concurrent market data lines (tickers you can stream simultaneously). The default is 100 lines for accounts generating less than $40/month in commissions.

If your bot requests data for 150 symbols, symbols beyond the limit will throw errors.

How to check your limit:

# The API does not directly report your line limit.
# But you can see it in Client Portal:
# Settings → User Settings → Market Data → Streaming Market Data Lines

How to increase it:

Workaround for bots: If you only need data for a few symbols at a time, cancel market data requests for symbols you are done with before requesting new ones:

# ib_insync — rotate through symbols
for symbol in large_symbol_list:
    contract = Stock(symbol, 'SMART', 'USD')
    ticker = ib.reqMktData(contract)
    ib.sleep(2)
    # Process data...
    ib.cancelMktData(contract)  # Free up the line

---

Fix 6: TWS/Gateway Connection and Port Issues

Sometimes error 354 is actually a connection problem masquerading as a subscription issue.

Verify your connection:
PlatformDefault Port (Live)Default Port (Paper)
TWS74967497
IB Gateway40014002
Common connection mistakes:

1. Connecting to paper port (7497/4002) when you meant live (7496/4001) — paper has no subscriptions by default

2. API connections not enabled — In TWS: Edit → Global Configuration → API → Settings → Enable ActiveX and Socket Clients 3. IB Gateway not authenticated — Gateway needs IB Key 2FA on every restart. If authentication failed silently, you will get data errors instead of connection errors.

If you are running IB Gateway for automated trading, I wrote a detailed guide on fixing IB Key 2FA issues — the most common reason Gateway fails to authenticate after a restart.

Quick connection test:

from ib_insync import *

ib = IB()
try:
    ib.connect('127.0.0.1', 4001, clientId=1)
    print(f"Connected: {ib.isConnected()}")
    print(f"Accounts: {ib.managedAccounts()}")

    # Check connection to data farms
    # If this returns empty, data farm connection failed
    ib.reqMarketDataType(1)
    contract = Forex('USDJPY')
    ticker = ib.reqMktData(contract)
    ib.sleep(3)

    if ticker.last != ticker.last:  # NaN check
        print("No data received — check data farm connection")
    else:
        print(f"USDJPY: {ticker.last}")
except Exception as e:
    print(f"Connection failed: {e}")
finally:
    ib.disconnect()

---

My Production Setup: What Actually Works

Here is the exact configuration running my USDJPY momentum strategy on IB Gateway, with zero market data errors for months:

Environment: Startup sequence in my trading daemon:

import asyncio
from ib_insync import *

async def connect_and_verify():
    ib = IB()
    await ib.connectAsync('127.0.0.1', 4001, clientId=1)

    # Always set market data type explicitly
    ib.reqMarketDataType(1)  # 1 = live streaming

    # Verify data connection with a known contract
    contract = Forex('USDJPY')
    ib.qualifyContracts(contract)
    ticker = ib.reqMktData(contract)

    await asyncio.sleep(3)

    if ticker.last != ticker.last:  # NaN = no data
        raise RuntimeError("Market data not flowing — check Gateway auth and subscriptions")

    print(f"Data OK — USDJPY: {ticker.last}")
    return ib

Key lessons from production:

1. Always call reqMarketDataType before any data request, every time you connect 2. Verify data is actually flowing with a canary request (I use USDJPY since it is free) 3. If Gateway restarts, re-authenticate IB Key 2FA *before* your bot reconnects — otherwise you get silent data failures 4. Use clientId consistently — if another process already connected with the same clientId, your data requests may not work

---

The Complete Troubleshooting Checklist

Run through this when you hit "market data not subscribed":

Nine times out of ten, the fix is one of the first three items on this list.

---

Still Stuck? Three More Things to Try

1. Restart TWS/Gateway completely. Not just reconnect your bot — close TWS/Gateway, re-authenticate with IB Key, and start fresh. Stale sessions can cause phantom data errors. 2. Check IB system status. Occasionally IB's data farms have outages. Check the IB System Status page before spending hours debugging your code. 3. Call IB support. If your subscription looks correct but data still will not flow, IB support can check if there is a backend issue with your account's data entitlements. This has happened to me once — a subscription was marked as active in Client Portal but not actually provisioned on the backend. Support fixed it in minutes.

---

What to Read Next

If you are building an automated trading system on Interactive Brokers, these guides cover the rest of the stack:

*I run a live USDJPY momentum strategy on Interactive Brokers. If you are building your own algo trading system, IBKR's referral program gives new accounts up to $1,000 in IBKR stock — which helps offset those first few months of market data subscriptions.*
Interactive Brokers

Ready to get started? Use the link below — it helps support ChartedTrader at no cost to you.

Open an IBKR Account →
📈

About the author

I'm a systematic trader running live strategies on IB (USDJPY momentum) and Hyperliquid (crypto perps). Every tool reviewed here is something I've used with real capital. Questions? Reach out.

📚 Related Articles

📖 Guides

TradingView Broker Connection Not Working? How to Fix Every Order Panel Error (2026 Guide)

TradingView broker connection failing? This step-by-step troubleshooting guide covers every common error — from "Not Connected" and login failures to order panel glitches, session limits, and reconnection issues. Includes fixes for OKX, Interactive Brokers, OANDA, and other integrated brokers in 2026.

March 28, 2026 ⏱ 17 min read
📖 Guides

Hyperliquid Gasless Trading and HYPE Staking Fee Discounts: How to Pay Less in 2026

Hyperliquid charges zero gas fees on orders, cancellations, and modifications. Stake HYPE tokens for up to 40% off trading fees. This guide covers the full fee structure, staking tiers, maker rebates, and 5 strategies to minimize your trading costs.

March 26, 2026 ⏱ 13 min read
📖 Guides

Forex Tester Prop Firm Challenge Mode: Practice FTMO & FundedNext Evaluations Risk-Free (2026)

Learn how to use Forex Tester Online's prop firm challenge simulation to practice FTMO, FundedNext, and other funded account evaluations without risking real fees. Step-by-step setup with realistic rules, drawdown tracking, and strategies that actually pass.

March 26, 2026 ⏱ 13 min read

📬 Get weekly trading insights

Real trades, honest reviews, no fluff. One email per week.