Capture Indian Court Case Status Pages with Python Playwright and Save Screenshots
Use Python Playwright to look up a case on the correct official eCourts portal, wait for the result, and save a focused or full-page screenshot.
Direct answer: use Python Playwright to open the official portal for the specific court, fill in a search field that portal actually provides, wait for the case result to appear, then call page.screenshot(). Indian court portals do not share one universal form or selector sequence, so the target court, bench where applicable, and official URL must be identified before selectors can be made runnable. The template below is complete as a browser-and-screenshot workflow; adapt its marked portal-specific steps after inspecting the chosen page.
This guide captures information displayed by a public service. It does not interpret case status, verify that the displayed data is correct, or make a screenshot a certified court record. Record when and where you captured it if that context matters.
1. Choose the official court page and search method
The eCourts Services portal provides case status and related court information. The available lookup options include CNR number, case number, Filing Number, party name, advocate name, FIR number, and Act. Choose an option supported by the particular portal and for which you have the relevant identifier. See the [eCourts Services portal](https://ecourts.gov.in/ecourts_home/) and its [official app help and user guide](https://ecourts.gov.in/ecourts_home/static/manuals/HelpManualEnglish.pdf).
For High Court services, first choose the High Court and bench, then select the search criterion. The High Court services flow is not interchangeable with every district court flow. Check the [eCourts High Court services](https://hcservices.ecourts.gov.in/) and any notices on the specific court page. Some services have CAPTCHA or other human-facing steps; do not try to bypass them. Pause for authorized human interaction or use an official permitted alternative.
| Identifier you have | Possible search | What to check |
|---|---|---|
| CNR | Search by CNR Number | The eCourts help describes a CNR as 16 alphanumeric characters entered without spaces or hyphens. |
| Case details | Case Number | The portal may ask for case type, number, year, court, or other fields. |
| Filing details | Filing Number | Confirm the exact fields and format required by the selected court. |
| Person or matter details | Party Name, Advocate Name, FIR Number, or Act | These options may not be present on every portal and can return multiple results. |
2. Install Playwright
Use a supported Python environment and install the Playwright package and browser binaries. The official [Playwright Python library guide](https://playwright.dev/python/docs/library) gives current setup details.
python -m pip install playwright
python -m playwright install chromium
Run the install command for the browser you plan to launch and the operating system where the script will run. In a container or CI environment, follow Playwright’s system dependency instructions as well.
3. Inspect the selected portal before writing selectors
Open the exact official URL in a normal browser and note its search flow. Identify the actual accessible labels, button names, result heading, and any court or bench selection steps. Prefer Playwright locators based on labels, roles, and text when available; avoid positional selectors that depend on page layout. Playwright describes locators as central to its [auto-waiting and retry behavior](https://playwright.dev/python/docs/locators).
There is no honest universal selector for “CNR Number” or “Search” across all Indian court pages. Replace the illustrative locator lines below with selectors verified against your target page. If the page requires a CAPTCHA, stop for a human to complete it; do not automate a solution or bypass.
4. Run the Python capture workflow
This script launches Chromium, opens the selected page, performs a placeholder search flow, waits for a result condition, and writes a PNG with a capture timestamp in a companion metadata file. Set the URL and identifiers from the portal you have selected. Uncomment and adapt the locator lines using the live page’s real labels and result text.
from datetime import datetime, timezone
from pathlib import Path
import json
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeoutError
TARGET_URL = "https://replace-with-the-selected-official-court-page"
OUTPUT = Path("case-status.png")
# Prefer environment variables or a secret manager for real case identifiers.
CNR = "REPLACE_WITH_16_CHARACTER_CNR"
with sync_playwright() as playwright:
browser = playwright.chromium.launch(headless=True)
page = browser.new_page(viewport={"width": 1440, "height": 1000})
try:
response = page.goto(TARGET_URL, wait_until="domcontentloaded", timeout=60_000)
if response is not None and response.status >= 400:
raise RuntimeError(f"Court page returned HTTP {response.status}")
# Adapt these to the selected portal. A High Court flow may first
# require choosing a High Court and bench before the search method.
# page.get_by_label("CNR Number").fill(CNR)
# page.get_by_role("button", name="Search").click()
# Wait for a specific, verified result locator rather than sleeping.
# page.get_by_text("Case Details", exact=True).wait_for(
# state="visible", timeout=30_000
# )
# Do not save a blank landing page as if it were a case result.
# Uncomment after adapting and verifying the result condition above.
# OUTPUT.parent.mkdir(parents=True, exist_ok=True)
# page.screenshot(path=str(OUTPUT), full_page=True)
# Capture metadata alongside the screenshot after a successful result.
captured_at = datetime.now(timezone.utc).isoformat()
metadata = {
"source_url": TARGET_URL,
"captured_at_utc": captured_at,
"screenshot": str(OUTPUT),
}
OUTPUT.with_suffix(".json").write_text(
json.dumps(metadata, indent=2), encoding="utf-8"
)
except PlaywrightTimeoutError as exc:
raise RuntimeError(
"Timed out waiting for navigation or the adapted result condition. "
"Check the portal flow, locator, network, and any human-facing challenge."
) from exc
finally:
browser.close()
Before using the script for a real capture, uncomment and adapt the search and result lines, then place screenshot saving after the result wait. The template intentionally does not claim that a guessed selector works on an unspecified court page. If the page uses a different identifier, replace the CNR step with the portal’s supported Case Number, Filing Number, Party Name, Advocate Name, FIR Number, or Act flow.
Choosing what to capture
page.screenshot(path="case-status.png")captures the current viewport.page.screenshot(path="case-status.png", full_page=True)captures the full scrollable page.page.locator("YOUR_VERIFIED_SELECTOR").screenshot(path="case-details.png")captures one selected element.
Element screenshots are useful when the page contains navigation or unrelated material, but only use a selector you verified on the chosen portal. Full-page captures can include more personal information than necessary. Capture and retain only what the task requires. Playwright documents these choices in [Screenshots](https://playwright.dev/python/docs/screenshots).
5. Waiting for the right result
Playwright waits for actionability around actions such as clicking, and locators retry while waiting for a condition. After submitting a search, wait for an observable result: a case-details heading, a result row, or another target-specific element. A successful navigation alone does not prove that a search succeeded.
Avoid using time.sleep() as the primary synchronization method. A fixed delay can be too short on a slow response and waste time on a fast one; it can also leave the page in an outdated state. Use locator waits and suitable navigation conditions as described in the [auto-waiting guide](https://playwright.dev/python/docs/actionability) and [library guide](https://playwright.dev/python/docs/library).
6. cURL, Node.js, and API alternative
For direct browser automation of the specific court workflow, the Python template above is the relevant method. These cURL and Node.js examples call ScreenshotNeo to capture a URL; they do not fill a court form, solve a CAPTCHA, or substitute for inspecting the official portal. Use only on a publicly accessible page and in accordance with the portal’s access terms. ScreenshotNeo supports screenshot output and configurable capture options; see the [API documentation](https://screenshotneo.com/docs/).
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://ecourts.gov.in/ecourts_home/ \
-o court-page.webp
Python requests
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://ecourts.gov.in/ecourts_home/",
},
timeout=90,
)
r.raise_for_status()
with open("court-page.webp", "wb") as output:
output.write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://ecourts.gov.in/ecourts_home/',
});
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(({ writeFile }) =>
writeFile('court-page.webp', Buffer.from(await res.arrayBuffer()))
);
These API calls capture the page URL as it loads. They cannot enter a CNR into a form unless the desired result page is itself directly addressable and publicly accessible. Do not put private case identifiers or personal data in URLs or logs without a clear basis to do so.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Locator times out | The portal label or control differs, an earlier court/bench choice is required, or the page has not reached the expected state. | Inspect the exact page and flow; update the locator and wait for a real result condition. |
| Screenshot shows a search form, not case details | The search step was not performed, did not submit, or returned no result. | Verify the identifier and portal fields, submit through the real control, and wait for a result element before capture. |
| Blank or incomplete screenshot | The page content had not rendered, a navigation failed, or the result condition was too weak. | Check the response and visible page state; wait for the target result locator, then capture. |
| Search returns many rows | The selected search method is broad, such as a name-based lookup, or needs additional court/year details. | Use a more specific supported identifier or inspect and capture only the intended result. |
| CAPTCHA or human challenge appears | The service requires a person to complete the challenge or imposes an access check. | Do not bypass it. Stop for authorized human interaction or use a permitted official route. |
| Browser launch fails in a server/container | Browser binaries or operating-system dependencies are missing. | Install the matching Playwright browser and required dependencies using the official library guide. |
| Screenshot file is missing | The script raised before the screenshot line, or that line remains commented pending selector adaptation. | Confirm the result wait succeeded and enable the screenshot save immediately afterward. |
8. Performance, reliability, and handling
- Use a narrow wait: waiting for the specific result locator avoids arbitrary delays and avoids treating the landing page as a completed lookup.
- Keep the capture small: viewport or element capture is often enough to show the relevant result; full-page mode can take longer and expose unrelated data.
- Handle failure explicitly: check navigation responses, catch timeouts, and do not write a success artifact when the expected result was not visible.
- Record provenance: keep the official source URL and a UTC capture time in adjacent metadata if needed. A screenshot only records what the browser displayed at capture time; it does not certify authenticity or current legal status.
- Protect identifiers: avoid embedding CNRs, names, or other identifying details in public logs, filenames, or shared screenshots. Restrict access and retention to what the task needs.
- Cost: local Playwright uses the computer or CI environment where it runs; budget for that environment and its browser dependencies. ScreenshotNeo has a free tier of 1,000 shots/month without a card; paid plans start at $5 for 3,000 shots. API captures are billed only when clean shots are returned, and response headers indicate page verdict and billing.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers, made by Yorker Media. One GET request captures a URL as PNG, JPEG, WebP, or PDF. It removes cookie and consent banners from 60+ known platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses include X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. It does not perform the court search form interaction shown in the Playwright workflow.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://ecourts.gov.in/ecourts_home/ \
-o court-page.webp
See the ScreenshotNeo API documentation for options such as full-page capture, element selectors, wait conditions, custom headers, and output format. ScreenshotNeo offers 1,000 screenshots a month free with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo, then sign up for the free plan.
FAQ
Can one Playwright script work on every Indian court portal?
No. Portal forms, court and bench selection, labels, and result structure vary. Verify the exact official page and adapt the locators and flow.
What if I do not have a CNR?
Check which alternatives the selected service offers. eCourts help lists Case Number, Filing Number, Party Name, Advocate Name, FIR Number, and Act as alternatives, though availability depends on the portal.
Does a screenshot prove the status is legally valid or current?
No. It shows what was rendered at the recorded capture time. It is not a certified record or legal interpretation.
Can the ScreenshotNeo URL call search by CNR?
Not by itself. It captures a page URL; the Python Playwright workflow is for interacting with a portal’s search form.


