Indian Historical Market Data Downloader from Zerodha
Project description
PyZData – Indian Historical Market Data Downloader
Download historical OHLCV and Open Interest candle data for any stock, index, or F&O instrument from Zerodha — as a Python library, a CLI command, or a browser-based web app. No API subscription required.
What you can do with PyZData
- Download price history for any stock or index listed on Zerodha (NSE, BSE, NFO, MCX)
- Choose intervals from 1-minute to daily
- Export clean pandas DataFrames ready for backtesting, charting, or ML
- Use the web app — no coding needed
- Use the CLI — one-liner downloads from the terminal
- Use the Python library — import and integrate into your own scripts
Web Interface (no coding required)
The easiest way to use PyZData is the built-in Streamlit web app.
Run it:
pip install "pyzdata[web]"
pyzdata-web
Then open http://localhost:8501 in your browser.
Features:
- Click popular stocks (NIFTY 50, RELIANCE, TCS, HDFC Bank …) — no typing needed
- Quick date presets: Last Week, Last Month, Last Year, Last 3 Years …
- Plain-English frequency selector with descriptions
- Download result as CSV or Excel (.xlsx)
- Built-in Help tab with step-by-step guides
Installation
# Library only (Python API + CLI)
pip install pyzdata
# Library + web interface (adds streamlit and openpyxl)
pip install "pyzdata[web]"
Requirements: Python 3.10+, pandas ≥ 2.0, requests ≥ 2.32
For development:
git clone https://github.com/vikassharma545/Historical-Market-data-From-Zerodha.git
cd Historical-Market-data-From-Zerodha
pip install -e ".[web,dev]"
Python Library
from pyzdata import PyZData, Interval
# Login with enctoken (paste from browser cookies after logging into kite.zerodha.com)
client = PyZData(enctoken="your_enctoken_here")
# OR login with credentials
client = PyZData(user_id="AB1234", password="your_password", totp="123456")
# Find the instrument token for a symbol
token = client.get_instrument_token("NIFTY 50", "NSE")
# Not sure of the exact symbol name? Search for it
results = client.search_instruments("NIFTY", exchange="NSE")
print(results[["tradingsymbol", "instrument_token", "exchange"]])
# Download daily candles for a full year
df = client.get_data(token, "2024-01-01", "2024-12-31", Interval.DAY)
print(df.head())
# Download 1-minute candles with Open Interest (F&O instruments)
fut_token = client.get_instrument_token("NIFTY24JANFUT", "NFO")
df = client.get_data(fut_token, "2024-01-02", "2024-01-25", Interval.MINUTE_1, oi=True)
Output columns: tradingsymbol, datetime, open, high, low, close, volume (+ open_interest when oi=True)
Context manager — automatically closes the HTTP session when done:
with PyZData(enctoken="your_enctoken") as client:
token = client.get_instrument_token("RELIANCE", "NSE")
df = client.get_data(token, "2024-01-01", "2024-12-31", Interval.DAY)
df.to_csv("reliance.csv", index=False)
# session is closed automatically here
CLI
# Daily data for NIFTY 50 — print to terminal
pyzdata download --enctoken TOKEN --symbol "NIFTY 50" --exchange NSE \
--start 2024-01-01 --end 2024-12-31
# 1-minute data — save to CSV
pyzdata download --enctoken TOKEN --symbol RELIANCE --exchange NSE \
--start 2024-01-01 --end 2024-06-30 \
--interval minute --output reliance.csv
# Login with credentials
pyzdata download --user-id AB1234 --password pw --totp 123456 \
--symbol RELIANCE --exchange NSE \
--start 2024-01-01 --end 2024-01-31
# Search for a symbol
pyzdata search --enctoken TOKEN --query HDFC --exchange NSE
# All options
pyzdata download --help
pyzdata search --help
Available Intervals
| Enum | Interval | Best for |
|---|---|---|
Interval.MINUTE_1 |
1 minute | Intraday scalping analysis |
Interval.MINUTE_5 |
5 minutes | Intraday charts |
Interval.MINUTE_15 |
15 minutes | Intraday / short-term |
Interval.MINUTE_30 |
30 minutes | Swing trading |
Interval.HOUR_1 |
1 hour | Swing / positional |
Interval.DAY |
Daily | Long-term investing & backtesting |
Configuration
Copy .env.example to .env and set any values you want to override:
| Variable | Default | Description |
|---|---|---|
PYZDATA_MAX_WORKERS |
4 |
Parallel download threads |
PYZDATA_MAX_RETRIES |
5 |
Retry attempts on failures |
PYZDATA_TIMEOUT |
30 |
HTTP timeout in seconds |
PYZDATA_CACHE_TTL_HOURS |
24 |
How long to cache the instruments list |
PYZDATA_RATE_LIMIT |
3.0 |
Max API requests per second (0 = disabled) |
PYZDATA_LOG_LEVEL |
WARNING |
DEBUG / INFO / WARNING / ERROR |
Or pass a Config object in code:
from pyzdata import Config, PyZData
cfg = Config(max_workers=8, log_level="DEBUG")
client = PyZData(enctoken="...", config=cfg)
Error Handling
from pyzdata.exceptions import (
AuthenticationError, # wrong credentials or expired enctoken
InstrumentNotFoundError, # symbol not found
DataFetchError, # API or network failure
PyZDataError, # catch-all base class
)
try:
client = PyZData(enctoken="...")
token = client.get_instrument_token("RELIANCE", "NSE")
df = client.get_data(token, "2024-01-01", "2024-12-31", Interval.DAY)
except AuthenticationError as e:
print(f"Login failed: {e}")
except InstrumentNotFoundError as e:
print(f"Symbol not found: {e}")
except DataFetchError as e:
print(f"Download failed: {e}")
Project Structure
pyzdata/
├── client.py PyZData — main entry point
├── auth.py Two-step Zerodha login
├── instruments.py Symbol lookup with 24-hour disk cache
├── downloader.py Parallel monthly data fetching
├── models.py Interval enum
├── config.py Settings + environment variable loading
├── exceptions.py Typed exception hierarchy
├── cli.py pyzdata command-line tool
├── _app.py Streamlit web interface
├── run_web.py Entry point for pyzdata-web command
└── py.typed PEP 561 type-checking marker
app.py Local dev launcher for Streamlit
tests/ Unit tests (90 tests, no credentials needed)
CONTRIBUTING.md How to contribute
CHANGELOG.md Release history
SECURITY.md Security policy
Running Tests
pip install -e ".[dev]"
pytest
No Zerodha account or internet connection needed — all HTTP calls are mocked.
How to get your enctoken
- Log in to kite.zerodha.com
- Press F12 → Application tab → Cookies →
kite.zerodha.com - Copy the value of the
enctokencookie - Paste it into the app or pass it as
PyZData(enctoken="...")
The enctoken refreshes each time you log in to Kite.
License
MIT — see LICENSE
Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
Changelog
See CHANGELOG.md for the full release history.
Security
To report a vulnerability, see SECURITY.md.
Author
Built by Vikas Sharma
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyzdata-1.0.6.tar.gz.
File metadata
- Download URL: pyzdata-1.0.6.tar.gz
- Upload date:
- Size: 38.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43f92f4cbc9569d0c73e47308ac59a80471e81b761fec595e2c435f972c86be0
|
|
| MD5 |
b4d2617744b52bd6ed66996734bde4ef
|
|
| BLAKE2b-256 |
1dae8c7b26d7844edbbfc9fa317d4f56760e128b2fea85b76dc5b56f52ca39ed
|
Provenance
The following attestation bundles were made for pyzdata-1.0.6.tar.gz:
Publisher:
publish.yml on vikassharma545/Historical-Market-data-From-Zerodha
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyzdata-1.0.6.tar.gz -
Subject digest:
43f92f4cbc9569d0c73e47308ac59a80471e81b761fec595e2c435f972c86be0 - Sigstore transparency entry: 1191042556
- Sigstore integration time:
-
Permalink:
vikassharma545/Historical-Market-data-From-Zerodha@2d008451906f498b3308067e45c429264f0a32ae -
Branch / Tag:
refs/tags/v1.0.6 - Owner: https://github.com/vikassharma545
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2d008451906f498b3308067e45c429264f0a32ae -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyzdata-1.0.6-py3-none-any.whl.
File metadata
- Download URL: pyzdata-1.0.6-py3-none-any.whl
- Upload date:
- Size: 33.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e17b9012038fbd090fa46075514babc80fe54e3fa20f4b74d233156a3bb4584d
|
|
| MD5 |
7c98fda5e5778e55ab289fe52c1de4c0
|
|
| BLAKE2b-256 |
07ce068c8366763412f68dfe7a8aaad6d949412363a0f79e817382de538b5114
|
Provenance
The following attestation bundles were made for pyzdata-1.0.6-py3-none-any.whl:
Publisher:
publish.yml on vikassharma545/Historical-Market-data-From-Zerodha
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyzdata-1.0.6-py3-none-any.whl -
Subject digest:
e17b9012038fbd090fa46075514babc80fe54e3fa20f4b74d233156a3bb4584d - Sigstore transparency entry: 1191042559
- Sigstore integration time:
-
Permalink:
vikassharma545/Historical-Market-data-From-Zerodha@2d008451906f498b3308067e45c429264f0a32ae -
Branch / Tag:
refs/tags/v1.0.6 - Owner: https://github.com/vikassharma545
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2d008451906f498b3308067e45c429264f0a32ae -
Trigger Event:
release
-
Statement type: