ScreenshotNeo

BlogHow-to

Capture Indian Railway Timetable Webpages as Screenshots with Java Playwright

Use Java Playwright to capture an Indian Railways timetable page as a viewport, full-page, or table screenshot, with runnable code and troubleshooting.

By the ScreenshotNeo team4 October 20269 min read

Use Java Playwright’s Page.screenshot() to save an Indian Railways timetable page as an image. For a full-page capture, set fullPage to true; for a timetable result, first submit a train name or number and wait until the result appears. Full-page mode captures the page’s scrollable content—it does not submit the search or fetch a timetable for you.

This guide uses the official Indian Railways Passenger Reservation Enquiry Train Schedule page. Its stated scope is limited: “Train Schedule is shown only for reserved trains defined in the PRS system.” The page is a schedule lookup, not a guarantee that every train or timetable source is represented.

1. Set up Java Playwright

Playwright for Java requires Java 8 or later. Add the Playwright Java dependency using the installation instructions for your build tool, then install the browser binaries required by the project. The official examples launch a browser headlessly by default. Follow the version-specific Java installation guide so the dependency and browser binaries match.

The following standalone program opens the schedule page and saves a full-page PNG. It captures the page’s initial state; it does not claim to capture a particular train’s result.

import com.microsoft.playwright.*;
import java.nio.file.Paths;

public class CaptureTimetable {
  public static void main(String[] args) {
    String url = "https://indianrail.gov.in/enquiry/SCHEDULE/TrainSchedule.html?locale=en2";
    try (Playwright playwright = Playwright.create()) {
      Browser browser = playwright.chromium().launch();
      try {
        Page page = browser.newPage();
        page.navigate(url, new Page.NavigateOptions().setWaitUntil(WaitUntilState.DOMCONTENTLOADED));
        page.screenshot(new Page.ScreenshotOptions()
            .setPath(Paths.get("timetable.png"))
            .setFullPage(true));
      } finally {
        browser.close();
      }
    }
  }
}

Save it as CaptureTimetable.java in a project with the Playwright Java dependency configured. Run it with that project’s normal Java build or execution command. The output is timetable.png in the process’s working directory. For a real result capture, use the query workflow below before taking the screenshot.

2. Capture a train’s schedule result

  1. Open the schedule page and inspect its current form. The service interface can change, so confirm the live labels and controls before relying on selectors in automation.
  2. Enter the train name or number using the actual search control. The Government of India service listing says users can search after entering at least three characters of a train name or number. Treat that as a useful input guideline and verify current behavior on the live page.
  3. Select the intended suggestion if the interface offers autocomplete, then submit the query using the page’s actual control.
  4. Wait for the schedule result to become visible, then capture it. A successful navigation to the form is not proof that a query result loaded.
  5. Record the query and capture context alongside the image if it will be used as evidence or compared later.

The exact selectors depend on the live page. Inspect the form in a browser or with Playwright’s locator tools, then replace the placeholders below with selectors verified against the page. The explicit checks make the script fail with a useful error instead of silently saving the empty form.

import com.microsoft.playwright.*;
import java.nio.file.Paths;

public class CaptureTrainResult {
  public static void main(String[] args) {
    String url = "https://indianrail.gov.in/enquiry/SCHEDULE/TrainSchedule.html?locale=en2";
    String trainQuery = "REPLACE_WITH_TRAIN_NAME_OR_NUMBER";
    String inputSelector = "REPLACE_WITH_VERIFIED_SEARCH_INPUT_SELECTOR";
    String submitSelector = "REPLACE_WITH_VERIFIED_SUBMIT_SELECTOR";
    String resultSelector = "REPLACE_WITH_VERIFIED_RESULT_SELECTOR";

    try (Playwright playwright = Playwright.create()) {
      Browser browser = playwright.chromium().launch();
      try {
        Page page = browser.newPage();
        page.navigate(url);
        Locator search = page.locator(inputSelector);
        search.waitFor(new Locator.WaitForOptions().setState(WaitForSelectorState.VISIBLE));
        search.fill(trainQuery);
        page.locator(submitSelector).click();
        Locator result = page.locator(resultSelector);
        result.waitFor(new Locator.WaitForOptions()
            .setState(WaitForSelectorState.VISIBLE)
            .setTimeout(30_000));
        page.screenshot(new Page.ScreenshotOptions()
            .setPath(Paths.get("train-schedule.png"))
            .setFullPage(true));
      } finally {
        browser.close();
      }
    }
  }
}

Important: the selector strings are deliberately placeholders, not verified selectors for the current Indian Railways page. Replace them after inspecting the live controls. If the site displays suggestions, selecting one may be a required step before submitting. If the site presents an error or empty table, resolve that state rather than treating it as a timetable capture.

3. Choose viewport, full-page, or element capture

Capture Use it when Java option
Viewport You need only what is visible in the current browser viewport. Omit setFullPage(true).
Full page The schedule or page content continues below the viewport. .setFullPage(true)
Element You need a known schedule table or result region without the surrounding page. Call screenshot() on a matching Locator.
Clipped region You need a specific rectangle and know its coordinates. Set a Clip on screenshot options.

Full-page capture concerns document length, not data completeness. It will not scroll a nested table to reveal content hidden inside that table’s own scroll container. Locator screenshots capture the matching element; for a scrollable element, only its currently scrolled content may be visible. Check the Java screenshots guide and the Page API reference for the API supported by your installed version.

Example of saving just a known result element:

Locator schedule = page.locator("REPLACE_WITH_VERIFIED_RESULT_SELECTOR");
schedule.waitFor(new Locator.WaitForOptions().setState(WaitForSelectorState.VISIBLE));
schedule.screenshot(new Locator.ScreenshotOptions()
    .setPath(Paths.get("schedule-table.png"))); 

4. Screenshot options and output

  • Path: setPath(Paths.get("file.png")) writes the capture to a file. Ensure the process can write to the destination directory.
  • Full page: setFullPage(true) captures the full scrollable document.
  • Type: choose PNG or JPEG with the screenshot options available in your installed Playwright version. Use PNG for crisp text and tables; JPEG can be smaller but may soften fine text. Check version-specific support before selecting other formats.
  • Scale: screenshot scale options can affect output dimensions and file size. Use the documented value appropriate to your installed version and intended output.
  • Clip: specify a rectangle when only a region is needed; coordinate-based clips can miss content if layout or viewport changes.
  • Animation: screenshot options can control animations. This is usually less relevant to a static timetable, but can help make repeated captures consistent.
  • Timeout: the Page API reference documents a 30-second screenshot timeout by default. Set a longer timeout only when the page or full-page render needs it, and check the API docs matching your library version.
  • Bytes: omit the path and use the screenshot method that returns bytes when you need to upload or process the image in memory.
  • Masking: screenshot options support masking matched elements in documented versions. Use it only when masking is appropriate for your record; it changes what the image shows.

For traceability, save a small metadata record with the image: train query, capture timestamp, browser name/version, viewport dimensions, and whether the capture was full-page or element-only. This is practical guidance because a live page and its layout can change; it does not imply that a specific schedule was verified.

5. Common problems and fixes

Symptom Likely cause Fix
The image shows the search form, not a timetable. No query was submitted, the result did not load, or the result selector matched nothing. Complete the live query flow, select any required suggestion, and wait for a verified result element before capturing.
The screenshot contains an error or empty results. The page returned an error or the query did not produce a result. Inspect the page state and query. Do not label an error-state image as a timetable.
TimeoutError while waiting for the result. The locator is wrong, the result is delayed, or the service did not return a result. Verify the selector and page state first. Increase the wait timeout only if a valid result is actually slow to appear.
The file is missing. The output path is relative to an unexpected working directory, or its parent directory is unavailable. Use an absolute path or create the destination directory, and check filesystem permissions.
Content is cut off. Viewport capture was used, or content is inside a nested scroll region. Use full-page capture for document content. For nested scrollable content, scroll that element or capture it in a suitable state.
Text is too small or the image is unexpectedly large. Viewport dimensions or scale are unsuitable for the use case. Set a deliberate viewport and scale, then check the resulting dimensions against the intended display or archive format.
Browser launch fails. The required browser binaries may not be installed for the Playwright dependency in the project. Follow the Java installation guide for the project’s dependency version and install its required browsers.
A selector works today but fails later. The page markup or controls changed. Reinspect the live form, prefer stable accessible labels or roles where available, and keep selector assumptions easy to update.

6. Performance, reliability, and cost

A single browser capture is straightforward, but full-page images can be tall and consume more memory and storage than viewport captures. Capture only the scope you need, select a suitable image format and scale, and avoid launching a separate browser for every URL when processing batches. Reuse a browser process where appropriate, while isolating page state between captures.

For reliability, wait for the specific timetable result rather than relying on a fixed sleep or on navigation completion alone. Sites can load data after the initial document. A selector-based wait gives the script a condition tied to the expected result; still inspect failures because a timeout can mean either slow loading or no result. Avoid assuming that a screenshot proves the schedule is current or complete.

Playwright is an open-source automation library; running it locally means managing Java, browser binaries, execution time, and storage yourself. The cited research does not establish a hosted browser provider, affiliate offer, or per-capture cost comparison, so none is claimed here.

7. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return a screenshot or PDF. For this official timetable page, the basic call captures the page currently served at that URL; it does not fill in a train query. Use Java Playwright when you need to drive the page’s search controls before capture.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://indianrail.gov.in/enquiry/SCHEDULE/TrainSchedule.html?locale=en2 -o timetable.webp

Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": "YOUR_API_KEY",
        "url": "https://indianrail.gov.in/enquiry/SCHEDULE/TrainSchedule.html?locale=en2",
    },
    timeout=90,
)
r.raise_for_status()
with open("timetable.webp", "wb") as output:
    output.write(r.content)

Node.js:

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://indianrail.gov.in/enquiry/SCHEDULE/TrainSchedule.html?locale=en2'
});
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(fs => fs.writeFile('timetable.webp', Buffer.from(await res.arrayBuffer())));

See the ScreenshotNeo API documentation for request options and setup. It removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed; and its response headers say the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account and get 1,000 screenshots a month with no card.

8. FAQ

Does the official schedule page cover every Indian train?

No. The page says it shows schedules only for reserved trains defined in the PRS system.

Does setFullPage(true) make the schedule load?

No. It changes the capture area to the full scrollable page. Submit the query and wait for the result separately.

Can I save the screenshot as bytes instead of a file?

Yes. The Java screenshot API can return image bytes; use that when passing the capture to another service or processing it in memory, and consult the API reference for the method signature in your installed version.

Can I use a screenshot as proof that a train is running now?

A schedule capture records what the page displayed at capture time. It is not, by itself, live running-status information.

Sources