data.gov.in API — Advanced Guide¶
Query India's open data portal programmatically — fetch any of 500,000+ datasets using Python.
Provider
National Informatics Centre (NIC) / MeitY
API Base URL
https://api.data.gov.in/resource/Access Level
🟡 Free API Key (register at data.gov.in)
Rate Limit
1,000 requests/day (free tier)
Response Format
JSON, XML, CSV
Docs
Getting Your API Key¶
- Go to data.gov.in
- Click "Sign In" → Register with email
- After login: Go to "My Account" → "API Access"
- Click "Generate API Key"
- Copy the key — you'll use it in every API request
API Endpoint Structure¶
Every dataset on data.gov.in has a Resource ID (UUID). The API call structure is:
Key parameters:
| Parameter | Description | Example |
|---|---|---|
api-key |
Your API key | abc123xyz |
format |
Response format | json, xml, csv |
limit |
Records per page | 100 (max 500) |
offset |
Skip first N records | 100 (for pagination) |
filters[column] |
Filter by column value | filters[State]=Maharashtra |
fields |
Select specific columns | fields=State,District,Total |
Python Wrapper for data.gov.in API¶
import requests
import pandas as pd
from time import sleep
class DataGovIn:
"""Simple wrapper for the data.gov.in API."""
BASE_URL = "https://api.data.gov.in/resource/{resource_id}"
def __init__(self, api_key: str):
self.api_key = api_key
def fetch(self, resource_id: str, filters: dict = None,
fields: list = None, limit: int = 100) -> pd.DataFrame:
"""Fetch a dataset and return as DataFrame."""
url = self.BASE_URL.format(resource_id=resource_id)
params = {
"api-key": self.api_key,
"format": "json",
"limit": limit,
"offset": 0
}
if filters:
for col, val in filters.items():
params[f"filters[{col}]"] = val
if fields:
params["fields"] = ",".join(fields)
all_records = []
while True:
resp = requests.get(url, params=params, timeout=30)
if resp.status_code != 200:
print(f"Error {resp.status_code}: {resp.text[:200]}")
break
data = resp.json()
records = data.get("records", [])
all_records.extend(records)
total = int(data.get("total", 0))
offset = params["offset"] + limit
print(f" Fetched {len(all_records)}/{total} records...")
if offset >= total or not records:
break
params["offset"] = offset
sleep(0.5) # Be polite to the server
return pd.DataFrame(all_records)
def search(self, query: str) -> list:
"""Search for datasets by keyword."""
resp = requests.get(
"https://data.gov.in/api/3/action/package_search",
params={"q": query, "rows": 10}
)
results = resp.json().get("result", {}).get("results", [])
return [(r.get("title"), r.get("id")) for r in results]
# ─── Usage Example ────────────────────────────────────────────────────────────
api = DataGovIn(api_key="YOUR_API_KEY_HERE")
# Example: Download MGNREGA data for Maharashtra
# Resource ID found by searching on data.gov.in
MGNREGA_RESOURCE_ID = "628f3a50-5b70-4b55-88c0-d4b6f618d855"
print("Downloading MGNREGA data for Maharashtra...")
mgnrega_mh = api.fetch(
resource_id=MGNREGA_RESOURCE_ID,
filters={"State": "MAHARASHTRA"},
limit=500
)
print(f"\nDownloaded {len(mgnrega_mh)} records")
print(mgnrega_mh.head())
# Save to CSV
mgnrega_mh.to_csv("mgnrega_maharashtra.csv", index=False)
print("Saved to mgnrega_maharashtra.csv")
Finding Resource IDs¶
To find the Resource ID for any dataset:
- Go to data.gov.in → Search for your dataset
- Click on the dataset → Scroll to "API" section
- The Resource ID is in the URL or the API panel
Or search via the API:
# Search data.gov.in catalogue
results = api.search("MGNREGA district Maharashtra")
for title, rid in results:
print(f"{rid} → {title}")
✏️ Practice Exercise¶
Exercise 6.4 — Auto-download PMGSY Data for Your State
Goal: Write a Python script to download and save PMGSY road connectivity data.
- Go to data.gov.in → Search:
"PMGSY habitation"→ Find a suitable dataset - Note the Resource ID from the API section
- Use the
DataGovInwrapper above:
api = DataGovIn(api_key="YOUR_KEY")
pmgsy_data = api.fetch(
resource_id="YOUR_PMGSY_RESOURCE_ID",
filters={"State_Name": "MAHARASHTRA"}, # Adjust column name
limit=500
)
print(f"Total records: {len(pmgsy_data)}")
print(f"Columns: {list(pmgsy_data.columns)}")
# Count connected vs unconnected
status_counts = pmgsy_data['Status'].value_counts()
print("\nConnectivity Status:")
print(status_counts)
pmgsy_data.to_csv("pmgsy_my_state.csv", index=False)
- How many habitations are in your state's PMGSY database?
- What % are connected?
- Which district has the most unconnected habitations?
Next: WRIS Web Services →