How to Automate Screenshots of Indian Public Exam Result Pages with Selenium
Use Selenium to wait for an authorized exam result page, capture its viewport or result element, and save a PNG without assuming every portal works alike.
Use Selenium WebDriver to open an authorized exam results page, wait for a page-specific result heading or table, and save a PNG. A normal WebDriver screenshot captures the browser’s visual viewport; an element screenshot captures the visible region of a selected element after scrolling it into view. Neither should be assumed to capture an entire long page. The result selector and access requirements depend on the specific portal.
Before automating, confirm that the page belongs to the exam authority or an authorized results platform, and review its current terms and access controls. NIC’s results portal terms say its content can change without notice; those terms do not establish rules for every state board, university, recruitment body, or third-party site. If a CAPTCHA or another access control blocks automation, stop and use the authorized human or official path. Do not automate solving or bypassing it. The Indian Government Website Guidelines describe CAPTCHA as a human-access check and discuss alternative sensory modes.
1. Install Selenium and choose a browser
This example uses Python and Chrome. Selenium’s current Python binding can manage browser drivers through Selenium Manager when a compatible browser is installed. Install the binding in your environment:
python -m pip install selenium
Use an environment where you are permitted to run the browser, and check the target portal’s current access instructions. For a first run, a visible browser can make it easier to see whether the page reached a result, a login screen, a CAPTCHA, or an error page. Headless mode is optional; it does not grant access or make a blocked request authorized.
2. Inspect the page and identify a result-ready condition
Open the official page manually first. Identify a stable selector for a result heading, result table, or other content that appears only after the result is available. Use the browser’s developer tools to inspect the page you are authorized to access. There is no universal selector for Indian exam portals, and portal markup may change.
For a results table, a CSS selector might be table#result or .result-table, but these are examples only. Replace the URL and selector in the script below with values from the actual page. If the page requires a person to enter details, an OTP, or a CAPTCHA, do not add automation that defeats that step.
3. Capture a viewport screenshot with Python Selenium
Save this as capture_result.py. It takes the target URL, a CSS selector, and an output filename from command-line arguments. It waits for the selector to become visible, checks that the screenshot write succeeded, and always closes the browser. The selector is intentionally supplied by you because each portal differs.
import argparse
from pathlib import Path
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, WebDriverException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
def main():
parser = argparse.ArgumentParser(
description="Capture an authorized exam result page viewport as PNG."
)
parser.add_argument("url", help="Official or authorized result page URL")
parser.add_argument(
"selector",
help="Inspected CSS selector for a result heading/table that indicates readiness",
)
parser.add_argument("--output", default="exam-result.png", help="PNG output path")
parser.add_argument("--timeout", type=int, default=45, help="Wait limit in seconds")
parser.add_argument("--headless", action="store_true", help="Run Chrome headlessly")
args = parser.parse_args()
output = Path(args.output)
if output.suffix.lower() != ".png":
parser.error("--output must end in .png")
output.parent.mkdir(parents=True, exist_ok=True)
options = webdriver.ChromeOptions()
if args.headless:
options.add_argument("--headless=new")
# A fixed window size makes viewport captures more consistent across runs.
options.add_argument("--window-size=1440,1000")
driver = None
try:
driver = webdriver.Chrome(options=options)
# A guard against navigation hanging; this does not mean dynamic results are ready.
driver.set_page_load_timeout(args.timeout)
driver.get(args.url)
# Wait for a page-specific signal, not just for navigation to return.
result_element = WebDriverWait(driver, args.timeout).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, args.selector))
)
# Capture what is visible in the browser viewport.
saved = driver.save_screenshot(str(output))
if not saved or not output.is_file() or output.stat().st_size == 0:
raise OSError(f"Screenshot was not written: {output}")
print(f"Saved viewport screenshot to {output.resolve()}")
print(f"Matched result element: {result_element.tag_name}")
except TimeoutException as exc:
raise SystemExit(
"Timed out waiting for the page or result selector. Check the URL, "
"selector, portal availability, and whether a human step is required."
) from exc
except (WebDriverException, OSError) as exc:
raise SystemExit(f"Capture failed: {exc}") from exc
finally:
if driver is not None:
driver.quit()
if __name__ == "__main__":
main()
Run it with your inspected target URL and selector:
python capture_result.py "https://official.example/results" "table#result" --output captures/result.png
The example URL and selector are placeholders, not a real exam portal. Selenium’s screenshot documentation shows viewport and element screenshot methods. The Python API documents that save_screenshot writes PNG and returns False on an I/O error. The WebDriver specification defines a viewport screenshot and a separate element screenshot of the visible region after the element is scrolled into view: W3C WebDriver screen capture.
4. Capture only the result element
If the result block is the useful artifact, save the element instead of the whole viewport. Replace the screenshot line in the script with result_element.screenshot(str(output)). The element method scrolls the element into view and captures its visible region. If a table is taller than the viewport, one element screenshot may not contain every row; use a verified full-page approach or separate captures only where permitted and appropriate.
# Replace driver.save_screenshot(str(output)) with:
saved = result_element.screenshot(str(output))
5. Choose the right capture scope and wait condition
| Need | Method | Watch for |
|---|---|---|
| What a person sees in the current browser viewport | driver.save_screenshot("result.png") |
Content below the viewport is omitted. |
| One result block | element.screenshot("result.png") |
Only the element’s visible region is captured; long elements may be clipped. |
| Dynamic result rendered after navigation | Wait for a visible, inspected result-specific selector | A page-load timeout alone does not prove the dynamic content is ready. |
| Document longer than the viewport | Use a full-page method verified for your browser, or capture permitted sections | Standard viewport capture is not a full-document screenshot. |
Selenium exposes set_page_load_timeout to bound navigation. Keep a separate explicit wait for the result condition. Choose a condition that actually indicates a usable result: visibility is often better than mere presence in the DOM, and a page-specific status or row count may be needed if the table appears before its data.
6. Protect candidate information and verify the output
- Use a predictable filename such as an exam name and date; avoid putting a candidate’s roll number, name, or other personal identifier in the path.
- Check that the PNG exists and has nonzero size. Open it and confirm that it shows the expected page state, not a loading screen, error, login prompt, or CAPTCHA.
- Do not publish candidate identifiers or result details unless you have authority and a clear need to share them. Store captures only as long as needed and restrict access appropriately.
- For authoritative result information, refer readers to the exam authority. NIC notes that portal information can change; a screenshot is a record of a page view, not a substitute for current official information.
7. Reliability, performance, and cost considerations
A capture run uses a real browser session, so its duration depends on the portal response, browser startup, page rendering, and your explicit wait. Reuse a browser only when repeated captures are authorized and session state is understood; otherwise, close it after each run as in the example. Avoid aggressive polling or repeated retries against a public results site. If a request fails, inspect the page and follow the portal’s stated process rather than trying to evade controls.
Selenium itself is open-source browser automation software; running it has infrastructure costs such as the machine and time used for browser sessions. This workflow does not provide a performance guarantee. Keep screenshots out of public logs and use careful file permissions, especially where result pages contain personal data.
8. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
TimeoutException waiting for the selector |
The selector is wrong or stale, the result has not loaded, navigation went elsewhere, or a human step is required. | Open the authorized page manually, inspect its current markup and state, update the selector, and raise the timeout only if the normal page legitimately needs longer. Stop if blocked by an access control. |
| Screenshot shows a loading page or empty table | Navigation completed before the result data rendered, or the chosen selector appears before rows populate. | Wait for a more specific stable condition, such as a visible result row or a page status indicating data is ready. Inspect the authorized page; do not assume a selector works across portals. |
| Screenshot file is missing or empty | Output directory permissions, invalid path, I/O error, or the browser failed before capture. | Use a writable output path, ensure the parent directory exists, retain the return-value and file-size checks, and inspect the reported WebDriver error. |
| Browser or driver fails to start | Browser is missing, unsupported, or unavailable in the execution environment. | Install a supported browser and current Selenium package, then review Selenium’s official browser setup guidance. In managed environments, use the browser and driver versions provided by that environment. |
| Only part of the table appears | The default screenshot is viewport-scoped; an element screenshot is scoped to the element’s visible region. | Adjust the viewport if a larger viewport is acceptable, use a verified full-page capture method, or capture separate sections when permitted. |
| The page displays CAPTCHA, access denied, or a bot check | The portal requires human access or has denied automation. | Do not solve or bypass it with automation. Stop and use an authorized human or official route, or ask the portal operator about permitted access. |
| Selector matches the wrong content | Selectors such as generic table or h1 are not specific enough. |
Inspect the page and use a selector tied to the result region; verify the element text or another page-specific signal before saving. |
Or skip the browser setup
For an authorized page that can be captured through an API, ScreenshotNeo takes a screenshot with one GET request. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Replace the example URL with a page you are authorized to capture. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. See ScreenshotNeo for product details and the docs for configuration. A screenshot service does not authorize access to a protected exam portal or bypass its access controls.
Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.
FAQ
Does Selenium save screenshots as PNG?
Yes. Selenium’s Python save_screenshot method saves the current window screenshot as PNG; use a filename ending in .png.
Will this work on every Indian exam results portal?
No single selector or access procedure applies to every portal. Check the specific authority’s current page and requirements, and adapt the readiness condition to its current markup.
Can I automate a CAPTCHA if the result is public?
No. Public result information does not mean a human-access check may be bypassed. Stop automation at that boundary and use the portal’s authorized path.
Is a screenshot the same as an official result record?
No. It records a visual page state. Refer to the exam authority for current and authoritative result information.


