A frontend dashboard to show current status of ESZ notifications by the Ministry of Environment Forests & Climate Change (MoEFCC), Government of India. Live dashboard →
Features
- Mirror the ESZ notification HTML table on https://www.moef.gov.in/esz-notifications, updated weekly. View
- Interactive map dashboard showing:
- KPIs for total protected areas vs. draft/final ESZ notification coverage
- Protected area locations colored by ESZ notification status, with a filterable/sortable notification table
- PA boundaries (where mapped on OpenStreetMap) explorable via a custom amche-atlas atlas
- Download the notification list and protected area list as CSV/JSON, and protected area locations as GeoJSON
- Conflation with protected area data on wikidata.org
ESZs are designated buffer areas around protected habitats like national parks and wildlife sanctuaries. They act as shock absorbers to minimize human impact on fragile ecosystems, typically spanning up to 10 kilometers, though boundaries remain site-specific
The purpose of declaring ESZs is to create buffer zones for the protected areas by regulating and managing the activities around such areas. They also act as a transition zone from areas of high protection to areas involving lesser protection.
Source: Wikipedia
About ESZ Notifications
Source: PIB, Ministry of Environment Forests & Climate Change, Government of India
- 1970: The Indian Board for Wildlife (IBWL) is created as an advisory body to provide guidance on issues relating to the protection and conservation of wildlife and their habitats.
- 2002: The 21st IBWL meeting adopts the Wildlife Conservation Strategy 2002 chaired by Shri Atal Bihari Bajpai, then honourable Prime Minister of India, which proposed notifying 10km buffer zones of eco-fragile zones around protected areas where mining an polluting industries will be prohibited
- 2003: The National Board for Wildlife (NBWL) is constituted as a statutory body to replace IBWL
- 2004: The Goa Foundation filed a landmark case (PIL Writ Petition 460/2004) in the Supreme Court of India for clarification regarding iron ore mining within 10km of protected areas in Goa state
- 2006: Supreme Court of India directs all State/UTs to define Eco-Sensitive Zones (ESZ) around protected areas within 4 weeks failing which a 10km ESZ will apply as default
- 2011: Guidelines for declaration of ESZ pulbished by MoEFCC outlining procedures to State/UTs to demarcate and notify ESZ with the following details:
(i) Delineation of the physical boundaries on a topo-sheet with precise
description in geographic terms together with a description of the
significant features/attributes that would potentially qualify the area as
eco-sensitive zone. A description of the boundaries alongwith the list of
villages with exception and exemption in the delineated buffer zone area.
(ii) An inventory of the existing legal status of rights, entitlements, privileges and obligations of the local communities.
(iii) A description of bio-diversity values including bio-geographical
representatives, endemism, species richness, geo-morphological
characteristics, and unique land use practices including aesthetic and
cultural values.
(iv) A description of the resource base indicating the economic potential and
livelihood implication for the people residing in and around the
proposed eco-sensitive area.
(v) An inventory of activities to be regulated and/ or prohibited in the
proposed eco-sensitive zone.
(vi) List of the protected areas for declaring eco-sensitive zone.
- 2012: Due to lack of progress on ESZ identification, [CEC reccomends a safety zone of 100m-2000m metres](https://hash-cookies.s3.amazonaws.com/CEC%20buffer%20zones%20report%2020.9.2012.pdf) in the interim based on protected area size
- 2015: Goa becomes the first state to publish final ESZ notifications for all 6 protected areas in the state
- 2017:
- 2022: Supreme Court mandates a minimum 1km ESZ around all protected areas
- 2023: Supreme Court dilutes 1km minimum ESZ in 2022 order to define minimum ESZ to be protected area specific citing uniform minimums being impossible to implement.
- 2023: MoEFCC release updated guidelines for seeking recommendations of the Standing Committee of NBWL for activities in protected areas and ESZ
- 2025: IGNFA publishes a Discussion paper on ESZ which advocates for a risk based approach to ESZ declaration
npm install
npm run update # fetch -> parse -> clean -> enrich:osm -> enrich:wikidata -> enrich:archive -> enrich:allmaps -> build:geojson -> build:full-join -> build:atlas
Runs weekly via .github/workflows/update.yml; the dashboard (index.html) is redeployed to GitHub Pages afterwards by .github/workflows/pages.yml. Enable Pages once under repo Settings → Pages → Source: "GitHub Actions".
npm run update is just those steps chained together. Each can also be run on its own,
which is useful when re-running only the part affected by a correction (see
Contributing corrections below) instead of the whole
pipeline:
| # | Command | Reads | Writes | What it does |
|---|---|---|---|---|
| 1 | npm run fetch |
https://moef.gov.in/esz-notifications, three Wikipedia protected-area list pages | data/raw/moef-esz-notifications-table.html, data/raw/{national-parks,wildlife-sanctuaries,tiger-reserves}-table.html |
Scrapes the raw MoEF ESZ notifications table HTML, plus the Wikipedia national parks/wildlife sanctuaries/tiger reserves list tables (each combined from that page's per-state sub-tables into one table) |
| 2 | npm run parse |
the raw tables from step 1 | data/moef/esz-notifications.json, data/wikipedia/{national-parks,wildlife-sanctuaries,tiger-reserves}.{csv,json} |
Parses the MoEF table into one structured record per Draft/Final notification (parse:moef) and the three Wikipedia tables into one structured record per protected area (parse:wikipedia) |
| 3 | npm run clean |
data/moef/esz-notifications.json, data/corrections.csv |
data/moef/esz-notifications.json |
Applies manual corrections, splits multi-park notifications into one record per area, canonicalizes names/types |
| 4 | npm run enrich:wikidata |
data/moef/esz-notifications.json, live Wikidata SPARQL, data/wikipedia/{national-parks,wildlife-sanctuaries,tiger-reserves}.json, data/osm/protected-areas.csv (if present) |
data/wikidata/protected-areas.{csv,json}, data/wikidata/qa-log.md, data/moef/esz-notifications.{csv,json} (+ wikidataId/matchConfidence), data/enrichment-cache.csv |
Fetches the full Wikidata list of Indian protected areas; cross-references it against the three Wikipedia lists to correct outdated protectedAreaType categorization and add any protected area Wikipedia has that Wikidata doesn't (building data/wikidata/protected-areas.json as the master PA list); cross-references OSM boundaries by wikidata tag; links each MoEF notification to its master-list item |
| 5 | npm run enrich:archive |
data/moef/esz-notifications.json, archive.org search |
data/moef/esz-notifications.{csv,json} (+ notificationArchiveLink), data/enrichment-cache.csv |
Looks up each notification's official gazette scan on archive.org |
| 6 | npm run enrich:allmaps |
data/enrichment-cache.csv |
data/enrichment-cache.csv (+ Allmaps fields) |
Adds Allmaps IIIF georeferencing links for toposheet scans found in step 5 |
| 7 | npm run build:geojson |
data/wikidata/protected-areas.json, data/moef/esz-notifications.json |
data/protected-areas.geojson |
Builds the point-feature GeoJSON (PA location + ESZ status) |
| 8 | npm run build:full-join |
data/wikidata/protected-areas.json, data/moef/esz-notifications.json |
data/full-join.json |
Builds the full outer join of Wikidata PAs and MoEF notifications (keyed by wikidataId, falling back to state+name for unmatched records) with a precomputed representative notification per PA — the single file index.html/assets/app.js load to render the table and map |
| 9 | npm run build:atlas |
data/protected-areas.geojson |
data/amche-atlas.json |
Builds the amche-atlas config (PA points + live OSM-relation boundary layers) |
Steps 4–6 cache their lookups in data/enrichment-cache.csv, so re-running them after
the first full run is fast — only new/changed notifications are re-fetched.
Outputs:
data/moef/esz-notifications.{csv,json}— one row per protected area per notification, with awikidataIdjoin keydata/wikipedia/national-parks.{csv,json}— one row per national park, from List of national parks of Indiadata/wikipedia/wildlife-sanctuaries.{csv,json}— one row per wildlife sanctuary, from List of wildlife sanctuaries of Indiadata/wikipedia/tiger-reserves.{csv,json}— one row per tiger reserve (with coordinates), from Tiger reserves of Indiadata/wikidata/protected-areas.{csv,json}— the master protected-area list: every Wikidata item in scope (protectedAreaTypecorrected against the Wikipedia lists where they disagree), plus adataSource: "wikipedia"entry (syntheticWIKIPEDIA:...id, no real Wikidata QID) for any Wikipedia protected area with no Wikidata match, cross-referenced with OSM boundary ids where matcheddata/wikidata/qa-log.md— QA report for both cross-reference passes: Wikidata ↔ Wikipedia joins (type corrections, multi-matched items, new master-list entries, unmatched items on either side) and Wikidata ↔ OSM joins (unmatched items, outdated ids, coordinate/name mismatches) — for manual reviewdata/protected-areas.geojson— PA point locations with ESZ statusdata/full-join.json— full outer join of the two above, one entry per protected area with its notification history nested; this is what the dashboard actually loads (downloadable CSV/JSON/GeoJSON links on the page still point at the individual files above)data/amche-atlas.json— custom amche-atlas config (PA points + OSM-relation boundary layers)data/enrichment-cache.csv— persistent cache of Wikidata/archive.org lookups so repeat runs are fast
This is scraped and joined data from a government site and Wikidata, so it's imperfect —
corrections are welcome via pull request. Depending on what's wrong, fix it at a
different point in the pipeline rather than editing the generated data/*.json/*.csv
outputs directly, since those get overwritten the next time the pipeline runs:
- A MoEF notification's protected area name, state, or type is wrong or garbled
(e.g. a mis-scraped name, a multi-park notification that didn't split correctly) —
add a row to
data/corrections.csvkeyed by the exactpaName/stateas they currently appear indata/moef/esz-notifications.json, withcorrectPaName/correctState/correctPaTypeset to the fix (leave a column blank to leave that field alone). Applied byscripts/clean-moef-data.js. Re-runnpm run clean(or the full pipeline from step 3 onward) to verify. - A state name is wrong or inconsistent everywhere it appears (e.g. an old/misspelled
state name used across many notifications) — add a row to
data/corrections.csvwithpaName/correctPaName/correctPaTypeleft blank, juststate(the exact value to match) andcorrectState(the fix). This renames the state on every MoEF record with that state, instead of needing one row per protected area. - A notification's S.O./order number is mis-typed on the MoEF site itself
(verified against the actual gazette, e.g. on archive.org) — add a row to
data/corrections.csvwithorderNumberset to the exact wrong value as it currently appears indata/moef/esz-notifications.jsonandcorrectOrderNumberset to the fix (all other columns blank). Applied byscripts/clean-moef-data.js, which also fixes the same literal number embedded in that record'snotificationSummarytext. - A Wikidata field is wrong or missing (state, admin territorial entity, coordinates,
IUCN category, etc.) — fix it at the source: edit the item on
wikidata.org, then re-run
npm run enrich:wikidata(ornpm run update) to pull the fix back into this repo. For rows missing astateorlocatedInAdminTerritorialEntityvalue,npm run suggest:missing-state/npm run suggest:missing-located-incan suggest one by reading the item's Wikipedia article — seescripts/plugins/README.mdfor that workflow before batch-editing Wikidata. - A gazette/archive.org or toposheet link is wrong — the
toposheet pagecolumn indata/enrichment-cache.csvis a manual override read byscripts/enrich-allmaps.js; other archive fields are safe to blank out to forcenpm run enrich:archiveto re-look them up on the next run. - Something else (pipeline bug, dashboard bug, new feature) — open an issue or PR as usual.
