ScreenshotNeo

BlogHow-to

How to Screenshot a GST Portal Page with Playwright After Login

Log in to the GST Portal through its current CAPTCHA and OTP flow, confirm the target page, and capture it safely with Playwright.

By the ScreenshotNeo team4 October 20267 min read

To screenshot an authenticated GST Portal page with Playwright, open the official portal, complete its current login flow for an account you are authorized to use, confirm that the intended page has loaded, and call page.screenshot(). Use fullPage: true for the full scrollable page or locator.screenshot() for one section. The portal may require CAPTCHA and OTP steps; let the account holder complete any challenge and do not attempt to bypass it.

This guide uses TypeScript with Playwright. The same approach works with JavaScript. GST Portal screens and selectors can change, so choose locators from the current page and assert a meaningful signal for the specific authenticated view you need.

1. Install Playwright and prepare private output folders

In a new project, install Playwright Test, which provides the browser API and assertion helpers used below:

npm init -y
npm install --save-dev @playwright/test
npx playwright install chromium

Create directories for captures and, only if you need reusable authentication, browser state. Add them to .gitignore:

mkdir -p artifacts playwright/.auth
printf '\nartifacts/\nplaywright/.auth/\n' >> .gitignore

Saved browser state can include cookies and other credentials-equivalent data. Playwright advises keeping it out of source control. Screenshots of signed-in tax pages can also reveal taxpayer or filing information, so restrict access to both files.

2. Open the official portal and complete login

Navigate to the official GST Portal and follow its current Login flow. Enter credentials through your normal secure process. The portal’s login manual describes CAPTCHA entry and OTP authentication in some circumstances, including first login or a new device. Requirements can vary; the account holder should handle each requested challenge.

Do not assume that filling a username and password is enough. Continue only after the intended authenticated page is visible. A domain check alone does not prove login succeeded because the portal may remain on a login, OTP, or error page.

3. Capture the authenticated page

Below is a runnable TypeScript scaffold. It opens a visible browser so the account holder can complete interactive challenges, waits for an explicit confirmation, and then captures the page. Before using it, set GST_AUTHENTICATED_URL_PATTERN to a URL pattern that identifies the destination you expect after login, and adapt the page-specific assertion to a stable signal on that view. The example deliberately does not automate CAPTCHA or OTP.

import { chromium, expect } from '@playwright/test';

const targetPattern = process.env.GST_AUTHENTICATED_URL_PATTERN;
if (!targetPattern) {
  throw new Error('Set GST_AUTHENTICATED_URL_PATTERN to the expected authenticated page URL pattern.');
}

const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();

try {
  await page.goto('https://www.gst.gov.in/', { waitUntil: 'domcontentloaded' });

  // Follow the portal's current Login flow. Complete CAPTCHA and any OTP
  // challenge manually as the authorized account holder.
  console.log('Complete login in the browser, then navigate to the intended GST page.');
  await page.pause();

  await expect(page).toHaveURL(new RegExp(targetPattern));

  // Replace this with a locator or assertion specific to the target page.
  // For example: await expect(page.getByRole('heading', { name: '...' })).toBeVisible();

  await page.screenshot({ path: 'artifacts/gst-page.png', fullPage: true });
  console.log('Saved artifacts/gst-page.png');
} finally {
  await browser.close();
}

Run it with your expected URL pattern. The pattern is a regular expression, so escape punctuation such as dots:

GST_AUTHENTICATED_URL_PATTERN='your-escaped-expected-path' npx tsx capture-gst.ts

If you use a plain JavaScript file, install tsx for the TypeScript example above, or remove the type-specific tooling and run equivalent JavaScript with Node. Do not put passwords, OTPs, or session values in source code or command history.

4. Choose the screenshot scope

  • Current viewport: await page.screenshot({ path: 'artifacts/gst-page.png' }); captures what is currently visible.
  • Full scrollable page: await page.screenshot({ path: 'artifacts/gst-page.png', fullPage: true }); captures beyond the viewport.
  • One element: await page.locator('YOUR_SELECTOR').screenshot({ path: 'artifacts/gst-section.png' }); captures a particular panel or region. Replace the selector with one verified against the current page.
  • Image bytes: const image = await page.screenshot(); returns a buffer for further processing instead of writing directly to a file.

Use a viewport capture when only the visible state matters, full-page capture for a long view, and a locator capture when you need one specific section. Large full-page images may be tall and contain more sensitive data than expected; review them before sharing.

5. Reuse an authenticated session only when necessary

For repeated captures, you can save browser state after a successful login and load it in a later context. Session state may expire, and the portal may ask for authentication again. Do not persist state for a one-off capture unless you have a clear need.

// After the account holder has logged in and you have confirmed the target view:
await context.storageState({ path: 'playwright/.auth/gst-user.json' });

// In a later script, create a context using that state:
const context = await browser.newContext({
  storageState: 'playwright/.auth/gst-user.json'
});

Keep playwright/.auth access-controlled, excluded from version control, and remove or refresh saved state when it is no longer needed. Playwright’s standard storage state includes cookies, local storage, IndexedDB, and passkey authentication; it does not include session storage by default. If the portal’s session depends on session storage, a saved state file may not recreate it.

6. Or skip the browser setup

If you need a screenshot of a publicly accessible GST Portal page, ScreenshotNeo can capture it with one GET request. It cannot use your authenticated browser session: never send private credentials or session cookies to an API unless you have explicitly designed and secured that integration. For a public page, see the ScreenshotNeo API documentation and use:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://www.gst.gov.in/ -o shot.webp

ScreenshotNeo accepts cookie and consent banners as 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, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and whether the request was billed. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. 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.

Sign up for 1,000 free screenshots a month, with no card required.

7. Troubleshooting

Symptom Likely cause What to do
Screenshot shows the login page Authentication did not finish, a challenge is still pending, or navigation returned to login. Complete the current CAPTCHA or OTP flow as the account holder. Confirm the target page with a page-specific assertion before capturing.
OTP or CAPTCHA interrupts the run The portal requires an interactive account verification step. Use a visible browser and let the authorized account holder complete it. Do not attempt to bypass the challenge or assume unattended completion will work.
URL assertion fails The expected pattern is unset, incorrectly escaped, or does not match the actual destination. Inspect the URL after manual login, set a suitable regular expression, and add a page-specific locator assertion. A matching GST domain alone is insufficient confirmation.
Element locator times out The selector is stale, the target has not rendered, or the page differs from the assumed view. Inspect the live page, choose a current role, label, or CSS locator, and wait for that element to become visible before capture.
Saved state does not restore login State expired, the portal demands a new challenge, or required session data was not persisted. Log in again through the normal flow and refresh state only if reuse is appropriate. Standard storage state does not include session storage.
Capture is unexpectedly long or huge fullPage: true includes a long page or additional content. Capture the viewport or a specific locator instead, and review full-page output for sensitive information.
Browser executable is missing Playwright’s browser binary was not installed for the project. Run npx playwright install chromium for the selected browser.

8. Performance, reliability, and handling sensitive files

A viewport screenshot generally captures less content and produces a smaller image than a full-page capture. Locator screenshots can reduce output to the relevant panel. Avoid adding arbitrary long waits: wait for a meaningful page-specific signal so a slow login or a stale view does not silently produce the wrong image.

Reliability depends on the portal’s current login requirements, session validity, page rendering, and selectors. Authentication may require a person, and selectors may change; treat this as a guided browser workflow rather than a guaranteed unattended job. If you save state for reuse, handle expiry and re-authentication explicitly.

Store screenshots in a restricted location, inspect them for GSTINs, names, email addresses, balances, and filing details, and share only what is needed. Delete temporary captures and authentication state when they are no longer required. These privacy precautions follow from the sensitive content an authenticated tax page may display.

FAQ

Can I run the login entirely headless?

This guide uses a visible browser because the portal may request interactive CAPTCHA or OTP. Whether a particular account flow can run unattended is not established here; follow the portal’s current requirements.

Does a GST Portal URL check prove that I am logged in?

No. Confirm the exact destination and a page-specific element or other signal that belongs to the authenticated view.

Can I use ScreenshotNeo with my logged-in GST session?

The one-call example captures a public URL and does not inherit your browser’s authenticated session. Keep private session data protected.

Should I save authentication state for a single screenshot?

Usually not. Save it only when reuse is needed and you can protect the file like a credential.