Indian Market Data Sources
Ground rules before you fetch anything
- Check the terms of use of every source. NSE, BSE and most commercial providers restrict automated access and redistribution. Public bhavcopy and AMFI files are published for download; undocumented JSON endpoints behind a website are not an API and using them may breach the site's terms.
- Never build a redistribution product on scraped exchange data. Exchange data is licensed. Personal research is a different matter from a hosted service.
- Respect
robots.txt, rate-limit politely, cache aggressively, and identify your client honestly.
- When a source cannot be reached, say so and name what you tried. Never fill a gap with a remembered figure.
The map
| You need |
Source |
Notes |
| Daily OHLC, all listed stocks |
NSE and BSE bhavcopy (daily CSV/ZIP) |
The canonical settlement-grade EOD file |
| Adjusted historical prices |
Yahoo Finance via yfinance, tickers RELIANCE.NS / 500325.BO |
Free, convenient; adjustment errors around Indian corporate actions are common — verify against bhavcopy |
| Index values and constituents |
NSE indices pages; NSE Indices publishes methodology and factsheets |
Free-float methodology; check rebalancing dates |
| Corporate announcements and filings |
NSE / BSE corporate announcements |
See exchange-filings-navigator |
| Shareholding pattern |
NSE / BSE quarterly filings |
See shareholding-pattern-analysis |
| Mutual fund NAVs, all schemes |
AMFI — the consolidated NAV text file, published every business day |
The single best free dataset in Indian finance |
| MF scheme portfolios |
AMC monthly portfolio disclosures; AMFI aggregates |
Monthly, with a lag |
| Fundamentals (P&L, balance sheet, ratios) |
Company filings; screener-type sites for convenience |
Always trace a number back to the filing before publishing it |
| Company master data, charges, financial filings of unlisted entities |
MCA21 |
Paid per document; the only source for subsidiary financials |
| Regulatory orders, circulars |
SEBI website |
|
| Insolvency |
IBBI public announcements, NCLT orders |
|
| Macro: policy rates, money supply, banking, external sector |
RBI — Database on Indian Economy (DBIE), Weekly Statistical Supplement, Handbook of Statistics |
Authoritative |
| Macro: GDP, IIP, CPI, WPI |
MoSPI and the Office of the Economic Adviser |
|
| Government finances, budget |
Union Budget documents; Controller General of Accounts monthly accounts |
|
| Trade data |
Ministry of Commerce, DGCI&S |
|
| FPI and DII flows |
NSDL/CDSL FPI data; exchange daily FII/DII activity reports |
|
| Credit ratings |
CRISIL, ICRA, CARE, India Ratings press releases |
Rationales are a forensic goldmine |
| Commodity prices |
MCX; for physical, the relevant commodity board |
|
| Currency reference rates |
RBI reference rate; FBIL benchmarks |
Use FBIL for anything requiring an official benchmark |
| G-Sec yields, benchmark curve |
CCIL, RBI, FBIL |
The 10Y benchmark is the risk-free rate for dcf-india |
Ticker and identifier conventions
Getting these wrong is the most common cause of a silently wrong dataset.
| Identifier |
Form |
Where used |
| NSE symbol |
RELIANCE, TCS, HDFCBANK |
NSE files, most Indian tools |
| BSE scrip code |
500325, 532540 |
BSE files |
| Yahoo suffix |
.NS for NSE, .BO for BSE |
yfinance |
| ISIN |
INE002A01018 |
The only stable identifier. Use it as the primary key |
| Series |
EQ, BE, SM, ST |
Filter to EQ for normal equity; BE is trade-for-trade surveillance |
Always key your database on ISIN. NSE symbols change on renames, mergers and demergers, and a symbol can be reassigned. Historical series joined on symbol will silently splice two different companies.
Bhavcopy: the workhorse
Both exchanges publish an end-of-day file with OHLC, volume, delivery quantity and series for every scrip. It is the correct base for any Indian backtest.
import io, zipfile, requests, pandas as pd
HEADERS = {"User-Agent": "research-script/1.0 (contact: you@example.com)"}
def fetch_zip_csv(url: str) -> pd.DataFrame:
"""Download a zipped CSV published by an exchange and return it as a DataFrame."""
r = requests.get(url, headers=HEADERS, timeout=30)
r.raise_for_status()
z = zipfile.ZipFile(io.BytesIO(r.content))
name = z.namelist()[0]
return pd.read_csv(z.open(name))
Exchange URL patterns change; check the current archives page rather than hardcoding a path that worked last year. Wrap every fetch so a 404 is reported, not swallowed.
Delivery percentage is published in the NSE securities-wise delivery file and is genuinely useful — a price move on low delivery is speculative positioning, one on high delivery is transfer of ownership.
AMFI NAV file
The most reliable free Indian dataset. A single semicolon-delimited text file with every scheme's NAV.
import requests, pandas as pd, io
URL = "https://portal.amfiindia.com/spages/NAVAll.txt"
def amfi_nav() -> pd.DataFrame:
txt = requests.get(URL, timeout=60).text
rows, amc, scheme_type = [], None, None
for line in txt.splitlines():
line = line.strip()
if not line:
continue
if ";" not in line:
# section headers alternate between scheme type and AMC name
if "Mutual Fund" in line:
amc = line
else:
scheme_type = line
continue
parts = line.split(";")
if parts[0] == "Scheme Code":
continue
rows.append({
"scheme_code": parts[0],
"isin_growth": parts[1] or None,
"isin_div_reinvest": parts[2] or None,
"scheme_name": parts[3],
"nav": pd.to_numeric(parts[4], errors="coerce"),
"date": parts[5],
"amc": amc,
"scheme_type": scheme_type,
})
df = pd.DataFrame(rows)
df["date"] = pd.to_datetime(df["date"], format="%d-%b-%Y", errors="coerce")
return df
Historical NAVs are available from AMFI's NAV history endpoint for a scheme code and date range. Scheme codes are stable; scheme names change on mergers, so key on scheme code or ISIN.
Prices via yfinance
Convenient, not authoritative.
import yfinance as yf
df = yf.download("RELIANCE.NS", start="2015-01-01", auto_adjust=False, progress=False)
# auto_adjust=False keeps raw Close and a separate Adj Close so you can inspect the adjustment
Known failure modes for Indian tickers:
- Corporate action adjustments around bonuses, splits and demergers are frequently wrong or late. Validate against
corporate-actions-india: a 1:1 bonus must show an exact 50% step in raw Close and no step in Adj Close.
- Companies renamed after mergers lose history under the old symbol.
- Volume is often unreliable; use bhavcopy volume.
- Index tickers use
^NSEI (Nifty 50) and ^BSESN (Sensex).
Useful Python libraries
| Library |
Use |
Caveat |
yfinance |
Quick historical prices |
Adjustment quality |
nsepython / jugaad-data |
Wrappers over NSE endpoints — quotes, option chain, bhavcopy |
Community-maintained; break when NSE changes its site. Check the terms of use |
mftool |
AMFI NAV history |
|
pandas-datareader |
Some macro sources |
|
nselib, bsedata |
Exchange helpers |
Same fragility caveat |
Prefer the published files (bhavcopy, AMFI) over any wrapper around an undocumented endpoint. The files are stable, permitted, and do not break.
Data hygiene rules
- Key on ISIN. Store symbol as an attribute, not an identifier.
- Store raw and adjusted separately. Never overwrite raw prices with adjusted ones.
- Record the source and the fetch timestamp on every row or table. Financial data is revised.
- Handle the Indian trading calendar: NSE and BSE holidays do not match any standard calendar library's defaults, there are special Muhurat trading sessions, and there have been occasional weekend sessions. Fetch the exchange's published holiday list rather than assuming.
- Crore and lakh. 1 crore = 10 million; 1 lakh = 0.1 million. Indian filings report in ₹ crore or ₹ lakh, and both appear in the same document. Normalise to one unit at ingestion and record which.
- Face value changes on a split alter the per-share series without any corporate action flag in some sources. Cross-check against the exchange's corporate action file.
- Survivorship bias: a universe built from today's index constituents excludes every delisted and merged company. For any backtest, reconstruct point-in-time index membership from the exchange's historical constituent changes.
- Ex-date on T+1. Under India's T+1 settlement cycle the ex-date coincides with the record date. Code written for T+2 will be one day off on every corporate action.
Output format
When asked where to get something, answer in this shape:
**Source:** <name> — <url or navigation path>
**Format:** <CSV / JSON / PDF>, <frequency>, <history available>
**Identifier:** <ISIN / symbol / scheme code>
**Cost / access:** <free / paid / registration>
**Caveats:** <the two or three things that will bite>
**Snippet:** <minimal working code, if code was asked for>
Hard rules
- Never fabricate a data point. If a fetch fails, report the failure and the URL attempted.
- Never present scraped data as official. Name the source in every output.
- Do not write code that circumvents authentication, rate limits, or a paywall.
- State the as-of date on every number that came from a market data source.
1---2name: market-data-sources-india3description: Find and pull Indian market data from the right source — NSE and BSE bhavcopy, AMFI NAV files, RBI and MoSPI macro series, MCA company filings, SEBI disclosures, and the Python libraries that wrap them — with the ticker conventions, date formats and licensing caveats that trip people up. Use when the user needs Indian stock prices, index data, mutual fund NAVs, corporate filings, macro series, or asks where to get Indian market data or why a data pull is failing.4license: MIT5---67# Indian Market Data Sources89## Ground rules before you fetch anything1011- **Check the terms of use of every source.** NSE, BSE and most commercial providers restrict automated access and redistribution. Public bhavcopy and AMFI files are published for download; undocumented JSON endpoints behind a website are not an API and using them may breach the site's terms.12- **Never build a redistribution product on scraped exchange data.** Exchange data is licensed. Personal research is a different matter from a hosted service.13- Respect `robots.txt`, rate-limit politely, cache aggressively, and identify your client honestly.14- When a source cannot be reached, **say so and name what you tried.** Never fill a gap with a remembered figure.1516## The map1718| You need | Source | Notes |19|---|---|---|20| Daily OHLC, all listed stocks | NSE and BSE **bhavcopy** (daily CSV/ZIP) | The canonical settlement-grade EOD file |21| Adjusted historical prices | Yahoo Finance via `yfinance`, tickers `RELIANCE.NS` / `500325.BO` | Free, convenient; adjustment errors around Indian corporate actions are common — verify against bhavcopy |22| Index values and constituents | NSE indices pages; NSE Indices publishes methodology and factsheets | Free-float methodology; check rebalancing dates |23| Corporate announcements and filings | NSE / BSE corporate announcements | See `exchange-filings-navigator` |24| Shareholding pattern | NSE / BSE quarterly filings | See `shareholding-pattern-analysis` |25| Mutual fund NAVs, all schemes | **AMFI** — the consolidated NAV text file, published every business day | The single best free dataset in Indian finance |26| MF scheme portfolios | AMC monthly portfolio disclosures; AMFI aggregates | Monthly, with a lag |27| Fundamentals (P&L, balance sheet, ratios) | Company filings; screener-type sites for convenience | Always trace a number back to the filing before publishing it |28| Company master data, charges, financial filings of unlisted entities | **MCA21** | Paid per document; the only source for subsidiary financials |29| Regulatory orders, circulars | SEBI website | |30| Insolvency | IBBI public announcements, NCLT orders | |31| Macro: policy rates, money supply, banking, external sector | **RBI** — Database on Indian Economy (DBIE), Weekly Statistical Supplement, Handbook of Statistics | Authoritative |32| Macro: GDP, IIP, CPI, WPI | **MoSPI** and the Office of the Economic Adviser | |33| Government finances, budget | Union Budget documents; Controller General of Accounts monthly accounts | |34| Trade data | Ministry of Commerce, DGCI&S | |35| FPI and DII flows | NSDL/CDSL FPI data; exchange daily FII/DII activity reports | |36| Credit ratings | CRISIL, ICRA, CARE, India Ratings press releases | Rationales are a forensic goldmine |37| Commodity prices | MCX; for physical, the relevant commodity board | |38| Currency reference rates | RBI reference rate; FBIL benchmarks | Use FBIL for anything requiring an official benchmark |39| G-Sec yields, benchmark curve | CCIL, RBI, FBIL | The 10Y benchmark is the risk-free rate for `dcf-india` |4041## Ticker and identifier conventions4243Getting these wrong is the most common cause of a silently wrong dataset.4445| Identifier | Form | Where used |46|---|---|---|47| NSE symbol | `RELIANCE`, `TCS`, `HDFCBANK` | NSE files, most Indian tools |48| BSE scrip code | `500325`, `532540` | BSE files |49| Yahoo suffix | `.NS` for NSE, `.BO` for BSE | `yfinance` |50| **ISIN** | `INE002A01018` | **The only stable identifier.** Use it as the primary key |51| Series | `EQ`, `BE`, `SM`, `ST` | Filter to `EQ` for normal equity; `BE` is trade-for-trade surveillance |5253**Always key your database on ISIN.** NSE symbols change on renames, mergers and demergers, and a symbol can be reassigned. Historical series joined on symbol will silently splice two different companies.5455## Bhavcopy: the workhorse5657Both exchanges publish an end-of-day file with OHLC, volume, delivery quantity and series for every scrip. It is the correct base for any Indian backtest.5859```python60import io, zipfile, requests, pandas as pd6162HEADERS = {"User-Agent": "research-script/1.0 (contact: you@example.com)"}6364def fetch_zip_csv(url: str) -> pd.DataFrame:65 """Download a zipped CSV published by an exchange and return it as a DataFrame."""66 r = requests.get(url, headers=HEADERS, timeout=30)67 r.raise_for_status()68 z = zipfile.ZipFile(io.BytesIO(r.content))69 name = z.namelist()[0]70 return pd.read_csv(z.open(name))71```7273Exchange URL patterns change; check the current archives page rather than hardcoding a path that worked last year. Wrap every fetch so a 404 is reported, not swallowed.7475**Delivery percentage** is published in the NSE securities-wise delivery file and is genuinely useful — a price move on low delivery is speculative positioning, one on high delivery is transfer of ownership.7677## AMFI NAV file7879The most reliable free Indian dataset. A single semicolon-delimited text file with every scheme's NAV.8081```python82import requests, pandas as pd, io8384URL = "https://portal.amfiindia.com/spages/NAVAll.txt"8586def amfi_nav() -> pd.DataFrame:87 txt = requests.get(URL, timeout=60).text88 rows, amc, scheme_type = [], None, None89 for line in txt.splitlines():90 line = line.strip()91 if not line:92 continue93 if ";" not in line:94 # section headers alternate between scheme type and AMC name95 if "Mutual Fund" in line:96 amc = line97 else:98 scheme_type = line99 continue100 parts = line.split(";")101 if parts[0] == "Scheme Code":102 continue103 rows.append({104 "scheme_code": parts[0],105 "isin_growth": parts[1] or None,106 "isin_div_reinvest": parts[2] or None,107 "scheme_name": parts[3],108 "nav": pd.to_numeric(parts[4], errors="coerce"),109 "date": parts[5],110 "amc": amc,111 "scheme_type": scheme_type,112 })113 df = pd.DataFrame(rows)114 df["date"] = pd.to_datetime(df["date"], format="%d-%b-%Y", errors="coerce")115 return df116```117118Historical NAVs are available from AMFI's NAV history endpoint for a scheme code and date range. Scheme codes are stable; scheme *names* change on mergers, so key on scheme code or ISIN.119120## Prices via yfinance121122Convenient, not authoritative.123124```python125import yfinance as yf126127df = yf.download("RELIANCE.NS", start="2015-01-01", auto_adjust=False, progress=False)128# auto_adjust=False keeps raw Close and a separate Adj Close so you can inspect the adjustment129```130131Known failure modes for Indian tickers:132- Corporate action adjustments around bonuses, splits and demergers are frequently wrong or late. **Validate against `corporate-actions-india`**: a 1:1 bonus must show an exact 50% step in raw Close and no step in Adj Close.133- Companies renamed after mergers lose history under the old symbol.134- Volume is often unreliable; use bhavcopy volume.135- Index tickers use `^NSEI` (Nifty 50) and `^BSESN` (Sensex).136137## Useful Python libraries138139| Library | Use | Caveat |140|---|---|---|141| `yfinance` | Quick historical prices | Adjustment quality |142| `nsepython` / `jugaad-data` | Wrappers over NSE endpoints — quotes, option chain, bhavcopy | Community-maintained; break when NSE changes its site. Check the terms of use |143| `mftool` | AMFI NAV history | |144| `pandas-datareader` | Some macro sources | |145| `nselib`, `bsedata` | Exchange helpers | Same fragility caveat |146147Prefer the published files (bhavcopy, AMFI) over any wrapper around an undocumented endpoint. The files are stable, permitted, and do not break.148149## Data hygiene rules1501511. **Key on ISIN.** Store symbol as an attribute, not an identifier.1522. **Store raw and adjusted separately.** Never overwrite raw prices with adjusted ones.1533. **Record the source and the fetch timestamp** on every row or table. Financial data is revised.1544. **Handle the Indian trading calendar**: NSE and BSE holidays do not match any standard calendar library's defaults, there are special Muhurat trading sessions, and there have been occasional weekend sessions. Fetch the exchange's published holiday list rather than assuming.1555. **Crore and lakh.** 1 crore = 10 million; 1 lakh = 0.1 million. Indian filings report in ₹ crore or ₹ lakh, and both appear in the same document. Normalise to one unit at ingestion and record which.1566. **Face value changes** on a split alter the per-share series without any corporate action flag in some sources. Cross-check against the exchange's corporate action file.1577. **Survivorship bias**: a universe built from today's index constituents excludes every delisted and merged company. For any backtest, reconstruct point-in-time index membership from the exchange's historical constituent changes.1588. **Ex-date on T+1.** Under India's T+1 settlement cycle the ex-date coincides with the record date. Code written for T+2 will be one day off on every corporate action.159160## Output format161162When asked where to get something, answer in this shape:163164```markdown165**Source:** <name> — <url or navigation path>166**Format:** <CSV / JSON / PDF>, <frequency>, <history available>167**Identifier:** <ISIN / symbol / scheme code>168**Cost / access:** <free / paid / registration>169**Caveats:** <the two or three things that will bite>170**Snippet:** <minimal working code, if code was asked for>171```172173## Hard rules174175- **Never fabricate a data point.** If a fetch fails, report the failure and the URL attempted.176- **Never present scraped data as official.** Name the source in every output.177- Do not write code that circumvents authentication, rate limits, or a paywall.178- State the as-of date on every number that came from a market data source.