Java SDK

The official Java SDK for RenderScreenshot. For Java 21 examples with virtual threads and Spring Boot, see the Java screenshot API guide.

Installation

Maven

Add the JitPack repository:

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

Add the dependency:

<dependency>
    <groupId>com.github.Render-Screenshot</groupId>
    <artifactId>rs-java</artifactId>
    <version>v2.0.2</version>
</dependency>

Gradle

Add the JitPack repository:

repositories {
    maven { url 'https://jitpack.io' }
}

Add the dependency:

implementation 'com.github.Render-Screenshot:rs-java:v2.0.2'

Requirements

  • Java 11 or higher

Quick Start

import com.renderscreenshot.sdk.Client;
import com.renderscreenshot.sdk.TakeOptions;

import java.nio.file.Files;
import java.nio.file.Path;

Client client = new Client("rs_live_xxxxx");

// Take a screenshot
byte[] image = client.take(
    TakeOptions.url("https://example.com").preset("og_card")
);

Files.write(Path.of("screenshot.png"), image);

Client

Constructor

import com.renderscreenshot.sdk.Client;

Client client = new Client(apiKey);
Client client = new Client(apiKey, baseUrl);
Client client = new Client(apiKey, baseUrl, timeout);
Client client = new Client(apiKey, baseUrl, timeout, signingKey, publicKeyId);
Parameter Type Description
apiKey String Your live API key (rs_live_*)
baseUrl String API base URL (null = https://api.renderscreenshot.com)
timeout Duration Request timeout (null = 30 seconds)
signingKey String Secret key (rs_secret_*). Only generateUrl() uses it
publicKeyId String Public key ID (rs_pub_*). Only generateUrl() uses it

Methods

take(options)

Take a screenshot and return binary data. The SDK sends the options to POST /v1/screenshot as nested JSON (for example viewport.width, capture.mode, output.format).

byte[] image = client.take(
    TakeOptions.url("https://example.com").preset("og_card")
);

// Save to file
Files.write(Path.of("screenshot.png"), image);

Returns: byte[]

takeJson(options)

Take a screenshot and return JSON metadata. The SDK sends the same request with an Accept: application/json header.

ScreenshotResponse response = client.takeJson(
    TakeOptions.url("https://example.com").preset("og_card")
);

System.out.println(response.getId());               // "req_..."
System.out.println(response.getStatus());           // "completed"
System.out.println(response.getImage().getUrl());   // CDN URL (shortcut: response.getUrl())
System.out.println(response.getImage().getWidth()); // 1200
System.out.println(response.getImage().getHeight());// 630
System.out.println(response.getCache().isHit());    // true/false (shortcut: response.isCached())
System.out.println(response.getUsage().getRemaining()); // credits left

The response has id, status, image (url, width, height, size, format), metadata, cache (hit, key, url, expires_at) and usage (credits, remaining). getImage(), getCache() and getUsage() return null when the API leaves that section out.

Returns: ScreenshotResponse

generateUrl(options, expiresAt)

Generate a signed URL for public embedding. Signed URLs work only for the GET render endpoint (GET /v1/screenshot). They need your public key ID (rs_pub_*) and your secret signing key (rs_secret_*). Your live API key does not sign URLs. Keep the secret key on your server.

import java.time.Duration;
import java.time.Instant;

Client client = new Client(
    "rs_live_xxxxx",     // API key for take(), batch(), etc.
    null,                // default base URL
    null,                // default timeout
    "rs_secret_xxxxx",   // signing key
    "rs_pub_xxxxx"       // public key ID
);

String signedUrl = client.generateUrl(
    TakeOptions.url("https://example.com").preset("og_card"),
    Instant.now().plus(Duration.ofHours(24)) // 24 hours (maximum 30 days)
);

// Or pass the credentials for one call:
String otherUrl = client.generateUrl(
    TakeOptions.url("https://example.com").width(1200).height(630),
    Instant.now().plus(Duration.ofHours(1)),
    "rs_secret_xxxxx",
    "rs_pub_xxxxx"
);

// Use in HTML: <img src="${signedUrl}" />

The URL contains key_id, expires, the flat GET parameters and a signature. Only options that the GET endpoint reads are included (for example width, fullPage(), element(), blockAds(), blockCookieBanners(), darkMode(), cacheTtl() and the PDF options). POST-only options, such as waitForSelector() or blockTrackers(), are left out.

Returns: String

Throws: RenderScreenshotException with code invalid_request if the signing key or the public key ID is missing.

batch(urls, options) / batchAdvanced(requests)

Process multiple screenshots in a batch.

import java.util.Arrays;
import java.util.List;

// Simple batch
List<String> urls = Arrays.asList(
    "https://example1.com",
    "https://example2.com"
);

BatchResponse results = client.batch(urls,
    TakeOptions.url("").preset("og_card")
);

// Advanced batch with per-URL options
List<Client.BatchRequest> requests = Arrays.asList(
    new Client.BatchRequest("https://example1.com",
        TakeOptions.url("https://example1.com").preset("og_card")),
    new Client.BatchRequest("https://example2.com",
        TakeOptions.url("https://example2.com").width(1920))
);

BatchResponse results = client.batchAdvanced(requests);

Returns: BatchResponse

getBatch(batchId)

Get the status of a batch job.

BatchResponse status = client.getBatch("batch_abc123");
System.out.println(status.getCompleted() + "/" + status.getTotal());

Returns: BatchResponse

presets() / preset(id)

Get available presets.

List<Preset> presets = client.presets();
Preset ogCard = client.preset("og_card");

devices()

Get available device presets.

List<Device> devices = client.devices();

TakeOptions

Fluent builder for screenshot options.

Creating Options

import com.renderscreenshot.sdk.TakeOptions;

// From URL
TakeOptions options = TakeOptions.url("https://example.com");

// From HTML
TakeOptions options = TakeOptions.html("<h1>Hello World</h1>");

Viewport Options

TakeOptions.url("...")
    .width(1200)           // Viewport width
    .height(630)           // Viewport height
    .scale(2.0)            // Device scale factor (1-3)
    .mobile();             // Enable mobile emulation

Capture Options

TakeOptions.url("...")
    .fullPage()            // Capture full scrollable page
    .element(".hero")      // Capture specific element
    .format("png")         // png, jpeg, webp, pdf
    .quality(90);          // JPEG/WebP quality (1-100)

Wait Options

TakeOptions.url("...")
    .waitFor("networkidle")      // load, networkidle, domcontentloaded
    .delay(2000)                 // Additional delay (ms)
    .waitForSelector(".loaded")  // Wait for selector
    .waitForTimeout(30);         // Max wait time (s, 1-60)

Presets & Devices

TakeOptions.url("...")
    .preset("og_card")           // Use a preset
    .device("iphone_14_pro");    // Emulate a device

Content Blocking

TakeOptions.url("...")
    .blockAds()                  // Block ad networks
    .blockTrackers()             // Block analytics
    .blockCookieBanners()        // Auto-dismiss cookie popups
    .blockChatWidgets()          // Block chat widgets
    .blockUrls(Arrays.asList("*.ads.com/*"))   // Block URL patterns
    .blockResources(Arrays.asList("font"));    // Block resource types

Browser Emulation

TakeOptions.url("...")
    .darkMode()                  // Enable dark mode
    .reducedMotion()             // Prefer reduced motion
    .mediaType("print")          // screen or print
    .userAgent("Custom UA")      // Custom user agent
    .timezone("America/New_York")
    .locale("en-US")
    .geolocation(40.7128, -74.006);

Network Options

import java.util.Map;
import java.util.HashMap;

Map<String, String> headers = new HashMap<>();
headers.put("X-Custom", "value");

TakeOptions.url("...")
    .headers(headers)
    .authBasic("user", "pass")
    .authBearer("token")
    .bypassCsp();

Cache Options

TakeOptions.url("...")
    .cacheTtl(86400)             // Cache TTL in seconds
    .cacheAvailable()            // Reuse an identical render inside the TTL (0 credits)
    .cacheRefresh();             // Force refresh

PDF Options

TakeOptions.url("...")
    .format("pdf")
    .pdfPaperSize("a4")          // a4, letter, legal, etc.
    .pdfLandscape()
    .pdfMargin("1in")
    .pdfPrintBackground()
    .pdfHeader("<div>Header</div>")
    .pdfFooter("<div>Page <span class=\"pageNumber\"></span></div>");

Storage Options (BYOS)

TakeOptions.url("...")
    .storageEnabled()
    .storagePath("{year}/{month}/{hash}.{ext}")
    .storageAcl("public-read");

Cache Management

// Get cached screenshot
byte[] image = client.cache.get("cache_xyz789");

// Delete single entry
client.cache.delete("cache_xyz789");

// Bulk purge by keys
CacheManager.PurgeResponse result = client.cache.purge(
    Arrays.asList("cache_abc", "cache_def")
);
System.out.println("Purged: " + result.getPurged());

// Purge by URL pattern
client.cache.purgeUrl("https://mysite.com/blog/*");

// Purge by storage path pattern
client.cache.purgePattern("screenshots/2024/*");

// Purge by date
client.cache.purgeBefore(Instant.parse("2024-01-01T00:00:00Z"));

Webhook Helpers

import com.renderscreenshot.sdk.Webhook;
import com.renderscreenshot.sdk.Webhook.WebhookEvent;

// Verify signature
boolean isValid = Webhook.verify(payload, signature, timestamp, secret);

// Parse event
WebhookEvent event = Webhook.parse(payload);
if ("screenshot.completed".equals(event.getEvent())) {
    System.out.println("Screenshot completed: " + event.getData());
}

// Extract headers (case-insensitive)
String[] headers = Webhook.extractHeaders(requestHeaders);
String signature = headers[0];
String timestamp = headers[1];

Error Handling

import com.renderscreenshot.sdk.RenderScreenshotException;

try {
    byte[] image = client.take(TakeOptions.url("..."));
} catch (RenderScreenshotException e) {
    System.out.println(e.getHttpStatus());  // 400, 429, etc.
    System.out.println(e.getCode());        // "invalid_url", "rate_limited"
    System.out.println(e.getMessage());     // Human-readable message
    System.out.println(e.isRetryable());    // true/false

    if (e.isRetryable() && e.getRetryAfter() != null) {
        Thread.sleep(e.getRetryAfter() * 1000L);
        // Retry the request...
    }
}

Error Codes

Code HTTP Retryable Description
invalid_request 400 No Malformed request
invalid_url 400 No Invalid URL provided
unauthorized 401 No Invalid API key
forbidden 403 No Access denied
not_found 404 No Resource not found
rate_limited 429 Yes Rate limit exceeded
timeout 408 Yes Screenshot timed out
render_failed 500 Yes Browser rendering failed
internal_error 500 Yes Internal server error

Was this page helpful?