Zerodha Kite Connect API with Python — a Production-Minded Tutorial
The step-by-step tutorial for integrating Kite Connect with Python, including the production gotchas that tutorials skip.
Zerodha Kite Connect API with Python — a Production-Minded Tutorial
Most Kite Connect tutorials show you how to place an order. They don't show you how to keep a live system running for 200 consecutive trading days without a single production incident. This tutorial is the second one.
If you want the basic "hello world" place-order example, the official Kite Connect documentation covers it well. The article below assumes you've done the hello world and are now asking "how do I deploy this for real money?"
Step 1 — Get API access
- Register at
developers.kite.tradewith your Zerodha Kite account - Create a new app — you'll be issued an API key and a one-time-visible API secret (save it; you can't retrieve it later)
- Subscribe to the ₹2,000/month historical data + API package
- Configure the redirect URL — for local development,
http://127.0.0.1/works; for production, use your actual domain
Step 2 — Install the SDK
pip install kiteconnect
The official Python SDK is thin and stable. It exposes roughly 30 REST methods and a WebSocket ticker class.
Step 3 — The three-token authentication dance
Kite Connect uses three tokens:
- API key — public identifier of your app
- API secret — proves you are the registered developer
- Access token — daily session token valid until 06:00 IST next morning
The authentication flow:
from kiteconnect import KiteConnect
kite = KiteConnect(api_key="your_api_key")
# User visits this URL in a browser:
print(kite.login_url())
# After login, Kite redirects to your redirect URL with ?request_token=...
# You capture the request_token, then:
data = kite.generate_session("request_token_here", api_secret="your_api_secret")
access_token = data["access_token"]
kite.set_access_token(access_token)
Production gotcha 1: the access token expires at 06:00 IST every day. A system that starts at 09:15 without fresh authentication fails at the first API call.
Production pattern: a session manager that checks expiry 10 minutes before the actual 06:00 mark, automatically re-authenticates (using TOTP for 2FA automation), and caches the fresh token. About 50 lines of code. Without it, you re-authenticate manually every morning — which is not production.
Step 4 — Place an order
The minimal order placement:
order_id = kite.place_order(
variety=kite.VARIETY_REGULAR,
tradingsymbol="RELIANCE",
exchange=kite.EXCHANGE_NSE,
transaction_type=kite.TRANSACTION_TYPE_BUY,
quantity=1,
product=kite.PRODUCT_MIS, # intraday
order_type=kite.ORDER_TYPE_LIMIT,
price=2900.00,
validity=kite.VALIDITY_DAY,
tag="my-strategy-v1"
)
Production gotcha 2: the returned order_id is NOT confirmation that the order was filled or even accepted. It means Kite received your request. The order then moves through states:
- PUT ORDER REQ RECEIVED
- VALIDATION PENDING
- OPEN PENDING (routed to exchange)
- OPEN (live at exchange)
- COMPLETE / CANCELLED / REJECTED (terminal)
Always query order status after placement:
order_status = kite.order_history(order_id)
For a production system, subscribe to Kite's order-update postback webhook. Zerodha will POST to your endpoint every time the order changes state. Polling is the fallback.
Production gotcha 3: every order should carry a unique tag — ideally a UUID. If you ever have to reconcile "did my order actually go through" after a network timeout, the tag lets you query for it without ambiguity.
Step 5 — Handle errors like they matter
Kite returns 12 error classes you need explicit handlers for:
| HTTP | Class | Meaning | Correct action |
|---|---|---|---|
| 400 | InputException | Invalid parameters | Fix code. Never retry. |
| 401 | TokenException | Access token expired | Re-authenticate. |
| 403 | PermissionException | Product not enabled | Contact Zerodha. Never retry. |
| 429 | NetworkException | Rate limit | Exponential backoff. |
| 500 | NetworkException | Kite backend error | Retry with backoff, max 3 attempts. |
| 502/503/504 | NetworkException | Kite gateway issue | Retry with backoff, max 5 attempts. |
| — | OrderException | OMS rejection | Log. Escalate. Never retry. |
| — | MarginException | Insufficient margin | Halt strategy. Never retry. |
| — | ExchangeException | Exchange reject | Log. Never retry. |
| — | GeneralException | Unknown | Log. Retry once. |
| — | Timeout | Request didn't return | Query order status before retry. |
| — | Connection error | Network down | Reconnect, then retry. |
Production gotcha 4: the most dangerous mistake is to catch all exceptions and retry. That creates duplicate orders on network timeouts. Rule: before retrying ANY write operation (place, modify, cancel), query the current state first.
Step 6 — WebSocket for live ticks
Real-time market data requires the WebSocket connection:
from kiteconnect import KiteTicker
kws = KiteTicker(api_key, access_token)
def on_ticks(ws, ticks):
print(ticks)
def on_connect(ws, response):
ws.subscribe([738561]) # RELIANCE token
ws.set_mode(ws.MODE_FULL, [738561])
kws.on_ticks = on_ticks
kws.on_connect = on_connect
kws.connect()
Three subscription modes:
- LTP — last traded price only, smallest payload
- Quote — price + OHLC + volume + top-of-book depth
- Full — everything plus 5-level order book depth
Production gotcha 5: the WebSocket disconnects. Regularly. Without reconnect logic, your strategy runs on stale data silently. The standard reconnect protocol:
- Detect disconnect (via
on_closecallback, or 60-second tick timeout) - Emit
BrokerDisconnectedEventto pause strategies - Exponential backoff: 1s → 2s → 4s → 8s → 16s → 30s
- Reconnect
- Resubscribe to all previously subscribed tokens
- Emit
BrokerReconnectedEvent - Reconcile positions via REST API
- Resume strategy submissions
All 8 steps. Skipping any one creates silent bugs.
Step 7 — Rate limits
Kite Connect rate limits (current as of 2026):
- Order placement: 10 requests/second, 200/minute
- Order modification/cancellation: 25/second
- Quote/LTP: 1 request/second per instrument list
- Historical data: 3 requests/second
A token-bucket rate limiter per endpoint category prevents 429 errors and IP bans. The aiolimiter Python library does this in ~20 lines of code.
Step 8 — Reconciliation on startup
Before your strategy resumes trading after any restart (cold start, cloud VM reboot, WebSocket reconnect), reconcile:
- Fetch broker positions via
/portfolio/positions - Fetch open orders via
/orders - Compare against your event-log's projected state
- Resolve mismatches BEFORE allowing new orders
Production gotcha 6: never trust that your system's internal state matches the broker's after any outage. Reconcile every time, without exception. The reconciliation step catches the bugs that would otherwise compound into catastrophic losses.
Step 9 — Deployment with secrets hygiene
Keep your API secret and daily access token out of source code. Three acceptable storage patterns:
- Cloud secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault) — read at runtime via IAM. Best for production.
.envfile with 0600 permissions, gitignored — fine for solo retail at scale < ₹50 lakh.- OS keychain (macOS Keychain, Windows Credential Manager) — fine for local development.
Never:
- Hardcode secrets in
.pyfiles - Commit secrets to Git, even in a private repo
- Email secrets, even to yourself
- Store secrets in a shared Google Sheet
Secret scanners index public GitHub constantly. A leaked Kite API secret on GitHub can drain a trading account in minutes.
The minimal production stack
Pulling the above together, the minimal production stack for a live Kite Connect retail algo system:
- Hosting: AWS ap-south-1 Mumbai, t3.small VM (~₹1,800/month)
- Deployment: Docker container, non-root user, HEALTHCHECK, systemd auto-restart
- Secrets: AWS Secrets Manager or
.envwith strict perms - Session: auto-reauthenticating session manager with TOTP
- Rate limiting: per-endpoint token-bucket
- WebSocket: 8-step reconnect protocol
- State: event-driven architecture with immutable event log; reconciliation on startup
- Monitoring: Prometheus + Grafana; Telegram alerts on the 6 must-monitor metrics
- Kill-switches: 4 levels, automated, non-overridable
Setup time for a first-time developer: 4-6 weeks end to end, including learning the Python scientific stack.
How Bharath Shiksha fits
Stage 5 Volume 3 (Broker Integration) is 75 minutes of main programme on this exact material, with a 14-page worksheet that walks through a session manager implementation, the 12 error classes, and the 8-step reconnect protocol with worked-through code.
Stage 5 as a whole is 5 volumes covering research-to-production, event-driven architecture, broker integration, deployment infrastructure, and the live deployment playbook. Priced at ₹16,999.
For the full retail-to-production path, the bundle of all 30 volumes is ₹39,999 at bharathshiksha.com.
Educational material. This tutorial is not affiliated with Zerodha. Always verify current rate limits, fees, and API behaviour against official Kite Connect documentation. Trading involves risk of capital loss.
Related reading
- How to Start Algo Trading in India — a Step-by-Step Path for Retail Traders
- Pandas Backtesting for Indian Equities: A Working Tutorial
- Cointegration Pairs Trading on NSE — a Working Example with Reliance and ONGC
Ready to go deeper than this article?
Bharath Shiksha is a 30-volume curriculum across 6 stages — from chart reading (Stage 1 at ₹2,999) through capital raising (Stage 6 at ₹18,999), or the full bundle at ₹39,999. Every volume has a 14-page companion worksheet, a 10-question gate quiz, and a 7-day money-back guarantee.
See the full curriculum →