How to Generate Website Previews for an Indian Government Scheme Links Directory
Build useful scheme directory previews with clear source ownership, safe metadata fetching, accessible cards, and reliable fallbacks.
A useful preview for an Indian government scheme directory should make the destination understandable before someone opens it: show the scheme name, the responsible department when known, a short description, and the destination URL. Keep a direct link to the source and make clear whether it is an official government destination. These fields are an implementation recommendation based on government guidance about page metadata, ownership, and meaningful links; they are not a prescribed GIGW preview format.
For a dependable directory, keep a reviewed record for each scheme and use remote page metadata only as an optional enrichment. Treat destination pages as untrusted input, do not execute their scripts, and provide an editorial fallback when automated retrieval fails. GIGW 3.0 addresses quality, accessibility, usability, and security for government websites, portals, web applications, and apps. It was formulated jointly with STQC and CERT-In; CERT-In formulated its cybersecurity chapter. GIGW introduction
1. Decide what each preview should communicate
A preview is a navigation aid, not proof that a scheme is currently open or that a linked page is authoritative. Separate information maintained by your directory from information observed on the destination.
| Field | Recommended source | Why it matters |
|---|---|---|
| Scheme name | Reviewed directory record | Gives the link a meaningful purpose. |
| Responsible department or organization | Official department information, verified by an editor | Helps readers identify ownership and distinguish the directory from the source. |
| Short summary | Prefer an editor-written summary; metadata can be a draft input | Explains what a reader will find without relying on visual context. |
| Destination URL and host | Reviewed canonical destination | Makes the actual external destination visible. |
| Last checked date | Your directory process | Signals when the link record was last reviewed; it does not guarantee current scheme availability. |
| Optional thumbnail | A screenshot generated from the destination | Can help distinguish pages visually, but must not carry information available only in the image. |
GIGW recommends relevant page metadata, necessary metadata in the HTML read by search engines, meaningful link text, and identification of page ownership. Use these as design principles for previews. Do not claim that GIGW requires Open Graph tags, a particular card layout, or automated screenshots. GIGW guidelines
2. Store a reviewed directory record
Maintain stable editorial data independently of any live fetch. The following JSON shape is an example application schema, not an official government schema:
{
"scheme_name": "Example public scheme",
"department": "Responsible department",
"official_url": "https://example.gov.in/scheme",
"summary": "A short, editor-written explanation of the destination.",
"last_checked": "2026-10-04",
"thumbnail_url": null
}
Before publication, verify the scheme name, department, and destination against the relevant official source. Where the official source cannot be established, label the destination accurately and do not style the card to imply government ownership. The Integrated Government Online Directory describes itself as the official directory of Indian Government websites, while cautioning that linked sites may not comply with GIGW and that readers should verify information with the relevant department. iGOD description and policy · iGOD website policies
3. Fetch page metadata safely (optional)
Fetching a destination can supply a candidate title and description when your editorial record is incomplete. It should not be the source of truth: pages can block bots, omit metadata, change ownership, or return misleading content. The official guidance reviewed does not prescribe a metadata-fetching protocol; the following are general safeguards for an application that makes server-side requests.
- Allow only HTTP and HTTPS URLs, and preferably maintain an allowlist of reviewed government domains or exact destinations.
- Resolve hostnames and reject loopback, private, link-local, and reserved IP addresses. Repeat the checks after DNS resolution and for every redirect to reduce server-side request forgery risk.
- Limit redirect count, connection and total time, and response bytes. Reject unexpected content types.
- Read HTML as data only. Do not run scripts, load subresources, or render a page in a privileged browser as part of metadata extraction.
- Extract only known fields such as the document title and description metadata. Decode entities, strip markup, and cap displayed text length.
- Cache results for a bounded period and keep the reviewed record as the fallback. Record retrieval time separately from the editorial last-checked date.
These controls are engineering recommendations, not GIGW-mandated preview-fetch rules. A production government website, web application, portal, or mobile app should have security audit clearance before production hosting, according to GIGW security guidance. GIGW security guidance
Example metadata fetch in Python
This small example is suitable only for a controlled list of trusted destinations. It uses a fixed URL, disables redirects, applies a timeout and byte limit, and parses HTML without executing it. It is not a complete SSRF defense for arbitrary user-supplied URLs; production code should enforce DNS/IP and redirect validation as described above.
from html.parser import HTMLParser
import requests
URL = "https://example.gov.in/scheme"
MAX_BYTES = 1_000_000
class Metadata(HTMLParser):
def __init__(self):
super().__init__()
self.title = []
self.in_title = False
self.description = ""
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag.lower() == "title":
self.in_title = True
if tag.lower() == "meta":
name = attrs.get("name", "").lower()
if name == "description":
self.description = attrs.get("content", "")
def handle_endtag(self, tag):
if tag.lower() == "title":
self.in_title = False
def handle_data(self, data):
if self.in_title:
self.title.append(data)
response = requests.get(
URL,
headers={"User-Agent": "SchemeDirectoryPreview/1.0"},
timeout=(3.05, 8),
allow_redirects=False,
stream=True,
)
response.raise_for_status()
content_type = response.headers.get("Content-Type", "").lower()
if "text/html" not in content_type:
raise ValueError(f"Expected HTML, received {content_type!r}")
chunks = []
total = 0
for chunk in response.iter_content(16_384):
total += len(chunk)
if total > MAX_BYTES:
raise ValueError("HTML response exceeds configured limit")
chunks.append(chunk)
parser = Metadata()
parser.feed(b"".join(chunks).decode(response.encoding or "utf-8", errors="replace"))
title = " ".join(" ".join(parser.title).split())[:180]
description = " ".join(parser.description.split())[:300]
print({"title": title, "description": description, "status": response.status_code})
For arbitrary destinations, add a URL validation layer before this request: resolve and validate the address, pin or otherwise protect the connection against DNS rebinding, revalidate each redirect target, and enforce outbound network policy. A simple hostname string check alone is not sufficient.
4. Render an accessible preview card
Keep the link operable without a thumbnail, and put the destination purpose in the link text. Avoid a generic “click here.” If the card contains multiple actions, use separate links with distinct names rather than nesting interactive elements.
<article class="scheme-card">
<h2>Example public scheme</h2>
<p>Responsible department: Department name</p>
<p>A short, editor-written explanation of the destination.</p>
<p>Official destination: <code>example.gov.in</code></p>
<p>Directory record last checked: <time datetime="2026-10-04">4 October 2026</time></p>
<a href="https://example.gov.in/scheme" target="_blank" rel="noopener noreferrer">
Open the Example public scheme page on example.gov.in (opens in a new tab)
</a>
</article>
Use semantic headings, readable contrast, visible keyboard focus, and a sufficiently large link target. If a thumbnail is decorative, use empty alternative text; if it conveys distinct information, provide equivalent text nearby. Do not put the scheme name or destination only inside an image. GIGW calls for meaningful link text and accessibility practices. GIGW accessibility and link guidance
5. Add an optional screenshot thumbnail
A screenshot can illustrate how a destination page looks, but it can become stale and should not replace the title, summary, department, URL, or accessible link. Use it only as a supplement, set a refresh policy, and provide an editorial fallback when the capture is blank or unavailable.
For a self-managed browser capture, use a browser automation library such as Playwright: navigate to a reviewed destination, wait for a bounded load condition, capture a viewport or full page, and store the result with the URL and capture timestamp. The exact setup depends on your runtime and deployment; do not run untrusted destination code with access to credentials or internal network resources.
Example browser capture with Playwright
import { chromium } from "playwright";
const url = "https://example.gov.in/scheme";
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
await page.screenshot({ path: "scheme-preview.png", fullPage: true });
} finally {
await browser.close();
}
For a recurring directory, place browser workers behind outbound restrictions, cap concurrency and page duration, and store generated assets in your own controlled storage. Check the destination policy and applicable terms before capturing or redistributing page imagery. GIGW’s linking terms apply to GIGW itself; they do not automatically govern each scheme site. GIGW link policy
6. Choose a resilient refresh and fallback policy
- Keep the reviewed record available if metadata fetch or screenshot capture fails.
- Show a last-checked date, and distinguish it from the time an automated preview was fetched.
- Do not infer that a scheme has ended because its page times out, blocks bots, or returns an error.
- Use bounded retries with backoff for transient failures; do not retry indefinitely or on every page view.
- Refresh thumbnails and metadata asynchronously, not in the reader’s critical page-render path.
- Provide a report or editorial review path for broken links and incorrect ownership.
GIGW emphasizes relevant and current content, page ownership, navigation, and contact information. A directory should make it easy to reach the responsible body and verify details at the source. GIGW guidance
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers, made by Yorker Media. One GET request can return a PNG, JPEG, WebP, or PDF. For a thumbnail, request the destination page and save the image response. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.gov.in/scheme -o scheme-preview.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.gov.in/scheme"},
timeout=90,
)
r.raise_for_status()
open("scheme-preview.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.gov.in/scheme'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('scheme-preview.webp', bytes));
Cookie and consent banners are accepted and removed before capture, along with 60+ known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan. Review the destination yourself and retain your directory’s editorial verification and fallback records.
Sign up for 1,000 free screenshots a month, with no card required.
8. Performance, reliability, and cost
- Keep page loads fast: serve stored thumbnails from your asset layer or CDN, use appropriately sized images, and lazy-load below-the-fold cards.
- Control capture work: generate images asynchronously, bound worker concurrency and timeouts, and avoid capturing the same URL repeatedly when a cached result is still acceptable.
- Plan for destination variability: government sites may be slow, temporarily unavailable, or resistant to automated access. A screenshot is best-effort enrichment, not a dependency for opening the directory.
- Manage costs: self-hosted browser workers consume compute and storage. Measure your own workload before sizing it; no general benchmark applies across sites and pages. With ScreenshotNeo, only clean shots are billed; select a plan based on expected volume and use its configurable caching where appropriate.
- Protect availability: use queues, bounded retries, stale-but-labeled previews, and editorial fallbacks so destination outages do not break directory rendering.
9. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| No title or description | The site omits metadata, fills it with JavaScript, or serves different content to bots. | Use the reviewed scheme record and editor-written summary; do not execute scripts just to fill a card. |
| Request times out | The origin is slow, unreachable, or waiting on resources. | Use a finite timeout, bounded retry policy, and the stored fallback. Do not make readers wait for capture. |
| Redirect to an unexpected host | The destination changed, uses a redirect service, or may be unsafe. | Stop the fetch, validate the new destination and ownership, then update the reviewed record if appropriate. |
| Private or internal address is fetched | URL validation did not account for DNS resolution, redirects, or address changes. | Block private, loopback, link-local, and reserved IPs at connection time; revalidate after DNS and each redirect. |
| Huge response exhausts memory | The response has no practical size limit. | Stream the body and stop after a configured byte limit; reject unsupported content types. |
| Screenshot is blank or shows a challenge | The page blocked automation, failed to load, or depends on interaction. | Keep the editorial card and direct link; do not represent the screenshot as evidence the scheme is unavailable. |
| Screenshot thumbnail is stale | The refresh job failed or has no expiry policy. | Track capture time, refresh asynchronously, and label or remove thumbnails past your chosen freshness window. |
| Card is confusing to screen-reader or keyboard users | Generic link text, image-only information, missing focus state, or nested controls. | Use meaningful link names, visible focus, text equivalents, and separate interactive elements. |
10. Frequently asked questions
Does GIGW prescribe a website-preview card format?
The cited guidance covers metadata, accessibility, meaningful links, ownership, content, and security. It does not prescribe a scheme-directory preview format.
Should the directory display only government domains?
Apply a clear editorial rule and label destinations accurately. The iGOD guidance warns that linked websites may not comply with GIGW; verify information with the relevant department.
Can an automated preview confirm that a scheme is active?
No. A reachable page or screenshot does not establish current eligibility, funding, or application status. Link readers to the responsible source and keep status claims editorially verified.
Can I reuse GIGW’s linking terms for every destination?
No. GIGW’s own policy describes linking to GIGW and its banners. Review the linking and content policies of each destination separately.
Implementation checklist
- Store reviewed scheme name, owning body, destination, editor-written summary, and last-checked date.
- Make official ownership and external destinations clear without implying endorsement.
- Use meaningful link text and ensure the card works without its image.
- Validate outbound destinations and bound redirects, response size, time, and concurrency.
- Keep metadata and screenshot retrieval optional, asynchronous, and backed by a stable fallback.
- Check each site’s policies and verify scheme details with the responsible department.


