Quotex API with Python — Connect, Read Candles and Automate
Want to connect to Quotex from Python to read prices and place CALL/PUT trades automatically? This page explains how the Quotex API works, shows a minimal Python example, and gives you a free open-source bot that already wraps it all — 13 strategies and a visual dashboard, no coding required.
🤖 Get the free Quotex bot (API ready)
Open-source Python bot using the Quotex API. Edit it by chatting with ChatGPT/Claude — no coding. Free, no spam.
Is there an official Quotex API?
Quotex does not offer an official public API. The community connects to it through the same WebSocket the web platform uses, via open-source Python libraries (the best known is pyquotex). It works, but because it is unofficial it can change without notice, and you should use it on a demo account first.
What you can do with the Quotex API in Python
Install pyquotex (it is not on PyPI)
Searching for "pip install pyquotex" is where most people get stuck: the library is not published on PyPI (in September 2026 pypi.org/project/pyquotex returns "not found"), so pip answers No matching distribution found for pyquotex. It is installed straight from the GitHub repository, whose pyproject.toml requires Python 3.12 or newer:
- Check your version:
python --versionmust show 3.12 or higher (the same version our bot uses). - Create and activate a virtual environment:
python -m venv .venv, then.venv\Scripts\activateon Windows orsource .venv/bin/activateon Linux/macOS. - Install from GitHub:
pip install git+https://github.com/cleitonleonel/pyquotex.git(Git must be installed). The README also documents Poetry:poetry add git+https://github.com/cleitonleonel/pyquotex.git. - Test:
python -c "from pyquotex.stable_api import Quotex"— no output means it worked.
Every method is async: call them with await inside an async def function started by asyncio.run(), as in the examples on this page. Calling client.connect() without await just creates a coroutine and nothing connects.
Connect with Python — minimal example
Using the pyquotex library (included in our bot), a minimal connection looks like this:
# pip install git+https://github.com/cleitonleonel/pyquotex.git (not on PyPI; Python 3.12+)
import time
from pyquotex.stable_api import Quotex
import asyncio
async def main():
client = Quotex(email="you@email.com", password="yourpass")
client.account_is_demo = 1 # always start on demo
ok, reason = await client.connect()
candles = await client.get_candles("EURUSD_otc", time.time(), 3600, 60) # last hour of M1
status, order = await client.buy(1, "EURUSD_otc", "call", 60)
await client.close()
asyncio.run(main())That is the raw API. Turning it into a safe, testable strategy (signals, risk control, payout filter, stop loss) is the hard part — which is exactly what the bot below already does.
pyquotex methods you will actually use
Signatures and return values below were checked in the library source (version 1.1.0, September 2026):
| Method | What it does | Returns / watch out |
|---|---|---|
Quotex(email, password, host="qxbroker.com", lang="pt") | Creates the client | If the default domain is blocked where you live, the README lists alternatives for host: quotex.com, qxbroker.io, quotex.io |
set_account_mode("PRACTICE") | Chooses demo or real before connecting | Only "PRACTICE" or "REAL"; anything else raises ValueError |
await connect() | Logs in and opens the WebSocket | (True, reason) or (False, reason); the session token is saved in session.json |
await change_account("PRACTICE") | Switches demo/real after connecting | Nothing |
await get_balance() | Balance of the active account | A number; raises RuntimeError if not connected |
await get_candles(asset, end_from_time, offset, period) | Candle history | List of dicts (with "close"). offset is seconds of history: 100 M1 candles = 6000 |
await get_available_asset(asset, force_open=True) | Checks whether the asset is open | (name, info); info[2] is True when open. With force_open it switches to the _otc version if the regular one is closed |
get_payout_by_asset(asset) | Payout for 1-minute trades (not async) | A percentage, e.g. 85 |
await buy(amount, asset, "call"/"put", duration) | Places an order; duration in seconds | (status, info); the order ID is info["id"] |
await check_win(order_id, duration) | Waits for the result | ("win" or "loss", profit). Waits up to 300 s and, on timeout, returns ("loss", 0.0) |
await close() | Closes the connection | Always call it at the end |
That last detail matters for statistics: a ("loss", 0.0) can mean "no answer within 5 minutes", not a real loss. A real loss comes with a negative profit; when you get exactly 0.0, confirm the ticket with await client.get_result(order_id), which looks it up in the trade history.
Skip the setup: get the ready-made bot
Instead of wiring the API by hand, download IaTraderPro Bot: it already uses the Quotex API and adds 13 ready strategies (Double Reversal, Exhaustion+Band, RSI Reversal, MACD Cross, SuperTrend+MACD…), a visual Streamlit dashboard, payout filter, daily stop loss/win and configurable martingale. Everything is open source, so you can read and change the code.
Modify it with AI — no coding
Paste bot.py into ChatGPT or Claude, describe the strategy you want in plain English, and the AI returns working code. You paste it back, test on demo, done. That is the real advantage of an open bot over a closed “magic” one.
FAQ
Is it official? No — it uses the community Quotex WebSocket API. Use demo first.
Can my account get banned? Automation carries risk on real accounts; test on demo and read the broker terms.
Is it free? Yes — the bot is free and open source.
Does it work for IQ Option too? Yes, the bot has an IQ Option version as well.
Full example: an RSI bot in 30 lines
The minimal example above only connects and places one order. Below is a genuinely functional bot: it reads the last 100 candles, computes RSI and opens a CALL when oversold (RSI < 30) or a PUT when overbought (RSI > 70), repeating every minute:
# Full example: simple RSI strategy (educational — run on DEMO)
import asyncio, time
from pyquotex.stable_api import Quotex
ASSET, AMOUNT, EXP = "EURUSD_otc", 1, 60
def rsi(closes, period=14):
gains = [max(closes[i+1]-closes[i], 0) for i in range(len(closes)-1)]
losses = [max(closes[i]-closes[i+1], 0) for i in range(len(closes)-1)]
ag = sum(gains[-period:]) / period
al = sum(losses[-period:]) / period or 1e-9
return 100 - 100 / (1 + ag / al)
async def main():
client = Quotex(email="you@email.com", password="yourpass")
client.account_is_demo = 1 # DEMO first, always
ok, _ = await client.connect()
while ok:
candles = await client.get_candles(ASSET, time.time(), 100 * 60, 60) # 100 M1 candles
closes = [c["close"] for c in candles]
r = rsi(closes)
if r < 30: # oversold → CALL
await client.buy(AMOUNT, ASSET, "call", EXP)
elif r > 70: # overbought → PUT
await client.buy(AMOUNT, ASSET, "put", EXP)
await asyncio.sleep(60)
asyncio.run(main())That is the skeleton of every Quotex bot: read candles → compute indicator → decide → place order. What separates this example from a bot you can run daily is the protection layer: daily stop loss/win, minimum payout filter, losing-streak limit and trade logging — everything the IaTraderPro Bot ships with out of the box.
How the connection works under the hood (WebSocket)
Understanding the mechanism helps you diagnose problems. Quotex's web platform talks to its servers over a WebSocket channel (wss://) — the same one that streams the live chart to your browser. The Python libraries do exactly what the browser does:
- Login: they authenticate with e-mail/password and store the session cookies (which is why sessions expire and you sometimes need to reconnect).
- Data subscription: they request the tick/candle stream for the chosen asset and receive continuous JSON with price, time and volume.
- Orders: placing a CALL/PUT means sending a message on the same channel with asset, amount, direction and expiry; the broker replies with the order ID and later the result.
- Keepalive: a periodic ping keeps the channel open — unstable connections kill bots, which is why a stable network matters more than CPU.
This is also why unofficial APIs break from time to time: whenever Quotex changes its internal protocol, the libraries must be updated. Prefer actively maintained GitHub projects and avoid "frozen" copies from courses and groups.
Common connection errors (and fixes)
“Connection failed” or timeout — usually an expired session. Delete the library's saved session (the session.json file) and reconnect; confirm your e-mail and password by logging in manually in the browser.
SSL/certificate error — update Python to 3.12+ and the certifi package (pip install -U certifi). Corporate proxies may block the WebSocket.
Account with 2FA/verification — on first connection Quotex may e-mail you a PIN code. Current libraries prompt for it in the terminal; type it once and the session is saved.
“Asset is closed” — the asset is outside market hours. Use _otc pairs on weekends and check the payout before trading (below 80% rarely pays off).
Order not executing — check the balance of the selected account (demo vs real) and the minimum order amount ($1).
No matching distribution found for pyquotex — the package is not on PyPI; install it from GitHub (see above). requires a different Python means your Python is older than 3.12.
Site or WebSocket does not open in your country — try another host from the README list (quotex.com, qxbroker.io, quotex.io) when creating Quotex(...).
ValueError: Invalid balance mode — set_account_mode() only accepts "PRACTICE" or "REAL"; "DEMO" is not valid.
2FA without a terminal (a service or a Streamlit panel) — the library calls input() for the PIN, which blocks forever when nobody is typing. Pass on_otp_callback= a function that returns the code, or log in once in a terminal so session.json is created.
Risk-management best practices for bots
- Demo first, always: run any change for at least a few days on demo before considering a real account.
- Daily stops: set a daily stop loss and stop win (e.g. −5% / +10% of the bankroll) — the bot stops by itself and you don't give profits back.
- Small stakes: 1–2% of the bankroll per trade; martingale multiplies wins and losses.
- Payout filter: only trade assets paying 80%+ — low payout destroys any strategy long term.
- Logging: follow the dashboard statistics to learn which strategy works at which hours.
- Credentials out of the code: read e-mail and password from environment variables (
os.environ["QX_EMAIL"]) and never commitsession.json— it holds your login token.
Payout, OTC and expiry: the numbers before you trade
get_payout_by_asset() returns a percentage. Convert it and compute the win rate you need to break even: break-even = 1 / (1 + payout). At 85% that is 54.1%; at 80%, 55.6%; at 70%, 58.8%. The expected result per $1 is p × payout − (1 − p).
| Situation | Win rate | Payout | Result per $1 |
|---|---|---|---|
| OTC pair (random in our test) | ~50% | 85% | −$0.075 |
| Real-market pair, good strategy | 57% | 85% | +$0.055 |
| Same strategy, low payout | 57% | 70% | −$0.031 |
The examples on this page use EURUSD_otc only because OTC is open on weekends and makes testing easy. In our study of real candles, OTC results were statistically random (~50%) — below break-even at any payout (details). Two other results from the same study are easy to apply through the API: an expiry of 2 candles beat 1 candle by about 3 points (60.8% vs 57.5% for Exhaustion+Band), which in pyquotex is buy(..., 120) on M1; and the edge concentrated at 9–10h and 18–23h (UTC−3), with Friday the weakest day (trading hours, all tested strategies).
→ Trading from India? Read this first: is Quotex legal in India?
⚠️ Binary options involve high risk and can result in total loss. This content is educational and not investment advice. No bot guarantees profit. Always test on a demo account first.