Short answer: not an official free one. On its own website the National Stock Exchange of India (NSE) offers 23 RSS feeds and paid, licensed data products; I found no developer portal, API key or API documentation for corporate filings. The filing pages on nseindia.com, however, load their tables from JSON endpoints that answer a plain HTTP GET. On 10 November 2026 one request returned all 6,029 equity announcements filed from 3 to 9 November (4.9 MB of JSON) without a login, a key or a cookie.

This post covers what NSE offers officially, the endpoints for announcements, corporate actions, board meetings and bulk/block deals, working Python for each, and the gotchas. Every number and every output below comes from a request I ran on 10 November 2026.

What NSE officially offers: RSS feeds and licensed data

RSS feeds. nseindia.com/rss-feed lists 23 XML feeds, among them announcements, corporate actions, board meetings, financial results, insider trading, shareholding patterns and offer documents. They live at https://nsearchives.nseindia.com/content/RSS/<name>.xml.

import xml.etree.ElementTree as ET import requests UA = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"} feed = "https://nsearchives.nseindia.com/content/RSS/Online_announcements.xml" items = ET.fromstring(requests.get(feed, headers=UA, timeout=30).content).findall(".//item") print(len(items), "items, from", items[-1].findtext("pubDate"), "to", items[0].findtext("pubDate")) for i in items[:3]: print(i.findtext("pubDate"), "|", i.findtext("title"), "|", i.findtext("link").rsplit("/", 1)[-1]) 
548 items, from 10-Nov-2026 00:06:51 to 10-Nov-2026 17:37:48 10-Nov-2026 17:37:48 | Kalyan Jewellers India Limited | KALYANKJIL_10112026173732_PR.pdf 10-Nov-2026 17:35:58 | Websol Energy System Limited | WEBELSOLAR_10112026173544_Reg_30_Transcript.pdf 10-Nov-2026 17:35:01 | Quadrant Future Tek Limited | QUADRANT_10112026173318_OutcomeOfBMNov2026ocr.pdf 

If "what was filed today" is all you need, use the RSS feed: it is the channel NSE publishes for machines, and the feed declares a refresh interval (ttl) of 5 minutes. Its limits, as observed: the announcements feed held only the current day, an item has four fields (company name, PDF link, one line of text, time) with no symbol, ISIN or category field, and all market segments share one feed. The other feeds were shorter: 59 items in Corporate_action.xml, 65 in Board_Meetings.xml, 16 in InsiderTrading.xml (one hour of filings), 3 in Financial_Results.xml and none in Shareholding_Pattern.xml.

Licensed data. NSE's data business is run by its subsidiary NSE Data & Analytics Limited. Its Paid Corporate Data page (marked "Updated on: 11/06/2026") lists a Corporate Data product, "company fundamentals, corporate announcements, and shareholding pattern", delivered over a dedicated leased line at INR 1,060,000 (USD 17,500 for international customers), and an End of Day Corporate Announcement product, delivered over SFTP after 8:00 PM IST, at INR 500,000 (USD 8,000) per annum.

Terms of use. NSE's Terms of Use say: "User is prohibited to conduct any systematic or automated data collection activities (including scraping, data mining, data extraction and data harvesting) on or in relation to our Website / Mobile Application", and that content may not be copied or distributed "without prior written permission of NSE". That is the exchange's stated position. Read it before you build on the endpoints below; for a commercial product the licensed route is NSE Data & Analytics.

The NSE corporate announcements JSON endpoint

The page Corporate Filings: Announcements fills its table from:

GET https://www.nseindia.com/api/corporate-announcements ?index=equities&from_date=09-11-2026&to_date=09-11-2026 
from datetime import date, timedelta import requests API = "https://www.nseindia.com/api" s = requests.Session() s.headers.update({ # python-requests' default User-Agent gets no answer at all; any browser string works "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36", "Accept": "application/json, text/plain, */*", }) def nse(path, **params): r = s.get(f"{API}/{path}", params=params, timeout=60) r.raise_for_status() return r.json() def dmy(d): # NSE wants DD-MM-YYYY return d.strftime("%d-%m-%Y") day = date(2026, 11, 9) rows = nse("corporate-announcements", index="equities", from_date=dmy(day), to_date=dmy(day)) print(len(rows), "equity announcements on", day) for a in rows[:3]: print(a["an_dt"], "|", a["symbol"], "|", a["desc"], "|", a["attchmntFile"].rsplit("/", 1)[-1]) 
234 equity announcements on 2026-11-09 09-Nov-2026 23:45:59 | CHALET | Analysts/Institutional Investor Meet/Con. Call Updates | CHALET_09112026234526_Regulation30InvestorConferenceIntimation09112026.pdf 09-Nov-2026 23:31:42 | TORNTPOWER | Analysts/Institutional Investor Meet/Con. Call Updates | TORNTPOWER_09112026233101_Transcript_-_SE_Intimation.pdf 09-Nov-2026 23:22:11 | AASTHA | Copy of Newspaper Publication | 9081535400_09112026232157_Final_Newspaper_Advertisment.pdf 

The answer is a JSON array, newest first, not paged. The fields that matter:

Field Meaning
seq_id NSE's id of the filing; use it to deduplicate
symbol, sm_name, sm_isin, smIndustry company (industry is often empty)
desc NSE's subject, for example Outcome of Board Meeting, Press Release, Dividend
attchmntText the summary text shown on the site
attchmntFile, attFileSize PDF link on nsearchives.nseindia.com and its size
an_dt, exchdisstime broadcast and dissemination time, India time, as 09-Nov-2026 23:45:59
sort_date the same moment as 2026-11-09 23:45:59
hasXbrl whether an XBRL version exists

index selects the segment: equities, sme, debt, mf (mutual funds) or invitsreits. Add symbol=RELIANCE for one company.

How many announcements does NSE publish per day?

Equity segment, one request per day, 10 November 2026:

Day Announcements Response size
Mon 2 Nov 904 0.66 MB
Tue 3 Nov 1,142 0.84 MB
Wed 4 Nov 1,419 1.03 MB
Thu 5 Nov 1,530 1.11 MB
Fri 6 Nov 1,239 0.90 MB
Sat 7 Nov 426 0.66 MB
Sun 8 Nov 39 0.06 MB
Mon 9 Nov 234 0.34 MB

A range is one answer too: 3 to 9 November returned 6,029 rows (the sum of the seven days, 6,029 distinct seq_id values, 1,667 companies) and the whole of October returned 14,045 rows in 10.5 MB. In that week the most frequent subjects were analyst and investor-call updates (1,274), board meeting outcomes (895) and newspaper publications (876). The other segments for the same week: SME 776, debt 827, mutual funds 2,258, InvITs and REITs 116.

NSE corporate actions API: dividends, bonus issues and splits by ex-date

Corporate actions, board meetings and the event calendar take the same parameters. Here the date range filters the ex-date (or the meeting date), so a range in the future gives you a calendar:

today = date(2026, 11, 10) actions = nse("corporates-corporateActions", index="equities", from_date=dmy(today), to_date=dmy(today + timedelta(days=30))) print(len(actions), "corporate actions with an ex-date in the next 30 days") for a in actions[:4]: print(a["exDate"], "|", a["symbol"], "|", a["subject"]) history = nse("corporate-announcements", index="equities", symbol="RELIANCE", from_date="01-01-2026", to_date=dmy(today)) print(len(history), "RELIANCE announcements in 2026, latest:", history[0]["an_dt"], history[0]["desc"]) 
57 corporate actions with an ex-date in the next 30 days 11-Nov-2026 | INDIGRID | Distribution Rs 4.12 Per Unit Consists Of Interest - Rs 3.1878 Per Unit /Capital Repayment - Re 0.9322 Per Unit 11-Nov-2026 | SONATSOFTW | Interim Dividend - Rs 1.25 Per Share 11-Nov-2026 | RITES | Interim Dividend - Rs 1.90 Per Share 11-Nov-2026 | PREMIERENE | Interim Dividend - Re 0.50 Per Share 146 RELIANCE announcements in 2026, latest: 06-Nov-2026 19:10:58 Analysts/Institutional Investor Meet/Con. Call Updates 

The action itself is free text in subject ("Interim Dividend - Rs 1.25 Per Share", "Buy Back", "Rights 5:12 @ Premium Rs 855/-"), so the amount or ratio has to be parsed out; Rs and Re both occur. Of the 57 rows, 50 were interim dividends. The other fields are symbol, comp, isin, series, faceVal, exDate, recDate, bcStartDate and bcEndDate.

NSE bulk deals and block deals API: the JSON stops at 70 rows

Deals use a different endpoint and different parameter names (from and to, not from_date):

import csv import io url = f"{API}/historicalOR/bulk-block-short-deals" q = {"optionType": "bulk_deals", "from": "03-11-2026", "to": "09-11-2026"} as_json = s.get(url, params=q, timeout=60).json()["data"] as_csv = s.get(url, params={**q, "csv": "true"}, timeout=60).content.decode("utf-8-sig") deals = [{k.strip(): v for k, v in row.items()} for row in csv.DictReader(io.StringIO(as_csv))] print(len(as_json), "rows in the JSON, dated", {d["BD_DT_DATE"] for d in as_json}) print(len(deals), "rows in the CSV, dated", sorted({d["Date"] for d in deals})) print(deals[0]) 
70 rows in the JSON, dated {'03-NOV-2026'} 548 rows in the CSV, dated ['03-NOV-2026', '04-NOV-2026', '05-NOV-2026', '06-NOV-2026', '08-NOV-2026', '09-NOV-2026'] {'Date': '03-NOV-2026', 'Symbol': 'AGIIL', 'Security Name': 'Agi Infra Limited', 'Client Name': 'ARIHANT CAPITAL MARKETS LIMITED', 'Buy / Sell': 'SELL', 'Quantity Traded': '13,30,449', 'Trade Price / Wght. Avg. Price': '266.03', 'Remarks': '-'} 

The JSON answer is cut at 70 rows without any flag: for the week it returned the first 70 rows of the first day and nothing else, and for the whole of October it also returned 70 rows where the CSV had 2,771. With csv=true the same request returns the full range. optionType is bulk_deals, block_deals or short_selling; for 3 to 9 November the CSVs held 548, 26 and 653 rows. Three things to handle in the CSV: it starts with a byte-order mark, the header names end with a space ("Date "), and quantities use Indian digit grouping (13,30,449).

For the latest trading day only, GET /api/snapshot-capital-market-largedeal returns all three lists in one JSON without a cap (on 10 November: as_on_date 09-Nov-2026 with 76 bulk deals, 2 block deals and 86 short-selling rows).

Polling for new NSE filings without duplicates

For an alert you only need the filings you have not seen. seq_id is unique per filing (6,029 rows, 6,029 ids in the week above), so a small file of seen ids is enough. Ask for yesterday and today so a late-night filing is not missed:

import json import pathlib seen_file = pathlib.Path("nse_seen.json") seen = set(json.loads(seen_file.read_text())) if seen_file.exists() else set() today = date.today() # run it on an India-time clock, or pass yesterday as well rows = nse("corporate-announcements", index="equities", from_date=dmy(today - timedelta(days=1)), to_date=dmy(today)) new = [a for a in rows if a["seq_id"] not in seen] for a in new[:5]: print(a["an_dt"], a["symbol"], "|", a["desc"]) print(len(new), "new of", len(rows)) seen_file.write_text(json.dumps(sorted(seen | {a["seq_id"] for a in rows}))) 

First run, then a second run a few seconds later:

10-Nov-2026 17:29:11 PARKHOTELS | Updates 10-Nov-2026 17:26:04 SIGMAADV | Analysts/Institutional Investor Meet/Con. Call Updates 10-Nov-2026 17:22:55 PILANIINVS | Outcome of Board Meeting 10-Nov-2026 17:22:53 SKYWAYS | Analysts/Institutional Investor Meet/Con. Call Updates 10-Nov-2026 17:20:56 PILANIINVS | Outcome of Board Meeting 427 new of 427 
0 new of 427 

NSE filing endpoints at a glance

All under https://www.nseindia.com/api/, all GET, all checked on 10 November 2026:

Data Path Parameters Rows returned
Announcements corporate-announcements index, from_date, to_date, optional symbol 6,029 (equities, 3-9 Nov)
Corporate actions corporates-corporateActions same, range on ex-date 57 (next 30 days); 2,027 (ex-date in 2026)
Board meetings corporate-board-meetings same, range on meeting date 1,446 (10 Nov-10 Dec)
Event calendar event-calendar same 671 (10 Nov-10 Dec)
Bulk, block, short deals historicalOR/bulk-block-short-deals optionType, from, to, csv=true 548 / 26 / 653 (3-9 Nov)
Latest day's deals snapshot-capital-market-largedeal none 76 / 2 / 86 (9 Nov)
Credit ratings corporate-credit-rating index, from_date, to_date 100 (3-9 Nov)
Shareholding patterns corporate-share-holdings-master index, from_date, to_date 2,460 (1 Oct-10 Nov)
Offer documents (IPO) corporates/offerdocs index 1,271 (main board register)

The gotchas

1. Send a browser User-Agent. With the default python-requests User-Agent the API did not answer at all (I gave up after 90 seconds) and the RSS host closed the connection. With a browser User-Agent the same request took 0.3 seconds. No cookie was needed: all 49 probe requests I sent without any cookie were answered with HTTP 200. The site's home page is stricter than its API: https://www.nseindia.com/ answered HTTP 403 "Access Denied" to the same client that the API and the filings page served with HTTP 200. If the API ever answers 401 or 403, load the filings page first in the same requests.Session (it sets cookies) and retry.

2. Dates are DD-MM-YYYY, and a wrong format fails silently. from_date=2026-11-09 and from_date=09/11/2026 both return HTTP 200 with {"data":[],"msg":"no data found"}. Note the shape change too: a dict instead of the usual array.

3. index is required. Without it the answer is HTTP 200 with the plain text Missing index.

4. No dates means "the latest 20", except with a symbol. corporate-announcements?index=equities returns the 20 newest rows. Add symbol=RELIANCE without dates and you get the company's whole history: 3,375 announcements back to 13 December 2004, 3.0 MB.

5. Deals: from/to, the 70-row JSON cap, and CSV quirks. See above. If your bulk-deal counts look suspiciously round, this is why.

6. Two endpoints are not usable for a date range. corporates-financial-results with 3 to 9 November returned 1 row (a filing for a quarter ended June 2024), in a week when the announcements feed carried 895 board meeting outcomes; without dates it returned 3,816 rows, of which 3,695 were broadcast in January or February 2025. corporates-pit (insider trading) returned an empty list for every variant I tried, with and without dates and symbol. For results, filter announcements by desc; for insider trades there is the RSS feed, which only holds the latest items.

7. Times are India time without an offset. an_dt is 09-Nov-2026 23:45:59. Parse it as Asia/Kolkata (UTC+05:30) before comparing with anything else.

8. Be a polite client. The answers are large (10.5 MB for one month of equities) and the data for past days does not change. Download a day once and cache it, poll the current day every few minutes at most, and keep requests sequential.

When not to maintain this yourself

The snippets above are enough for a script. A product needs more: parsing the free-text corporate actions, the CSV workaround for deals, India-time timestamps, a memory of delivered rows, retries, and someone who notices when NSE changes a field.

I packaged that as the NSE Corporate Announcements API on Apify (disclosure: I built it). One input covers eight reports (announcements, corporate actions, board meetings, event calendar, deals, credit ratings, shareholding patterns, offer documents), with symbol, category and keyword filters and an onlyNew mode that delivers each row once. It reads the same public endpoints described here, so the terms of use above apply to your use of the data either way.

import os from decimal import Decimal from apify_client import ApifyClient client = ApifyClient(os.environ["APIFY_TOKEN"]) run = client.actor("data_daemon/nse-corporate-announcements").call( run_input={ "reports": ["announcements", "corporateActions"], "categories": ["Dividend"], # NSE's subject contains this word "daysBack": 7, # filings: the last 7 days "daysAhead": 30, # ex-dates: the next 30 days "maxItems": 4, # per report }, max_total_charge_usd=Decimal("0.05"), logger=None, ) print(run["status"], "|", run["statusMessage"]) for row in client.dataset(run["defaultDatasetId"]).iterate_items(): if row["reportType"] == "announcements": print(row["broadcastAt"], row["symbol"], "|", row["category"], "|", row["attachmentUrl"].rsplit("/", 1)[-1]) else: print(row["exDate"], row["symbol"], "|", row["actionType"], row.get("amountPerShare"), "|", row["purpose"]) 
SUCCEEDED | Saved 4 announcements (2026-11-03 to 2026-11-10), capped by maxItems 4; 4 corporate actions (2026-11-10 to 2026-12-10), capped by maxItems 4. Set maxItems to 0 for every row in the dates. 2026-11-10T14:34:06+05:30 COCHINSHIP | Dividend | Aswi4739_10112026143317_SE_Intimation_Sgd.pdf 2026-11-06T20:18:10+05:30 TRANSWORLD | Dividend | TRANSWORLD_06112026201735_Board_Meeting_Outcome-signed.pdf 2026-11-06T20:13:56+05:30 RAIN | Dividend | RAIN_06112026201303_OutcomeOfBoardMeeting.pdf 2026-11-06T19:07:15+05:30 INGERRAND | Dividend | INGERRAND1_06112026190613_FinancialResultsSept2026.pdf 2026-11-11 ADFFOODS | dividend 0.6 | Interim Dividend - Re 0.60 Per Share 2026-11-11 AUROPHARMA | dividend 7 | Interim Dividend - Rs 7 Per Share 2026-11-11 BALKRISIND | dividend 4 | Interim Dividend - Rs 4 Per Share 2026-11-11 BALRAMCHIN | dividend 4 | Interim Dividend - Rs 4 Per Share 

That run took 3 seconds and delivered 8 rows. The price is $0.003 per row, with no start fee and no subscription. What typical jobs cost, using the row counts measured above:

Job Rows on 10 Nov 2026 Cost
Default run: the 50 newest announcements 50 $0.15
Ex-dates for the next 30 days 57 $0.17
One company's announcements in 2026 (RELIANCE) 146 $0.44
Bulk, block and short-selling rows, 3-9 Nov 1,227 $3.68
One busy day of equity announcements (5 Nov) 1,530 $4.59
A week of equity announcements (3-9 Nov) 6,029 $18.09
All equity announcements of October 2026 14,045 $42.14

Ready-made inputs: latest NSE corporate announcements as JSON and bulk and block deals of the last 7 days.

Nothing here is investment advice; it is a description of where public disclosures can be read.

FAQ

Is there an official NSE API for corporate announcements?

Not a free developer API. NSE's website offers RSS feeds (23 of them, including announcements, corporate actions and board meetings) and NSE Data & Analytics sells licensed Corporate Data products (listed on 10 November 2026 at INR 500,000 a year for the end-of-day file and INR 1,060,000 for the leased-line feed). The JSON endpoints in this post are the ones the public filing pages call; NSE does not document them.

Does the NSE API need an API key or cookies?

No key exists. On 10 November 2026 the endpoints answered 49 of 49 requests that carried only a browser-like User-Agent header and no cookie. The default python-requests User-Agent got no answer.

How do I get NSE bulk deals and block deals for a date range?

GET /api/historicalOR/bulk-block-short-deals?optionType=bulk_deals&from=DD-MM-YYYY&to=DD-MM-YYYY&csv=true (or block_deals, short_selling). Keep csv=true: without it the JSON stops at 70 rows.

What date format does the NSE API use?

DD-MM-YYYY in requests (from_date=09-11-2026). Responses use 09-Nov-2026 23:45:59 for timestamps and 11-Nov-2026 for ex-dates, in India time.

How far back do NSE announcements go?

For one symbol, a long way: RELIANCE returned 3,375 announcements, the oldest dated 13 December 2004. Whole-market ranges work as well; I pulled the 14,045 equity announcements of October 2026 in one request.

Does this cover BSE?

No. These are NSE's endpoints and NSE's filings only.