IQ Option API with Python (iqoptionapi) — Connect, Trade and check_win

How to connect to IQ Option from Python using the community iqoptionapi library: log in, read candles, send orders and read the result with check_win_v4. Plus a free open-source bot that already wraps it all.

🤖 Get the free IQ Option bot (API ready)

Open-source Python bot using iqoptionapi. Edit it by chatting with ChatGPT/Claude — no coding. Free, no spam.

Is there an official IQ Option API?

No. IQ Option has no official public API. The community uses the open-source iqoptionapi library, which talks to the same WebSocket the platform uses. It is unofficial — use a demo (practice) account and be aware of ban risk on real accounts.

Install iqoptionapi the right way (virtual environment)

The most common reason the example above fails is the install itself. pip install iqoptionapi downloads the package with that name on PyPI, which is version 0.5, uploaded in October 2016. That release has no stable_api module, so from iqoptionapi.stable_api import IQ_Option fails with ModuleNotFoundError. The community code that has check_win_v4 is maintained on GitHub and must be installed from there:

  1. Create an isolated environment in your project folder: python -m venv .venv
  2. Activate it: .venv\Scripts\activate on Windows, source .venv/bin/activate on Linux/macOS.
  3. If you installed the old package, remove it: pip uninstall iqoptionapi
  4. Install from GitHub over HTTPS: pip install -U git+https://github.com/iqoptionapi/iqoptionapi.git (requires Git). Without Git, use the ZIP link the project README gives: pip install -U https://github.com/iqoptionapi/iqoptionapi/archive/refs/heads/master.zip
  5. Test the import: python -c "from iqoptionapi.stable_api import IQ_Option" — no output means it worked.

Why a virtual environment: the library pins websocket-client==0.56, a very old version. Inside .venv that pin cannot break other Python projects on the same machine. Also ignore the git+git:// command still printed in the project README: GitHub permanently disabled the unencrypted git:// protocol on March 15, 2022, so only the https:// form works.

Connect with Python — minimal example

Login, read candles, buy and read the result with check_win_v4:

# pip install -U git+https://github.com/iqoptionapi/iqoptionapi.git (NOT the PyPI package — see install section) import time from iqoptionapi.stable_api import IQ_Option api = IQ_Option("you@email.com", "yourpass") api.connect() api.change_balance("PRACTICE") # always demo first candles = api.get_candles("EURUSD", 60, 100, time.time()) ok, order_id = api.buy(1, "EURUSD", "call", 1) # 1 = 1-minute expiry result, profit = api.check_win_v4(order_id) # ("win" | "loose" | "equal", profit)

check_win_v4 returns a tuple: a status string — "win", "loose" (the library's own spelling) or "equal" — and the profit as a number (the net gain on a win, minus the stake on a loss, 0 on a tie). It works for binary/turbo options only and waits for the result with no timeout.

Useful iqoptionapi methods

connect() / change_balance()
get_candles()
buy() / buy_digital_spot()
check_win_v4() / get_balance()

What each call actually returns (checked against the stable_api.py source of the GitHub version, 7.1.1):

MethodWhat it doesReturns / watch out
connect()Logs in and opens the WebSocket(True, None) on success, (False, reason) on failure, (False, "2FA") when an SMS code is required
connect_2fa(code)Finishes the login with the SMS codeSame tuple as connect()
change_balance(mode)Selects the account: "PRACTICE", "REAL" or "TOURNAMENT"Any other text (e.g. "DEMO") logs an error and calls exit(1) — your script simply stops
get_balance()Balance of the selected accountA number
get_candles(asset, interval, count, endtime)History; interval in seconds (60 = M1), endtime as a Unix timestampList of candle dicts ("from" = candle start). Unknown asset prints Asset … not found on consts
get_all_open_time()Which assets are open nowNested dict: [type][asset]["open"] = True/False, type such as "turbo", "binary", "digital"
get_all_profit()Payout per assetFractions: {"turbo": 0.85, ...} means 85%
buy(amount, asset, "call"/"put", minutes)Opens a binary/turbo option(True, order_id) or (False, message); after 5 s without confirmation it logs buy late 5 sec and returns (False, None)
check_win_v4(order_id)Waits until the order closes("win" | "loose" | "equal", profit) — blocks with no timeout; binary/turbo only
buy_digital_spot() / check_win_digital_v2()Digital-option equivalentsUse these for digital orders; check_win_v4 never returns for them
check_connect()Is the WebSocket alive?False when the socket has closed

Common errors and how to fix them

SymptomLikely causeFix
ModuleNotFoundError: No module named 'iqoptionapi.stable_api'The 2016 PyPI package (0.5) is installedpip uninstall iqoptionapi, then install from GitHub as shown above
pip fails on a git+git:// URLGitHub no longer serves git://Use git+https://
Import works in one terminal and not in anotherpip installed into a different Python than the one running the scriptActivate the venv and use python -m pip install ...; check python --version (library README: 3.7+; our bot: 3.12+)
connect() returns (False, reason)Wrong e-mail/password or blocked loginPrint reason; log in once in the browser with the same credentials
reason == "2FA"Two-factor login by SMS is enabledapi.connect_2fa(input("SMS code: "))
Script exits right after change_balanceMode text other than PRACTICE/REAL/TOURNAMENTUse exactly "PRACTICE"
Asset EURUSD-op not found on constsAsset missing from constants.ACTIVESInject the ID (see the "-op" section below) or use a listed name
check_win_v4 never returnsDigital order, or the WebSocket dropped before the result arrivedUse check_win_digital_v2 for digital; monitor check_connect()
check_connect() is False after some hoursNetwork drop or expired sessionCall api.connect() again, then change_balance("PRACTICE") again before the next order

Check the payout before every order (the math)

get_all_profit() gives the payout as a fraction, and that single number decides the minimum win rate you need: break-even = 1 / (1 + payout). Expected result per $1 traded = p × payout − (1 − p), where p is your win rate.

PayoutBreak-even win rateResult per $1 at 56% wins
0.90 (90%)52.6%+$0.064
0.85 (85%)54.1%+$0.036
0.80 (80%)55.6%+$0.008
0.70 (70%)58.8%−$0.048

The same 56% win rate goes from a small profit to a steady loss just because payout fell from 85% to 70%. In our own test on real M1 forex candles, the best strategies held ~57–61% out of sample and nothing came close to 70% (full results); on OTC assets the outcome was statistically random at ~50% (why OTC is random). A bot should therefore skip any asset whose payout puts break-even above what the strategy has shown on demo.

Good practices before you automate

  • Keep the password out of the code: read it from environment variables — IQ_Option(os.environ["IQ_EMAIL"], os.environ["IQ_PASSWORD"]) — and never commit a file with credentials to GitHub.
  • Do not type your password into closed .exe files or "robot websites": the library's own README warns that scammers have stolen IQ Option passwords this way. Open-source code runs on your PC and you can read what it does with the password.
  • PRACTICE by default: call change_balance("PRACTICE") at start-up and switch to "REAL" only through an explicit setting, never as the default.
  • Check before buying: get_all_open_time() for the asset, get_all_profit() for the payout, then buy().
  • One candle request per closed candle is enough for M1 strategies; a tight loop only re-downloads the same data.
  • Log every order_id with its check_win_v4 result, so you can compare your real win rate with the break-even table above.

Skip the setup: get the ready-made bot

Our IaTraderPro Bot already uses iqoptionapi and adds 13 ready strategies, a visual Streamlit dashboard, payout filter, daily stop loss/win and configurable martingale — open source, so you read and change the code. It runs on IQ Option demo (PRACTICE) and real accounts — always start on demo.

Modify it with AI — no coding

Paste bot.py into ChatGPT or Claude, describe the strategy you want, get working code back. Paste, test on demo, done.

FAQ

Is it official? No — community library. Use demo first.
What does check_win_v4 do? Waits for a binary/turbo order to close and returns a tuple (status, profit).
Account ban risk? Automation carries risk on real accounts; test on demo and read the terms.
Is it free? Yes — the bot is free and open source. It also supports Quotex.

REAL forex on IQ Option: the "-op" assets (2026 discovery)

IQ Option's legacy API looked dead for real forex: turbo/binary only on OTC and digitals disabled. But in 2026 IQ launched assets with the -op suffix (e.g. USDJPY-op, EURUSD-op) — real forex as binary options, with 2 to 15-minute expirations.

The technical catch: iqoptionapi doesn't list these assets because they don't exist in the library's constants.ACTIVES. The fix (our bot does it automatically) is to inject the "-op" IDs into the dictionary at startup. Two practical notes: verified accounts get broader access to "-op" assets, and payout should be read with a fallback (1 − commission) when the API doesn't return it.

→ Trading from India? Read this first: is Quotex legal in India?

How to inject the "-op" assets (working code)

The library ships a static asset dictionary, so the new real-forex instruments are invisible until you add them. Our bot does this at startup:

# Make the real-forex "-op" assets visible to iqoptionapi from iqoptionapi import constants from iqoptionapi.stable_api import IQ_Option OP_ASSETS = {"USDJPY-op": 1807, "EURUSD-op": 1806, "GBPJPY-op": 1811} constants.ACTIVES.update(OP_ASSETS) # IDs vary by account/region — read them from the API api = IQ_Option("you@email.com", "yourpass") api.connect() api.change_balance("PRACTICE") # demo first, always # payout fallback: some -op assets do not return profit via the usual call def payout(api, asset): d = api.get_all_profit().get(asset, {}) p = d.get("binary") or d.get("turbo") return p # None = no payout returned: skip the asset (iqoptionapi has no get_commission() method) ok, order_id = api.buy(1, "USDJPY-op", "call", 15) # 15-minute binary
ExpiryAvailabilityNotes
2 minEURUSD-op and some majorsFastest; not available on every pair
5 / 10 minMost -op assetsBlitz-style; the library cannot buy blitz directly
15 minUSDJPY-op, GBPJPY-opStandard binary — what our bot uses in production

Two practical notes from running this live: a verified account gets broader access to the -op list, and the asset set changes by region — always read the live list instead of hard-coding it permanently.

⚠️ Binary options involve high risk and can result in total loss. Educational content, not investment advice. No bot guarantees profit. Always test on a demo account first.