How to Capture a Puppeteer Screenshot of an Aadhaar Service Website
Capture an authorized UIDAI page with Puppeteer, choose a reliable wait condition, and protect Aadhaar details before sharing screenshots.
Use Puppeteer’s page.screenshot() on a UIDAI page you are authorized to capture. For a public information page, navigate to the page, wait for an appropriate ready condition, then save the image. Avoid capturing authenticated myAadhaar pages containing Aadhaar numbers, VID, OTPs, credentials, demographic information, or offline e-KYC material if the image will be shared. UIDAI describes its main site as informational and associated portals such as myAadhaar as service portals that may require personal information and authentication. UIDAI’s site and website policy are the authority for the page and reuse requirements.
Capture a public UIDAI page with Puppeteer
The following is an illustrative Node.js workflow for a public page. It saves a full-page PNG and closes the browser even if navigation or capture fails. Use the Puppeteer version already installed in your project and check its API reference for the exact options supported by that version.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 1000 });
await page.goto('https://uidai.gov.in/', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'uidai-page.png', fullPage: true });
} finally {
await browser.close();
}
This example uses networkidle2 as a possible wait condition; it is not guaranteed to work for every page. Pages with analytics, streaming requests, or other ongoing activity may never become idle. For a page with a known content landmark, wait for that selector instead. Puppeteer documents Page.screenshot(); its default result is a Uint8Array, while the base64 encoding overload returns a base64 string.
Install and run
In a new Node.js project, install Puppeteer and save the example as capture.mjs:
npm install puppeteer
node capture.mjs
Puppeteer downloads a compatible browser as part of its usual installation. If your environment supplies its own Chrome or Chromium, configure launch() with that environment’s executable path and ensure the runtime has the libraries and permissions the browser needs.
Choose a wait condition and capture scope
| Need | Approach | Trade-off |
|---|---|---|
| Initial document load | waitUntil: 'load' |
Does not guarantee that client-rendered content or images are ready. |
| DOM is parsed | waitUntil: 'domcontentloaded' |
May be early for content populated by scripts. |
| Network activity mostly settles | waitUntil: 'networkidle2' |
Can be unsuitable for pages with persistent network requests. |
| Known content is visible | Navigate, then await page.waitForSelector('...') |
Requires a stable selector on the page. |
| Entire document | { fullPage: true } |
Creates a potentially tall image; review its dimensions and content. |
| Visible viewport only | Omit fullPage |
Content outside the current viewport is not included. |
For example, replace the navigation and capture lines with a selector wait when the page has a known landmark:
await page.goto('https://uidai.gov.in/', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('main', { visible: true, timeout: 15000 });
await page.screenshot({ path: 'uidai-page.png', fullPage: true });
Choose a selector that actually exists on the target page; main is only an example. If a wait times out, inspect the page structure and use a more specific, stable selector. A fixed delay can be used for known animations, but it is less reliable than waiting for the content the screenshot needs.
Viewport and output
Set the viewport before navigation when responsive layout matters. A desktop viewport such as 1440 by 1000 pixels and a mobile-sized viewport produce different layouts. Use fullPage: true for a document capture; omit it for the viewport. You can save another supported format by choosing a matching path extension and the type option supported by your Puppeteer version, such as JPEG or WebP. Check the installed version’s API documentation before relying on less common screenshot settings.
Protect Aadhaar information and respect reuse terms
- Prefer public informational pages. Do not automate Aadhaar authentication or OTP flows just to make a screenshot.
- Before sharing a screenshot, inspect it for Aadhaar numbers or VID, OTPs, credentials, account details, demographic data, and private e-KYC contents. A screenshot preserves whatever is visible in the browser.
- UIDAI’s FAQ says service providers shall not share, publish, or display offline e-KYC XML, share codes, or their contents. The statement specifically names service providers; do not treat it as a complete ruling on every screenshot scenario. See the UIDAI FAQ.
- UIDAI’s website policy asks that reused material be accurate, not misleading, and attributed with the source page URL. Check the policy and any third-party rights before publishing an actual page image; the policy does not settle every licensing question.
- If an authorized internal workflow requires an authenticated view, restrict access to the resulting file and redact sensitive information before wider sharing. Keep credentials and authentication material out of logs and artifacts.
UIDAI notes that some service portals may request Aadhaar number or VID, mobile number, and OTP, and that usage logs, authentication events, and service interactions may be recorded. See its website policy for the portal and credential context.
Return screenshot bytes instead of writing a file
For a pipeline that uploads the image or processes it in memory, omit path and store the returned bytes. Keep the buffer private if it may contain personal information.
const imageBytes = await page.screenshot({ type: 'png', fullPage: true });
// imageBytes is a Uint8Array by default; pass it to your authorized storage or processing step.
For base64 output, use the base64 encoding overload documented for the Puppeteer version installed in your project. Avoid printing either the image bytes or a base64 representation to logs.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
TimeoutError during navigation |
The chosen readiness event does not occur, or the page keeps network requests open. | Try a less restrictive navigation condition, then wait for the specific visible content needed for the capture. Set a bounded timeout appropriate to the job. |
| Screenshot is blank or missing content | Capture happened before client-rendered content appeared, or the wrong page loaded. | Check the response and final page URL, then wait for a visible content selector before capture. |
| Browser fails to launch | Browser dependencies, executable path, or sandbox permissions are incompatible with the runtime. | Use the browser installed for the Puppeteer version or configure the correct executable; install required system libraries and use the runtime’s documented container settings. |
| Output file is absent | The process lacked write permission or the relative path points somewhere unexpected. | Use a writable output directory and an explicit path; handle filesystem errors in the calling process. |
| Image is unexpectedly huge or clipped | Full-page capture includes a long document, or viewport dimensions differ from the intended layout. | Choose viewport-only or full-page deliberately, set dimensions before navigation, and inspect the output before sharing. |
| Personal information appears in the artifact | The captured page exposed account or authentication data. | Do not publish it. Restrict access, remove the artifact where appropriate, and create a redacted capture from an authorized workflow. |
Performance, reliability, and cost
Launching a browser has more setup and resource overhead than making a direct screenshot API request, especially when a process launches a fresh browser for each page. For batches, reuse a browser process where your application’s isolation and lifecycle requirements allow it, and close pages and the browser when finished. Bound navigation and selector waits so stuck pages do not occupy workers indefinitely. Full-page captures use more memory and produce larger files as page height grows.
Reliability depends on the target site, network, chosen readiness condition, and browser environment. A successful navigation does not prove that the intended content loaded: check the final URL, expected page content, and the saved image. UIDAI pages and policies can change, so confirm the current page and policy before publishing.
Puppeteer is open source, but browser execution still consumes compute, memory, storage, and network capacity in your environment. Estimate cost from your own workload and deployment. Avoid retries that repeatedly submit sensitive forms; capture public pages and retry only transient navigation or infrastructure failures.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its one-call API can return an image or PDF. The request below captures a public UIDAI page as WebP; see the ScreenshotNeo API documentation for options.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://uidai.gov.in/ -o uidai.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://uidai.gov.in/"},
timeout=90,
)
r.raise_for_status()
open("uidai.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://uidai.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(({ writeFile }) =>
writeFile('uidai.webp', new Uint8Array(await res.arrayBuffer()))
);
ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, and cache hits are not billed. Its response includes X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Use it for public pages and do not send Aadhaar credentials or personal information to a screenshot service.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Can I screenshot a myAadhaar page that requires OTP?
Puppeteer can capture a page your authorized session can access, but this guide does not cover automating Aadhaar authentication. Avoid retaining or sharing a capture that contains personal or authentication data.
Does fullPage: true capture content below the fold?
It requests a full-page screenshot. Review the result because dynamic or lazy-loaded content may need additional page-specific waiting.
Can I use a screenshot in a published article?
Check UIDAI’s current reuse policy and relevant third-party rights, reproduce material accurately, and attribute the source page as requested by the policy.


