ScreenshotNeo

BlogHow-to

Generate PDF Screenshots of Indian Invoice Webpages in Java

Use Playwright for Java to save an Indian invoice webpage as a PDF or screenshot, with print and screen CSS, authentication, and rendering guidance.

By the ScreenshotNeo team4 October 202610 min read

For an existing Indian invoice webpage, use Playwright for Java to create either a paginated PDF with page.pdf() or a pixel-based image with page.screenshot(). These are different outputs: PDF generation follows print layout and pagination, while a full-page screenshot captures the page as pixels. The examples below show both. They do not assume that any particular GST or invoice portal supports automated capture.

1. Choose a PDF or an image screenshot

Need Use What it produces
A document that can span pages and be printed page.pdf() A paginated PDF using print CSS by default
One tall image of the whole scrollable page page.screenshot() with fullPage: true A single image of the page, subject to browser and image-size limits
Only the invoice panel, table, or receipt Locator screenshot An image of a selected element
A PDF made from page pixels Capture an image and place it in a PDF separately Usually one image per page or a scaled image; text may not be selectable

If the page’s on-screen layout is the requirement, note that Playwright’s PDF method uses print media by default. Use media emulation to select screen media before calling pdf(). If the desired result is a normal printable document, leave print media active and tune the paper size, margins, background, and page-break behavior.

2. Set up a Java project

Use a current Playwright Java release from its official documentation. The Maven coordinates below use the documented artifact name; check the official Java getting-started guide for the current version before pinning it.

<dependency>
  <groupId>com.microsoft.playwright</groupId>
  <artifactId>playwright</artifactId>
  <version>YOUR_PLAYWRIGHT_VERSION</version>
</dependency>

Install the browser binaries using the command documented for the selected Playwright Java version. For Maven projects, this is commonly run through the Playwright CLI after resolving the dependency. Browser installation is a separate deployment concern: ensure the runtime image includes the selected browser and its system dependencies.

3. Generate a PDF from an invoice page

This runnable example accepts the page URL and output path as command-line arguments. It waits for navigation to reach domcontentloaded, then waits for the invoice element to appear. Replace #invoice with a selector that identifies the rendered invoice in the target application.

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

public class InvoicePdf {
  public static void main(String[] args) {
    if (args.length < 2) {
      System.err.println("Usage: InvoicePdf <url> <output.pdf>");
      System.exit(2);
    }

    String url = args[0];
    String output = args[1];

    try (Playwright playwright = Playwright.create()) {
      Browser browser = playwright.chromium().launch(
          new BrowserType.LaunchOptions().setHeadless(true));
      BrowserContext context = browser.newContext();
      Page page = context.newPage();

      page.navigate(url, new Page.NavigateOptions()
          .setWaitUntil(WaitUntilState.DOMCONTENTLOADED)
          .setTimeout(60_000));

      // Prefer a meaningful invoice selector over a fixed sleep.
      page.locator("#invoice").waitFor(new Locator.WaitForOptions()
          .setState(WaitForSelectorState.VISIBLE)
          .setTimeout(30_000));

      page.pdf(new Page.PdfOptions()
          .setPath(Paths.get(output))
          .setFormat("A4")
          .setPrintBackground(true)
          .setMargin(new Page.PdfMargins()
              .setTop("12mm")
              .setRight("12mm")
              .setBottom("12mm")
              .setLeft("12mm")));

      browser.close();
    }
  }
}

Run it with a URL the browser process can access:

mvn compile
mvn exec:java -Dexec.mainClass=InvoicePdf -Dexec.args="https://example.com/invoice invoice.pdf"

For a page styled for the screen rather than print, set screen media before PDF generation:

page.emulateMedia(new Page.EmulateMediaOptions().setMedia(Media.SCREEN));
page.pdf(new Page.PdfOptions().setPath(Paths.get(output)).setPrintBackground(true));

Print CSS is often intentionally different from screen CSS. For a stable invoice PDF, consider adding print styles in the application to control page breaks, hide navigation, preserve table headers, and avoid splitting totals across pages. The page format, margins, scale, background printing, and CSS page-size preference are configurable in the Playwright Page API.

4. Save a full-page or targeted screenshot

For a single image containing the scrollable page, use the screenshot API’s full-page option. For an image of only the invoice, take a locator screenshot instead. The official Playwright Java screenshot guide covers full-page, element, and byte-buffer capture.

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

public class InvoiceImage {
  public static void main(String[] args) {
    String url = args.length > 0 ? args[0] : "https://example.com/invoice";

    try (Playwright playwright = Playwright.create()) {
      Browser browser = playwright.chromium().launch(
          new BrowserType.LaunchOptions().setHeadless(true));
      Page page = browser.newPage();
      page.navigate(url, new Page.NavigateOptions()
          .setWaitUntil(WaitUntilState.DOMCONTENTLOADED)
          .setTimeout(60_000));
      page.locator("#invoice").waitFor(new Locator.WaitForOptions()
          .setState(WaitForSelectorState.VISIBLE)
          .setTimeout(30_000));

      page.screenshot(new Page.ScreenshotOptions()
          .setPath(Paths.get("invoice-full.png"))
          .setFullPage(true));

      page.locator("#invoice").screenshot(new Locator.ScreenshotOptions()
          .setPath(Paths.get("invoice-element.png")));
      browser.close();
    }
  }
}

Image screenshots can also be returned as bytes rather than written directly to disk, which is useful when storing the result in object storage or passing it to another service. Full-page captures can become very large for unusually long pages; a PDF or a targeted element capture may be more practical.

5. Handle authentication and dynamic invoice content

Invoice pages may require a signed-in session or may render data after navigation. Authenticate through the application’s supported login flow or an authorized session. Do not put passwords, access tokens, or invoice data in source control or command-line arguments that may be logged. Use environment-based secrets or a secure secret store, and follow the application’s access controls.

Wait for a meaningful condition: a visible invoice selector, a known invoice number element, or an application-specific ready state. A fixed delay is less reliable because page speed varies. If content appears only after a user action, perform that action through the page API and then wait for the expected result. Avoid treating networkidle as universal proof that a page is ready; analytics, polling, and long-lived connections can keep a page active. The reviewed sources do not establish behavior for a specific Indian invoice portal or login flow.

6. Output options that affect the result

PDF settings

  • Paper size: select the required format, such as A4, or use CSS page sizing when the document defines it.
  • Margins: set all four explicitly when consistent printable bounds matter.
  • Backgrounds: enable background printing if colored fills or background graphics are part of the invoice.
  • Screen or print media: choose the CSS mode before generating the PDF. Print is the default for PDF output.
  • Pagination: use print CSS to control page breaks and avoid splitting important invoice sections.
  • Scale: adjust cautiously; scaling to fit may make fine invoice text hard to read.

Screenshot settings

  • Full page: captures the scrollable page in one image.
  • Element: captures a locator’s bounds and is useful for the invoice itself without site navigation.
  • Image type: select PNG when lossless detail matters; use JPEG or WebP when supported by the chosen workflow and smaller files are preferred.
  • Bytes or path: write directly to a path or consume the returned byte array in application code.

7. Alternative Java PDF tools

Apache PDFBox creates and manipulates PDFs and can render PDFs as images. It is useful when the input is already a PDF or when building a document from structured content. It does not, by itself, reproduce a live browser page’s dynamic layout.

OpenHTMLtoPDF renders a supported subset of HTML and CSS to PDF or images. Its project documentation cautions that modern HTML may need adaptation. Consider it when you control the markup and its supported subset meets the document’s needs; for an existing dynamic webpage, browser rendering is generally the closer match.

8. Or skip the browser setup

If you need a screenshot image of a publicly reachable invoice page and want to avoid managing browser binaries, ScreenshotNeo provides a website screenshot API and MCP server. See the API documentation for its options. This Java example makes one GET request and saves the response body:

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;

public class ScreenshotNeoCapture {
  public static void main(String[] args) throws Exception {
    String apiKey = System.getenv("SCREENSHOTNEO_API_KEY");
    String targetUrl = args.length > 0 ? args[0] : "https://example.com/invoice";
    if (apiKey == null || apiKey.isBlank()) {
      throw new IllegalStateException("Set SCREENSHOTNEO_API_KEY first");
    }

    String query = "access_key=" + URLEncoder.encode(apiKey, StandardCharsets.UTF_8)
        + "&url=" + URLEncoder.encode(targetUrl, StandardCharsets.UTF_8);
    HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://api.screenshotneo.com/v1/shot?" + query))
        .timeout(Duration.ofSeconds(90))
        .GET()
        .build();

    HttpResponse<byte[]> response = HttpClient.newHttpClient().send(
        request, HttpResponse.BodyHandlers.ofByteArray());
    if (response.statusCode() < 200 || response.statusCode() >= 300) {
      throw new RuntimeException("Screenshot request failed with HTTP " + response.statusCode());
    }
    Files.write(Path.of("invoice-shot.webp"), response.body());
  }
}

The service removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, and cache hits are not billed; response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for MCP clients including Claude and Cursor. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. For private invoices, confirm that the page can be accessed through the API’s supported authentication options and that sending its URL and content to an external screenshot service is appropriate for your use.

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card required.

9. cURL, Python, and Node.js API examples

The following examples use the ScreenshotNeo endpoint and write an image response. Store the API key in a secret manager or environment variable in production. Review the documentation for format and capture parameters.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key="$SCREENSHOTNEO_API_KEY" \
  --data-urlencode url="https://example.com/invoice" \
  -o invoice-shot.webp

Python

import os
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": os.environ["SCREENSHOTNEO_API_KEY"],
        "url": "https://example.com/invoice",
    },
    timeout=90,
)
r.raise_for_status()
with open("invoice-shot.webp", "wb") as f:
    f.write(r.content)

Node.js

import { writeFile } from 'node:fs/promises';

const q = new URLSearchParams({
  access_key: process.env.SCREENSHOTNEO_API_KEY,
  url: 'https://example.com/invoice',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await writeFile('invoice-shot.webp', Buffer.from(await res.arrayBuffer()));

10. Troubleshooting

Symptom Likely cause What to do
PDF is laid out differently from the browser PDF generation uses print CSS by default, or print rules change the layout. Emulate screen media before pdf() if screen styling is required; otherwise inspect and adjust the page’s print CSS.
Invoice content is missing The app rendered it after navigation, the selector is wrong, or the session is not authenticated. Verify authorized access, wait for the invoice’s actual selector or ready state, and inspect the page after navigation.
Text or colored areas are absent in PDF Background printing is disabled, or the page relies on background graphics. Enable printBackground and check print-specific styles.
PDF content is clipped or split awkwardly Paper dimensions, margins, scale, or print page-break rules do not fit the invoice. Set the intended paper size and margins; add print CSS rules for page breaks and invoice sections.
Navigation times out The site is slow, unreachable from the browser runtime, or never reaches the selected wait condition. Check network access and the target URL; use a suitable navigation milestone, then wait for the specific invoice content.
Full-page screenshot is enormous or fails The page is unusually tall or includes expansive content. Capture the invoice element, split the capture into sections, or generate a paginated PDF.
Browser launches locally but fails in deployment The browser binary or required operating-system libraries are missing from the runtime. Install the browser version associated with the Playwright dependency and include its runtime dependencies in the deployment image.
Screenshot API response is not an image The request failed or returned an error response. Check the HTTP status and response headers before saving the body; verify the key and URL and consult the API documentation.

11. Performance, reliability, and cost

Browser capture requires a browser process and its runtime dependencies, so reuse a browser for multiple pages where the application architecture allows it, while keeping separate contexts for sessions that must not share cookies. Wait on the smallest meaningful invoice-ready condition to avoid unnecessary delay. Keep timeouts bounded and report navigation, readiness, and output errors separately. For very long pages, element capture or a paginated PDF can use less memory than one giant image.

Reliability depends on the target page, its authentication and rendering behavior, network access, and the browser environment. A successful navigation does not prove that invoice data rendered correctly; validate the expected selector and, where appropriate, the resulting file’s size or page count. Do not log invoice contents or credentials. Cost for a self-hosted Playwright workflow includes the compute and maintenance of the browser runtime; actual cost depends on deployment and workload, and no benchmark is implied here. ScreenshotNeo’s stated plans are Free: 1,000 shots/month, Starter: $5 for 3,000, Growth: $15 for 15,000, Pro: $39 for 60,000, Scale: $99 for 250,000, and Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan.

12. Frequently asked questions

Can I turn a screenshot image into a PDF?

Yes, with a separate image-to-PDF step, but the result is image-based and may not preserve selectable text or natural pagination. Use browser PDF generation when document pagination matters.

Can I capture only the invoice and omit the surrounding website?

Yes. Use a locator screenshot for an image, or use the page’s print styles to hide surrounding elements in PDF output.

Does this guarantee compatibility with an Indian GST portal?

No. Portal behavior, authentication, and permitted access vary. The examples use a generic page and require validation against the specific authorized page.

Which Java library should I use to create PDFs from my own data?

PDFBox is suited to creating or manipulating PDFs directly. OpenHTMLtoPDF can render supported HTML/CSS. For an existing browser-rendered invoice, Playwright provides browser-based PDF and screenshot capture.