How to Use a Screenshot API from Java in an Indian Web App
Capture a web page from Java, save or serve the image bytes, and configure language, time zone, IP country, and browser geolocation for Indian visitors.
To use a screenshot API from a Java web app, keep the provider credentials on your server, send the target URL and capture options to the API, then save or return the response image bytes. For an Indian web app, first decide what “Indian” means: an app deployed in India, or a screenshot that represents an Indian visitor. The localization settings below can request India-specific rendering; they do not establish India-region hosting or data residency.
This guide uses ScreenshotOne’s documented Java SDK and REST endpoint as the do-it-yourself example. The SDK is published as com.screenshotone.jsdk:screenshotone-api-jsdk; check the provider’s current Java documentation for the current release and compatibility details before pinning a version. The documented dependency uses the range [1.0.0,2.0.0). See the Java SDK documentation and API getting-started guide.
1. Choose the right kind of India localization
“Render this for India” can mean several different things. A destination website may use one or more signals to choose language, currency, prices, or content. Set the signals the site actually reads:
| Signal | What it controls | When to set it |
|---|---|---|
| IP country | The country associated with the outgoing request IP | The site selects content based on IP location; use ip_country_code=in. |
| Language and locale | Language preference and locale-based formatting | Set an Accept-Language header, for example en-IN or hi-IN, according to the test case and site support. |
| Time zone | Browser-local time and date behavior | Use Asia/Kolkata when the page displays local dates or times. |
| Browser geolocation | Coordinates exposed through the browser Geolocation API | Set coordinates only when the page asks the browser for location; IP country does not set browser coordinates. |
| Site preference | Market or language selected inside the site | Use the localized URL, preference cookie, or market selector if that is how the site remembers a choice. |
These settings are independent. An Indian IP alone does not guarantee Indian-language content, and browser geolocation does not change the request IP country. ScreenshotOne documents in as a supported ip_country_code; proxy routing can add latency. Its documentation describes country-IP rendering, not India-region compute or data residency. Verify hosting and data-location terms with the provider if your application has those requirements. See the localization guide and option reference.
2. Add the Java SDK and keep credentials server-side
Add the documented Maven dependency. The version range below follows the provider’s cited example; confirm the current release and your Java compatibility needs before production use.
<dependency>
<groupId>com.screenshotone.jsdk</groupId>
<artifactId>screenshotone-api-jsdk</artifactId>
<version>[1.0.0,2.0.0)</version>
</dependency>
Keep API credentials in deployment configuration or a secrets manager. Do not commit them or send a secret signing key to a browser. In a typical deployment, configure environment variables such as SCREENSHOTONE_ACCESS_KEY and SCREENSHOTONE_SECRET_KEY, then inject them through your application’s configuration system. Keep the capture call on the server whenever possible. The provider’s API key guidance covers access keys and signed requests.
3. Capture a screenshot in Java
This example follows the documented Java SDK pattern: configure a URL and viewport, request PNG output, receive bytes, and write them to a file. It expects the two environment variables to be present.
import com.screenshotone.jsdk.Client;
import com.screenshotone.jsdk.TakeOptions;
import java.nio.file.Files;
import java.nio.file.Path;
public class CapturePage {
public static void main(String[] args) throws Exception {
String accessKey = System.getenv("SCREENSHOTONE_ACCESS_KEY");
String secretKey = System.getenv("SCREENSHOTONE_SECRET_KEY");
if (accessKey == null || accessKey.isBlank()) {
throw new IllegalStateException("SCREENSHOTONE_ACCESS_KEY is required");
}
if (secretKey == null || secretKey.isBlank()) {
throw new IllegalStateException("SCREENSHOTONE_SECRET_KEY is required");
}
String targetUrl = args.length > 0 ? args[0] : "https://example.com";
Client client = Client.withKeys(accessKey, secretKey);
TakeOptions options = TakeOptions.url(targetUrl)
.fullPage(true)
.deviceScaleFactor(1)
.viewportWidth(1200)
.viewportHeight(1200)
.format("png");
byte[] image = client.take(options);
Files.write(Path.of("screenshot.png"), image);
}
}
Run it with credentials set in the environment and optionally pass a URL. Consult the SDK documentation for supported option methods and exceptions for the SDK version you install.
export SCREENSHOTONE_ACCESS_KEY='YOUR_ACCESS_KEY'
export SCREENSHOTONE_SECRET_KEY='YOUR_SECRET_KEY'
java CapturePage.java https://example.com
The SDK can also generate a screenshot URL instead of fetching the image bytes. Use the URL workflow when it fits your delivery model, but do not expose a URL containing a raw access key. For a public browser-facing link, use the provider’s signed-request flow; otherwise, fetch on the server and return the image through an application endpoint governed by your own access and retention policy.
4. Set India-specific rendering options
When using the SDK, pass the equivalent supported request options through the SDK version you selected. The REST examples below show the option names explicitly. A practical starting set for a site that uses India IP, English language preference, and local time is:
ip_country_code=in
headers=Accept-Language:en-IN
time_zone=Asia/Kolkata
Choose hi-IN instead if you need Hindi preference and the destination supports it. Some sites use a market selector or a preference cookie instead of headers or IP. If browser geolocation is needed, supply both latitude and longitude, and optionally accuracy; do not set coordinates just to imply an India IP. Use coordinates that are appropriate for the test scenario and permitted by your application.
Country-IP routing may be slower than a request without that option. Only enable it when the page’s behavior depends on IP location. A localized URL or site preference can be a better fit when the destination offers a stable market-specific route.
5. REST examples: cURL, Python, and Node.js
The same integration can use HTTP directly instead of the Java SDK. ScreenshotOne documents https://api.screenshotone.com/take, HTTPS, GET and POST. GET is convenient for command-line use; POST accepts a JSON body and avoids placing long option sets in a URL. Image responses are binary, with a content type matching the requested format. Check status codes and documented JSON error details before treating a response as an image.
cURL
curl --get 'https://api.screenshotone.com/take' \
--data-urlencode 'access_key=YOUR_ACCESS_KEY' \
--data-urlencode 'url=https://example.com' \
--data-urlencode 'format=png' \
--data-urlencode 'full_page=true' \
--data-urlencode 'ip_country_code=in' \
--data-urlencode 'headers=Accept-Language:en-IN' \
--data-urlencode 'time_zone=Asia/Kolkata' \
--output screenshot.png
Python
Install the HTTP client with python -m pip install requests. This example checks the status before writing the response body so an error response is not saved with a misleading image extension.
import os
import requests
params = {
"access_key": os.environ["SCREENSHOTONE_ACCESS_KEY"],
"url": "https://example.com",
"format": "png",
"full_page": "true",
"ip_country_code": "in",
"headers": "Accept-Language:en-IN",
"time_zone": "Asia/Kolkata",
}
response = requests.get(
"https://api.screenshotone.com/take",
params=params,
timeout=90,
)
response.raise_for_status()
with open("screenshot.png", "wb") as image_file:
image_file.write(response.content)
Node.js
This example uses the built-in fetch API in a Node.js runtime that provides it. It checks the status and writes the binary response to disk.
import { writeFile } from 'node:fs/promises';
const q = new URLSearchParams({
access_key: process.env.SCREENSHOTONE_ACCESS_KEY,
url: 'https://example.com',
format: 'png',
full_page: 'true',
ip_country_code: 'in',
headers: 'Accept-Language:en-IN',
time_zone: 'Asia/Kolkata'
});
const res = await fetch(`https://api.screenshotone.com/take?${q}`);
if (!res.ok) {
throw new Error(`Screenshot API returned HTTP ${res.status}: ${await res.text()}`);
}
await writeFile('screenshot.png', Buffer.from(await res.arrayBuffer()));
Java REST with JSON POST
If you prefer not to add the Java SDK, Java’s built-in HTTP client can submit a JSON request. The API documentation says POST accepts JSON; confirm the current request schema and option types in the provider docs. This example uses Java 11 or later APIs and Jackson for JSON serialization.
// Maven dependency for Jackson Databind:
// com.fasterxml.jackson.core:jackson-databind (use your approved current version)
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Map;
public class CaptureWithRest {
public static void main(String[] args) throws Exception {
String accessKey = System.getenv("SCREENSHOTONE_ACCESS_KEY");
if (accessKey == null || accessKey.isBlank()) {
throw new IllegalStateException("SCREENSHOTONE_ACCESS_KEY is required");
}
Map<String, Object> body = Map.of(
"access_key", accessKey,
"url", "https://example.com",
"format", "png",
"full_page", true,
"ip_country_code", "in",
"headers", new String[] {"Accept-Language:en-IN"},
"time_zone", "Asia/Kolkata"
);
String json = new ObjectMapper().writeValueAsString(body);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.screenshotone.com/take"))
.timeout(Duration.ofSeconds(90))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<byte[]> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException("Screenshot API returned HTTP "
+ response.statusCode() + ": " + new String(response.body()));
}
Files.write(Path.of("screenshot.png"), response.body());
}
}
Do not log a request URL if it contains an access key. Also avoid logging full error bodies when they might echo sensitive request details.
6. Return or store the image in a web app
The screenshot bytes can be written to local storage, an object store, or returned by your own endpoint. Choose a storage location and retention policy that match your application. If returning bytes from a Java HTTP endpoint, set the response content type to image/png for PNG output and an appropriate cache policy. Do not send arbitrary user-controlled destination URLs straight to a screenshot provider: validate allowed schemes and hosts, impose request limits, and decide how to prevent your endpoint from being used to capture internal services.
If the browser needs an image, a server-side proxy endpoint keeps provider credentials out of client code. Alternatively, a signed public link can be useful when the image should load directly in an <img> tag. Follow the provider’s rules for signed links and never expose the secret signing key. See the API key documentation.
7. Options to consider for production
| Need | Configuration decision | Trade-off or edge case |
|---|---|---|
| Full page | Enable full-page capture. | Long pages can take more time and produce larger files; lazy-loaded content may need an appropriate wait strategy. |
| Viewport consistency | Set viewport width and height, plus device scale factor. | A CSS viewport and pixel output dimensions are not always the same when scale factor changes. |
| File format | Choose PNG, JPEG, or WebP as supported by the provider and client. | Make the output extension and HTTP content type match the actual format. |
| Wait for rendering | Use a selector, delay, or network-idle option when the page needs time to render. | Long fixed delays add latency; network activity that never settles can make network-idle unsuitable. |
| Authentication or personalization | Send only the needed headers or cookies using the documented options. | Treat captured pages and credentials as sensitive; avoid leaking secrets into logs or shared URLs. |
| Reliability | Set a client timeout, handle non-success responses, and apply bounded retries for transient failures. | Do not blindly retry invalid requests or repeated failures; retries can multiply load and spend. |
| Repeated captures | Consider caching when the target content does not change often. | Choose freshness and cache behavior deliberately; stale screenshots may be incorrect for dynamic pages. |
| Many URLs | Use a bulk or asynchronous workflow if offered by the provider and appropriate to the workload. | Track per-item failures and avoid treating a partially completed batch as fully successful. |
ScreenshotOne supports GET and POST, and its API returns binary image content on success; its documented errors include HTTP status codes and JSON details. Treat those response types separately. For a robust integration, verify the content type and status before saving bytes, set an application-level timeout, and record a request correlation identifier if the provider exposes one in its current docs.
8. Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
| 401 or authorization error | Missing, invalid, or incorrectly configured access key; malformed signed request. | Read credentials from the intended environment, check for whitespace, and follow the provider’s current signing instructions. Never paste a secret key into browser code. |
| 4xx response with JSON instead of an image | Invalid URL or option name/value, or a malformed request. | Check the status and parse the JSON error body. URL-encode GET parameters or send a correctly serialized JSON POST body. |
| Image file contains JSON or appears corrupt | The client saved an error response as if it were an image. | Check HTTP status and content type before writing the response bytes. |
| Wrong language or market | The site uses a localized path, cookie, selector, or a signal other than the one configured. | Test language header, IP country, time zone, site preference cookie, and market selector separately. The website determines how it uses these signals. |
| Location-dependent page still appears elsewhere | IP country and browser geolocation are different signals. | Set ip_country_code=in for IP-based content; set both geolocation coordinates only if the site uses browser location. |
| Request is slower after localization | Country proxy routing can add latency; full-page capture or heavy pages also take longer. | Enable country routing only when needed, choose a suitable wait condition, and set a realistic timeout. |
| Blank or incomplete screenshot | Capture occurred before client-rendered content appeared, a selector was wrong, or the site blocked the request. | Use a documented wait option, confirm the URL works, inspect provider error details, and test whether the content requires authentication or a site-specific interaction. |
| File not found or permission denied | Deployment working directory differs from local development, or the process cannot write there. | Write to an explicitly configured writable path or stream bytes to approved storage. |
| Timeouts and repeated failures | Slow destination, overly strict timeout, or an unavailable dependency. | Bound retries, use backoff for transient errors, and surface final failure to callers rather than returning an empty image. |
9. Performance, reliability, and cost
Rendering a page is network- and browser-work intensive. A larger viewport, full-page capture, slow target site, delayed JavaScript, and country-IP routing can all increase completion time or payload size. Avoid unnecessary waits and options; use a cache when the page’s freshness requirements allow it. For high-volume jobs, use a queue and limit concurrency so a burst of user requests does not overwhelm your app or the capture provider.
Set timeouts at the HTTP client and application layers. Retry only transient failures, use a bounded retry count with backoff, and make duplicate work safe where your application can do so. Distinguish a provider error from a valid image response. Store enough operational information to diagnose failures, but redact credentials, signed URLs, and sensitive page data.
The research material does not establish ScreenshotOne’s current price, quota, SLA, Java runtime compatibility guarantees, or India-region data handling terms. Check current commercial and contractual documentation for those specifics instead of assuming them. Compare providers on Java SDK maintenance, REST behavior, authentication and signing, output formats, rendering controls, India localization, error handling, latency, quotas, and data terms. The available material documents Browserless’s REST pattern—POST to /screenshot with an API token and JSON, returning configured image formats—but does not support a comparative claim about performance or pricing. See the Browserless documentation.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request returns a PNG, JPEG, WebP, or PDF. Its Java-friendly integration can use the REST API directly:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
See the ScreenshotNeo API documentation for request options and response details. ScreenshotNeo accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks, blank pages, and failed loads are never billed, and responses identify the page verdict and billing status in headers. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
FAQ
Does “India rendering” mean the screenshot is processed in India?
No such conclusion follows from setting an India IP country. The cited documentation establishes an India IP rendering option, not India-region hosting or data residency.
Should I use the SDK or REST?
Use the SDK if its documented API fits your Java application and you want its client abstractions. Use REST if you prefer to control HTTP requests directly or want to avoid an additional SDK dependency.
Can a Java web app return the image without saving it first?
Yes. The capture response is image bytes; your server can stream those bytes from an endpoint with the matching image content type, subject to your access-control and retention decisions.
Can I make the screenshot show a particular Indian city?
Only if you configure the signal the page reads. IP country selects a country, while browser geolocation exposes coordinates to pages that request them. A city-specific test may also require a site-specific setting or an appropriate proxy; verify the destination’s behavior.


