NSE Bhavcopy for Options Data: What You Get and Where It Stops
Before paying anyone for Indian options data, it is worth knowing exactly what the exchange gives away free, because for a meaningful set of use cases it is enough.
What bhavcopy is
At the end of each trading session, NSE publishes a report covering every instrument traded that day. The F&O bhavcopy covers futures and options: one row per contract, carrying the day’s open, high, low, close, settlement price, contracts traded, value, and open interest.
Two things make it valuable beyond being free:
It is authoritative. This is the settlement record. Where any other source disagrees with bhavcopy, the other source is wrong.
It is complete. Every contract that traded, including the illiquid ones a commercial aggregator might drop.
What is in a row
The F&O bhavcopy identifies a contract by instrument type (OPTIDX for index options), symbol, expiry date, strike and option type, then reports:
| Field | Meaning |
|---|---|
OPEN / HIGH / LOW / CLOSE |
Premium in rupees for the session |
SETTLE_PR |
Settlement price — the number that matters for margining |
CONTRACTS |
Contracts traded |
VAL_INLAKH |
Traded value |
OPEN_INT |
Open interest at the close |
CHG_IN_OI |
Change in open interest from the previous session |
That is genuinely a lot for a free source. Daily OHLC plus closing open interest per contract, for every contract, going back years.
Parsing it
The mechanics are straightforward; the pitfalls are all in the details.
import io, zipfile, requests
import pandas as pd
HEADERS = {
# A plain scripted request is usually rejected. This is not a bypass —
# the file is public — it just needs to look like a browser.
"User-Agent": "Mozilla/5.0",
"Accept-Language": "en-US,en;q=0.9",
}
def load_fo_bhavcopy(url: str) -> pd.DataFrame:
r = requests.get(url, headers=HEADERS, timeout=30)
r.raise_for_status()
if r.headers.get("content-type", "").startswith("application/zip"):
with zipfile.ZipFile(io.BytesIO(r.content)) as z:
name = z.namelist()[0]
df = pd.read_csv(z.open(name))
else:
df = pd.read_csv(io.BytesIO(r.content))
df.columns = [c.strip().upper() for c in df.columns]
return df
Four things that will bite you:
Column names drift. Whitespace, case and outright renames vary across eras. Normalise on load, and never index by position.
Dates are formatted inconsistently. Expiry appears as 28-JAN-2024 in some files and ISO in others. Parse defensively and fail loudly rather than silently producing NaT.
Non-trading days return errors, not empty files. Holidays and weekends have no file at all. A loop that treats a 404 as “no trades” will quietly skip real sessions when the URL structure changes.
The URL structure itself has changed. A downloader written against current URLs will not fetch 2021 files. Expect to maintain per-era logic.
Where it stops
Bhavcopy is end-of-day. One row per contract per session. That is the whole limitation, and everything that follows from it:
No intraday series. You cannot test an entry at 10:15, or see how premium behaved through the session, or observe when open interest was built rather than where it ended. A rule that fires intraday cannot be tested on data that records only the close.
No open interest path. OPEN_INT is the closing figure. The building of that position — which is the informative part — is invisible.
Events are invisible. Implied volatility collapsing after an announcement happens in minutes. In bhavcopy it is one number replaced by another number the next day.
Assembly is your problem. One file per day. Ten years is roughly 2,500 downloads, stitched, with per-era parsing. Doable, and a real afternoon or three.
It only works forward for intraday. If you later decide you need minute data, bhavcopy cannot supply it retrospectively. That decision has to be made before the sessions happen.
The honest dividing line
Use bhavcopy when: your strategy decides daily, you want settlement prices, you need an authoritative reference to reconcile another source against, or you are validating an idea before spending money. In all of these it is the correct tool and costs nothing.
You need something else when: any decision happens intraday, you want to see open interest build within a session, you are studying event behaviour, or you want per-contract series without building a download-and-stitch pipeline first.
That is the whole distinction — not quality, and not completeness. Bhavcopy is excellent at what it does. It simply records one moment per day.
For per-minute data with open interest at the same granularity, MoneyTicks keeps it for expired NIFTY, BANK NIFTY and SENSEX contracts — disclosure, our own product — and the archive is browsable free if you want to see the difference in resolution before deciding. The comparison of Indian options data sources covers the other options too, several of which are also free.
A recommendation
Even if you buy data, reconcile against bhavcopy. It is the settlement record, it is free, and checking a vendor’s daily closes against it is the cheapest data-quality control available. We do this ourselves, and it is how discrepancies get found the same evening rather than weeks later inside a backtest result.
Related: building an options database covers the storage side, including why reconciliation belongs in the ingestion path.
Frequently asked questions
What is NSE bhavcopy?
The end-of-day report NSE publishes for every instrument traded that session, including all futures and options contracts. It carries open, high, low, close, settlement price, volume and open interest per contract, and it is free.
Is NSE bhavcopy free to download?
Yes. It is published on the NSE website each trading day at no cost, and is the authoritative settlement record. There is no API key or account required, though scripted downloads need appropriate headers to avoid being blocked.
Does bhavcopy include intraday options data?
No. Bhavcopy is strictly end-of-day — one row per contract per session. There is no minute-level or hourly series in it, and no way to derive one from it. Anything intraday has to come from a live capture or an archive that made one.
How far back does NSE bhavcopy go?
Years, though the file format and URL structure have changed over time, so a loader written for recent files will often fail on older ones. Older archives are available but expect to write per-era parsing rather than one universal reader.
Is bhavcopy enough for options backtesting?
For daily-decision strategies, often yes, and it costs nothing. For anything intraday it is not — you cannot test an entry rule that fires at 10:15 with a dataset that only records the close. That is the dividing line.