How to generate the request_token and access_token on Kite Connect

From WebNotes, a public knowledge base. Last updated . Reading time ~9 min. Level: Intermediate.

Every Kite Connect API session requires a fresh access_token that is valid for the current trading day. Generating an access_token involves a two-step OAuth-style flow: the user logs in through Zerodha’s browser-based consent screen to obtain a request_token, and the server then exchanges that request_token, along with a cryptographic checksum, for an access_token. This guide explains both steps using the official kiteconnect Python SDK.

How the token flow works

Kite Connect’s authentication is modelled on OAuth 2.0 with a custom checksum step. The flow has three actors: your application, the user’s browser, and Zerodha’s API server.

  1. Login URL. Your application constructs a URL pointing to kite.trade/connect/login and includes your api_key as a query parameter. When a user visits this URL, Zerodha displays its standard login page (client ID, password, TOTP).

  2. request_token. After the user successfully authenticates, Zerodha redirects their browser to your registered redirect URL and appends a request_token in the query string. This token is short-lived and single-use.

  3. Checksum and exchange. Your server computes a SHA-256 hash of the concatenated string api_key + request_token + api_secret. It then sends this hash along with the request_token and api_key to POST /session/token. Zerodha verifies the hash (proving you possess the api_secret) and returns the access_token.

  4. access_token use. Every subsequent API call includes the access_token in the Authorization header (or the SDK injects it automatically). The access_token expires the following trading day at 6:00 AM IST and must be regenerated.

This design ensures the api_secret is never sent over the network as plaintext. Only its cryptographic contribution, as part of the SHA-256 hash, is transmitted.

Step-by-step procedure

Install the kiteconnect SDK

pip install kiteconnect

Verify the installation:

python -c "import kiteconnect; print(kiteconnect.__version__)"

The SDK wraps all REST calls and WebSocket connections. Refer to the kiteconnect Python SDK repository for the full changelog and version history.

Initialise the KiteConnect object

import os
from kiteconnect import KiteConnect

API_KEY = os.environ["KITE_API_KEY"]
API_SECRET = os.environ["KITE_API_SECRET"]

kite = KiteConnect(api_key=API_KEY)

Instantiating KiteConnect does not make any network request. It stores the api_key and configures the HTTP session, base URL, and timeout parameters.

Generate and open the login URL

login_url = kite.login_url()
print(login_url)

This prints a URL of the form:

https://kite.trade/connect/login?api_key=xxxxxxxxxxxxxxxx&v=3

Open this URL in a web browser. On a server or headless environment you may print the URL, open it manually on any browser, and then transfer the request_token to your script. For automated setups, see How to authenticate Kite Connect with TOTP automation.

The user completes the standard Zerodha login: client ID, password, and TOTP. After the final authentication step, Zerodha redirects the browser to your registered redirect URL.

Capture the request_token

After login the browser address bar shows a URL like:

https://your-redirect-url/?request_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&action=login&status=success

Extract the request_token value. In an automated setup, your server captures it programmatically from the query string of the incoming request. In a manual workflow, copy the value from the address bar.

# Manual development workflow, paste from address bar
request_token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

The request_token is single-use and expires after a short window (a few minutes). Do not delay the next step.

Exchange the request_token for an access_token

session_data = kite.generate_session(request_token, api_secret=API_SECRET)
access_token = session_data["access_token"]
print("access_token:", access_token)

Internally, generate_session computes:

import hashlib
checksum = hashlib.sha256(
    (API_KEY + request_token + API_SECRET).encode("utf-8")
).hexdigest()

It then sends a POST request to https://api.kite.trade/session/token with the api_key, request_token, and checksum. On success the API returns a JSON response containing the access_token, user_id, user_name, email, broker, and other profile fields.

Set the access_token on the client object

kite.set_access_token(access_token)

After this call all further methods on the kite object, kite.profile(), kite.positions(), kite.place_order(...), automatically include the access_token in the Authorization HTTP header.

Persist the access_token

The access_token is valid for the entire trading day. You should save it so that multiple scripts or services running on the same day can reuse it without requiring a fresh browser login.

import json
from pathlib import Path

TOKEN_FILE = Path("/tmp/kite_token.json")

def save_token(access_token: str) -> None:
    TOKEN_FILE.write_text(json.dumps({"access_token": access_token}))

def load_token() -> str | None:
    if TOKEN_FILE.exists():
        return json.loads(TOKEN_FILE.read_text()).get("access_token")
    return None

# After successful generate_session:
save_token(access_token)

# At the start of subsequent scripts:
token = load_token()
if token:
    kite.set_access_token(token)

Store the token file in a path with appropriate OS-level permissions. Do not commit the token file to version control.

Full minimal example

import os
import json
from pathlib import Path
from kiteconnect import KiteConnect

API_KEY = os.environ["KITE_API_KEY"]
API_SECRET = os.environ["KITE_API_SECRET"]
TOKEN_FILE = Path("/tmp/kite_token.json")

kite = KiteConnect(api_key=API_KEY)

# Step 1: generate login URL and open in browser
print("Open this URL to log in:")
print(kite.login_url())

# Step 2: after redirect, paste the request_token
request_token = input("Paste request_token here: ").strip()

# Step 3: exchange for access_token
session_data = kite.generate_session(request_token, api_secret=API_SECRET)
access_token = session_data["access_token"]

# Step 4: set on client and persist
kite.set_access_token(access_token)
TOKEN_FILE.write_text(json.dumps({"access_token": access_token}))

print("Session ready. Profile:", kite.profile()["user_name"])

What can go wrong

  • request_token already used. Each request_token is single-use. Calling generate_session a second time with the same token returns a TokenException. Re-run the browser login to obtain a new token.
  • Checksum mismatch. If the api_secret passed to generate_session does not match the one registered in the developer console, Zerodha returns a TokenException: Invalid checksum. Verify that you are using the correct api_secret from kite.trade/developers/apps.
  • Stale access_token. After 6:00 AM IST on the following trading day, all API calls return TokenException: Invalid token. Scripts that run overnight or early morning must regenerate the token at the start of each day.
  • Redirect URL mismatch. If the redirect URL in your KiteConnect constructor does not match the one registered in the console, Zerodha rejects the authorisation. Ensure the URLs are identical.
  • Network timeout during generate_session. The exchange endpoint at api.kite.trade has a default timeout. If your network is slow, increase the timeout: KiteConnect(api_key=API_KEY, timeout=30).
  • User cancels login. If the user closes the browser without completing login, no request_token is issued and no redirect occurs. Your UI should handle a missing or absent request_token gracefully.

References

  1. Zerodha, Kite Connect authentication documentation, kite.trade/docs/connect/v3/user/, accessed 2024.
  2. kiteconnect Python SDK, generate_session method, github.com/zerodha/pykiteconnect, accessed 2024.
  3. Zerodha Support, Kite Connect access token expiry, support.zerodha.com.
  4. SEBI, Guidelines on algorithmic trading, sebi.gov.in.
  5. Zerodha Z-Connect blog, Building with Kite Connect, zerodha.com/z-connect.

Reviewed and published by

The WebNotes Editorial Team covers Indian capital markets, payments infrastructure and retail investor procedures. Every article is fact-checked against primary sources, principally SEBI circulars and master directions, NPCI specifications and the official support documentation published by the intermediary in question. Drafts go through a second-pair-of-eyes review and a separate compliance read before publication, and revisions are tracked against the SEBI and NPCI rule changes referenced in the methodology section.

Last reviewed
Conflicts of interest
WebNotes is independent. No relationship with any broker, registrar or bank named in this article.