How to Take Website Screenshots with Java

Published April 3, 2026 · 6 min read · URLSnap Team

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.

Prerequisites

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.

Step 1: Get a Free API Key

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"}

Step 2: Take Your First Screenshot (Java 11+ HttpClient)

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());
    }
}
💡 full_page=true captures the entire scrollable page height, not just the visible viewport. Great for long landing pages and reports.

All API Parameters

ParameterTypeDefaultDescription
urlstringrequiredTarget URL to screenshot
widthinteger1280Viewport width in pixels
heightinteger800Viewport height in pixels
formatstringpngpng or jpeg
full_pageboolfalseCapture full scrollable page
delayinteger0Wait ms after page load, max 5000

Reusable UrlSnapClient Class

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)");
    }
}
⚡ The record syntax for ScreenshotOptions requires Java 16+. For older Java versions, use a plain POJO class with a constructor and getters.

Spring Boot Integration

// 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

With OkHttp (Android / Retrofit-compatible)

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();
        }
    }
}

Check Your Daily Quota

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());
    }
}

Ready to screenshot the web with Java?

Free tier: 20 screenshots/day. No Selenium, no ChromeDriver, no browser to manage.

Get your free API key →