Need to capture website screenshots from a Java application? Whether you're building a Spring Boot microservice, a scheduled report generator, or an automated QA tool, this tutorial shows you how to go from URL to PNG image — no Selenium, no ChromeDriver, no browser process to manage.
We'll use the URLSnap REST API: send an HTTP request, receive an image back. Works out of the box with Java 11+'s built-in HttpClient and with popular libraries like OkHttp or Apache HttpClient.
Java 11 or higher (for the built-in java.net.http.HttpClient). No external dependencies needed for the basic examples. OkHttp and Spring WebClient examples require their respective dependencies.
curl -X POST https://urlsnap.dev/api/register \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com"}'
# {"key":"us_abc123...","message":"Free tier: 20 requests/day"}
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 ScreenshotExample {
private static final String API_KEY = "us_your_key_here"; // get free at urlsnap.dev
private static final String BASE_URL = "https://urlsnap.dev/api/screenshot";
public static void main(String[] args) throws Exception {
String targetUrl = "https://example.com";
String encoded = URLEncoder.encode(targetUrl, StandardCharsets.UTF_8);
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "?url=" + encoded + "&format=png&full_page=true&width=1280"))
.header("x-api-key", API_KEY)
.timeout(Duration.ofSeconds(60))
.GET()
.build();
HttpResponse<byte[]> response = client.send(
request, HttpResponse.BodyHandlers.ofByteArray()
);
if (response.statusCode() != 200) {
throw new RuntimeException("API error " + response.statusCode() +
": " + new String(response.body()));
}
Path output = Path.of("screenshot.png");
Files.write(output, response.body());
System.out.println("Screenshot saved to " + output.toAbsolutePath());
}
}
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | string | required | Target URL to screenshot |
| width | integer | 1280 | Viewport width in pixels |
| height | integer | 800 | Viewport height in pixels |
| format | string | png | png or jpeg |
| full_page | bool | false | Capture full scrollable page |
| delay | integer | 0 | Wait ms after page load, max 5000 |
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;
import java.util.StringJoiner;
public class UrlSnapClient {
private final String apiKey;
private final HttpClient http;
public UrlSnapClient(String apiKey) {
this.apiKey = apiKey;
this.http = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
}
public record ScreenshotOptions(
int width,
int height,
String format, // "png" or "jpeg"
boolean fullPage,
int delayMs
) {
public static ScreenshotOptions defaults() {
return new ScreenshotOptions(1280, 800, "png", false, 0);
}
}
public byte[] screenshot(String targetUrl, ScreenshotOptions opts) throws Exception {
StringJoiner params = new StringJoiner("&");
params.add("url=" + URLEncoder.encode(targetUrl, StandardCharsets.UTF_8));
if (opts.width() > 0) params.add("width=" + opts.width());
if (opts.height() > 0) params.add("height=" + opts.height());
if (opts.format() != null) params.add("format=" + opts.format());
if (opts.fullPage()) params.add("full_page=true");
if (opts.delayMs() > 0) params.add("delay=" + opts.delayMs());
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://urlsnap.dev/api/screenshot?" + params))
.header("x-api-key", apiKey)
.timeout(Duration.ofSeconds(60))
.GET()
.build();
HttpResponse<byte[]> response = http.send(
request, HttpResponse.BodyHandlers.ofByteArray()
);
if (response.statusCode() == 429) {
throw new RuntimeException("Daily limit reached — upgrade at urlsnap.dev/#pricing");
}
if (response.statusCode() != 200) {
throw new RuntimeException("API error " + response.statusCode() +
": " + new String(response.body()));
}
return response.body();
}
public byte[] pdf(String targetUrl, String pageFormat) throws Exception {
String params = "url=" + URLEncoder.encode(targetUrl, StandardCharsets.UTF_8)
+ "&format=" + pageFormat;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://urlsnap.dev/api/pdf?" + params))
.header("x-api-key", apiKey)
.timeout(Duration.ofSeconds(60))
.GET()
.build();
HttpResponse<byte[]> response = http.send(
request, HttpResponse.BodyHandlers.ofByteArray()
);
if (response.statusCode() != 200) {
throw new RuntimeException("PDF error " + response.statusCode() +
": " + new String(response.body()));
}
return response.body();
}
// Usage example:
public static void main(String[] args) throws Exception {
UrlSnapClient client = new UrlSnapClient("us_your_key_here");
ScreenshotOptions opts = new ScreenshotOptions(1280, 800, "png", true, 0);
byte[] png = client.screenshot("https://example.com", opts);
Files.write(Path.of("example.png"), png);
System.out.println("Saved example.png (" + png.length + " bytes)");
byte[] pdfBytes = client.pdf("https://example.com", "A4");
Files.write(Path.of("example.pdf"), pdfBytes);
System.out.println("Saved example.pdf (" + pdfBytes.length + " bytes)");
}
}
// UrlSnapService.java — inject into any @Service or @Controller
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Service
public class UrlSnapService {
private final WebClient webClient;
public UrlSnapService(@Value("${urlsnap.api-key}") String apiKey) {
this.webClient = WebClient.builder()
.baseUrl("https://urlsnap.dev")
.defaultHeader("x-api-key", apiKey)
.build();
}
public Mono<byte[]> screenshot(String url, boolean fullPage) {
return webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/api/screenshot")
.queryParam("url", url)
.queryParam("format", "png")
.queryParam("full_page", fullPage)
.queryParam("width", 1280)
.build())
.retrieve()
.bodyToMono(byte[].class);
}
public Mono<byte[]> pdf(String url, String pageFormat) {
return webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/api/pdf")
.queryParam("url", url)
.queryParam("format", pageFormat)
.build())
.retrieve()
.bodyToMono(byte[].class);
}
}
// application.properties:
// urlsnap.api-key=us_your_key_here
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class OkHttpExample {
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
public static byte[] screenshot(String apiKey, String url) throws IOException {
Request request = new Request.Builder()
.url("https://urlsnap.dev/api/screenshot?url=" +
java.net.URLEncoder.encode(url, "UTF-8") +
"&format=png&full_page=true")
.addHeader("x-api-key", apiKey)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("API error: " + response.code());
}
return response.body().bytes();
}
}
}
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.*;
public class QuotaCheck {
public static void main(String[] args) throws Exception {
String apiKey = "us_your_key_here";
HttpClient http = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://urlsnap.dev/api/me"))
.header("x-api-key", apiKey)
.GET()
.build();
HttpResponse<String> response = http.send(
request, HttpResponse.BodyHandlers.ofString()
);
ObjectMapper mapper = new ObjectMapper();
JsonNode json = mapper.readTree(response.body());
System.out.printf("Plan: %s%n", json.get("plan").asText());
System.out.printf("Used today: %d/%d%n",
json.get("requests_today").asInt(),
json.get("daily_limit").asInt());
System.out.printf("All-time total: %d%n", json.get("requests_total").asInt());
}
}
Free tier: 20 screenshots/day. No Selenium, no ChromeDriver, no browser to manage.
Get your free API key →