Data API (Option Chain + Historical) – invalid JSON / status: failure

I am subscribed to the Dhan Data API plan and using DhanHQ‑py (v2.x) with access‑token + client‑id authentication.

For NIFTY Index (security_id = 13, segment = IDX_I), both option chain expiries and historical data endpoints are failing with parse errors, even during live market hours.

1) Option Chain – expiry list:
I am calling expiry_list(13, "IDX_I") via DhanHQ‑py. The raw response (printed from Python) is:

json

{"status": "failure", "remarks": "Extra data: line 1 column 5 (char 4)", "data": ""}

So the SDK only returns a single dict with status=failure and an internal JSON parse error in remarks, and no list of expiries.

2) Historical Intraday Data:
Similarly, for intraday minute data for NIFTY Index, the SDK returns:

json

{"status": "failure", "remarks": "Expecting value: line 1 column 1 (char 0)", "data": ""}

again with no data, even when called during market hours.

Because of this, it is not possible to fetch NIFTY option chain or intraday candles via the Data API, although my subscription is active.

curl --location ‘https :globe_showing_europe_africa: ://api.dhan.co/v2/optionchain/expirylist :globe_showing_europe_africa: ’ \

–header ‘access-token: <YOUR_ACCESS_TOKEN>’ \
–header ‘client-id: <YOUR_CLIENT_ID>’ \
–header ‘Content-Type: application/json’ \
–data ‘{
“UnderlyingScrip”: 13,
“UnderlyingSeg”: “IDX_I”
}’

When I hit the above curl (with my real token and client id), the SDK reports status: failure and remarks: "Extra data: line 1 column 5 (char 4)". Please confirm what the correct response body should be for this request.

*import os, json
from dhanhq import dhanhq
from dotenv import load_dotenv

load_dotenv()
CLIENT_ID = os.getenv(“DHAN_CLIENT_ID”)
ACCESS_TOKEN = os.getenv(“DHAN_ACCESS_TOKEN”)

dhan = dhanhq(CLIENT_ID, ACCESS_TOKEN)

1) NIFTY expiry list

expiries = dhan.expiry_list(13, “IDX_I”)
print(“expiry_list raw:”, type(expiries), expiries)
with open(“nifty_expiries_raw.json”, “w”) as f:
json.dump(expiries, f, indent=2)

2) NIFTY intraday minute

intraday = dhan.intraday_minute_data(
security_id=13,
exchange_segment=“IDX_I”,
instrument_type=“INDEX”,
from_date=“2025-12-20”,
to_date=“2025-12-20”
)
print(“intraday raw:”, type(intraday), intraday)
with open(“nifty_intraday_raw.json”, “w”) as f:
json.dump(intraday, f, indent=2)*

Could you please:

  1. Confirm if there is an issue on the /v2/optionchain/expirylist and /charts/intraday (or corresponding v2 historical) endpoints for UnderlyingScrip = 13, UnderlyingSeg = "IDX_I"?

  2. Share a working curl example and expected JSON response for NIFTY option chain and intraday data, so I can validate independently of the Python SDK?

  3. Let me know if there is any change in payload/URL for Data API users that is not yet reflected in the public docs?

Thanks.

Hey @Anugraha_Bharadwaj ,

As discussed over call , below is the python sample code for fetching the option expiry list and Historical intraday data.

  1. Option expiry list:
    dhan.expiry_list(
    under_security_id=13, # Nifty
    under_exchange_segment=“IDX_I”
    )

  2. Intraday historical data
    dhan.intraday_minute_data(“1333”, “NSE_EQ”, “EQUITY”, “2026-01-01”, “2026-01-06”, 60)

You may check all the python sample codes in our github library GitHub - dhan-oss/DhanHQ-py: The official Python client for communicating with the Dhan API.

Your Historical Rolling Options API is practically unusable for serious quantitative research or backtesting.

You are providing rolling relative strike data (ATM, ATM+1, ATM-1 etc.) where the strike itself keeps changing as spot moves. Because of this, continuity of a single contract is completely lost.

For example:
23950 CE → 24000 CE → 24050 CE

This means the returned series is not an actual tradable instrument history. It becomes impossible to perform:

  • Proper backtesting

  • Strike-wise analysis

  • Greeks modelling

  • Volatility surface analysis

  • Realistic PnL reconstruction

Even worse, once the ATM shifts, data for the previous strike effectively stops in the rolling stream. At minimum, each strike should have complete continuous historical data for the duration it existed.

Right now the API is neither a proper rolling continuous instrument nor a proper fixed-strike historical dataset. It falls into an unusable middle ground for serious options research. @Shrutika_Poojari

@Hardik please you also look into it

Hello @dev_g

The rolling options data available on Dhan currently is on the basis of strike itself in respect to ATM. Along with that, it also has rolling IV and OI data.

It might not be suitable for backtesting strategies on basis of particular strike selection, but can be very simple to implement for a lot of IV based strategy. On raw data of historical options, given the data size is too large, we are looking into how we can facilitate the same over API endpoints.

Hello @Hardik

What I am asking for is that you do not need to provide the complete option chain data for the entire day. Instead, it would be very helpful if you could provide the full historical data only for the strikes that fall within the underlying OHLC range ±1 strike.

For example, if the underlying moved between certain levels during the day, then only the strikes around that active range would be enough. This would significantly reduce the data size while still making strategy backtesting practical, especially for strike-selection and IV/OI-based strategies.

This approach can also help reduce API load and storage requirements compared to providing the entire chain.