How to capture screenshots of Indian municipal websites with Selenium
Capture a municipal page with Selenium Python, wait for its real content, and choose the right method for viewport or full-page screenshots.
Use Selenium 4 with Chrome to open the public municipal page, set a fixed viewport, wait for a meaningful page element, and call driver.save_screenshot(). That saves a PNG of the current window; it does not by itself promise a full-page image. The example below is runnable after you install Selenium and a compatible Chrome browser, then replace the example URL and page selector with the target page.
1. Install Selenium and prepare Chrome
Install Selenium in the Python environment you will use to run the script:
python -m pip install selenium
Selenium 4 can manage browser drivers through Selenium Manager in supported setups. If browser startup fails, check that Chrome is installed and that your Selenium, Chrome, and driver setup are compatible. For reproducible captures, record the browser and driver versions along with the capture settings.
2. Capture a consistent viewport screenshot
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
url = "https://example.gov.in/" # Replace with the public municipal page.
out = Path("screenshots/municipal-home.png")
out.parent.mkdir(parents=True, exist_ok=True)
options = Options()
options.add_argument("--headless")
options.add_argument("--window-size=1440,1200")
driver = webdriver.Chrome(options=options)
try:
driver.set_page_load_timeout(45)
driver.get(url)
# Replace this with a stable element that indicates the needed content is ready.
WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.TAG_NAME, "body"))
)
saved = driver.save_screenshot(str(out))
if not saved or not out.is_file():
raise RuntimeError(f"Screenshot was not saved: {out}")
finally:
driver.quit()
save_screenshot() writes a PNG screenshot of the current window and returns a success value; use a .png path. The sample waits for the body only to make the script concrete. For a useful capture, wait for the actual page heading, service panel, search results, or other content you need. Selenium notes that document readiness does not guarantee that JavaScript-rendered content has finished appearing: Selenium waiting strategies and the Python WebDriver API.
Choose a wait that reflects the page
Prefer an explicit wait for a meaningful condition over a fixed sleep. For example, if the service panel has a stable CSS selector, replace the body wait with:
WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "#service-panel"))
)
Use a selector that exists on the particular portal. If the page updates a result after a search or button click, wait for the result state you need, not just for the initial page to load. Avoid mixing implicit and explicit waits; Selenium warns that doing so can produce unpredictable total wait times.
3. Select viewport or full-page output
A viewport screenshot captures the browser’s current window. Set the window dimensions before navigation or capture because viewport size can change responsive breakpoints, text wrapping, and visible content. The example uses 1440 × 1200 pixels as an illustrative desktop choice, not a standard or benchmark.
| Need | Approach | Check |
|---|---|---|
| One visible screen | Use driver.save_screenshot(). |
Confirm the target content fits inside the chosen viewport. |
| Entire long page as an image | Use a browser and driver API that supports full-document screenshots, or use a scroll-and-stitch workflow. | Verify support in your installed browser/driver; inspect sticky elements, seams, and content that loads only after scrolling. |
| Readable archive of a long page | Consider Selenium’s print-to-PDF path in headless Chromium. | PDF is a different output format, not a PNG screenshot. |
Selenium’s Firefox Python API documents full-page screenshot methods. Do not assume that the general current-window screenshot method captures the full document in every browser. Check the API for your chosen browser and version before relying on a full-page method. If you need a PNG and native full-page capture is unavailable, a scroll-and-stitch process must account for overlap, sticky headers, changing page state, and lazy-loaded content. See the Firefox WebDriver Python API and Selenium’s Chrome documentation.
4. Make captures repeatable and interpretable
- Record the source URL, capture date and time, viewport dimensions, browser and driver versions, operating system, and locale.
- Use a filename that identifies the site or city, page, viewport, and date. For example:
pune-property-tax-desktop-1440x1200-2026-10-03.png. - Keep a companion text record of the capture settings and any page state that affects rendering.
- For a report or public archive, preserve enough context to distinguish the source capture from later edits.
These are reproducibility practices. They do not establish that a particular municipality permits automated access or republication. The Government of India’s Guidelines for Indian Government Websites and Apps include local-government websites in their stated scope and discuss usability, accessibility, and security, but they do not answer the access or reuse rules for a specific portal. Review the target site’s published terms, notices, access controls, and intended-use restrictions. Keep requests conservative, capture only needed pages, and do not try to bypass a login, CAPTCHA, rate limit, or other access control. See the GIGW 3.0 guidance.
5. Troubleshoot common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Chrome fails to start | Chrome is missing, the driver setup is incompatible, or the environment cannot launch a headless browser. | Install a supported Chrome build, check Selenium and browser versions, and review the driver startup error. In restricted server containers, confirm the environment supports the browser process. |
| Screenshot is blank or missing page content | The page has not rendered the needed JavaScript content, or the wait checks an element that appears too early. | Wait explicitly for the heading, result, or panel required. Confirm the selector matches the page and that the element is visible before capture. |
| Capture differs between runs | Viewport, locale, browser version, page state, or dynamically changing content differs. | Fix and record viewport and locale, note browser/driver versions, and capture the same URL and page state. Some pages may still change content over time. |
| Long page is cut off | save_screenshot() captured the current window rather than the full document. |
Use a documented full-page API for the chosen browser, validate its support, or implement and inspect scroll-and-stitch. Use PDF only if a PDF archive meets the need. |
| Wait times out | The selector is wrong, the element never becomes visible, the service is unavailable, or the page state differs from the assumed state. | Inspect the page and selector, wait for the condition that actually signals readiness, and handle the unavailable-page case. Do not increase the timeout blindly without checking the cause. |
| Screenshot cannot be written | The output directory is missing or unwritable, or the path is unsuitable. | Create the parent directory, use a writable absolute or project-relative path, and check the method’s return value and output file. |
6. Performance, reliability, and cost
For one page, browser startup and page rendering are usually the main work; this guide makes no benchmark claim. Reuse a browser session when capturing a small batch of pages with the same settings, but isolate failures so one stalled navigation does not prevent later captures. Set a page-load timeout, use explicit waits with a finite limit, and always call driver.quit() in a finally block so the browser process is closed after success or error.
Keep capture volume proportional to the task and the site’s published rules. Rendering can vary with network conditions and page changes, so a successful navigation alone is not proof that the intended content is present. Selenium itself is open-source software; operational costs can include the machine and time needed to run browsers, storage for the resulting files, and maintenance of browser/driver compatibility. No municipal-site throughput or cost figures are assumed here.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its API returns an image or PDF from one GET request. For example, capture a public municipal page as WebP:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.gov.in/ -o municipal.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.gov.in/"},
timeout=90,
)
r.raise_for_status()
open("municipal.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.gov.in/'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('municipal.webp', Buffer.from(await res.arrayBuffer())));
See the ScreenshotNeo API documentation for request options. Before capture, it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up for 1,000 free screenshots a month with no card.
FAQ
Can I use this for every Indian municipal portal?
The Selenium workflow is general, but page structure and published access conditions vary. Check the specific portal before automating it.
Does the basic script make a full-page PNG?
No. It captures the current window. Use a supported full-document browser API or a validated stitching workflow for a long-page image.
Why wait for a page element if navigation completed?
Navigation readiness does not mean JavaScript-driven content has finished rendering. Wait for the content your capture needs.
Can I save a long page as PDF instead?
Headless Chromium has a Selenium print-to-PDF path. Choose it when a PDF is acceptable; it is not a screenshot image.


