Batch Screenshots

The batch endpoint lets you capture multiple screenshots in a single request, with support for both synchronous and asynchronous processing.

Endpoint

POST https://api.renderscreenshot.com/v1/batch

Authentication

Include your API key in the Authorization header:

Authorization: Bearer rs_live_xxxxx

Simple Batch Request

Apply the same options to all URLs:

{
  "urls": [
    "https://example1.com",
    "https://example2.com",
    "https://example3.com"
  ],
  "options": {
    "preset": "og_card",
    "block": { "ads": true }
  },
  "concurrency": 3
}
Parameter Type Required Description
urls array Yes* List of URLs to screenshot (*or use requests)
options object No Options applied to all URLs
concurrency integer No Parallel screenshots (default: 3, max varies by plan)

Advanced Batch Request

Specify different options per URL:

{
  "requests": [
    { "url": "https://example1.com", "preset": "og_card" },
    { "url": "https://example2.com", "preset": "full_page" },
    { "url": "https://example3.com", "viewport": { "width": 1920 } }
  ],
  "webhook": {
    "url": "https://your-server.com/webhook"
  }
}
Parameter Type Required Description
requests array Yes* Array of request objects with individual options
webhook object No Webhook configuration for async processing

Sync vs Async Processing

Synchronous (≤10 URLs without webhook): - Request blocks until all screenshots complete - Returns full results in response

Asynchronous (>10 URLs or webhook specified): - Returns immediately with job ID - Poll GET /v1/batch/:id for status - Or receive webhook on completion

Synchronous Response

{
  "id": "batch_abc123",
  "status": "completed",
  "results": [
    {
      "url": "https://example1.com",
      "status": "completed",
      "image": {
        "url": "https://cdn.renderscreenshot.com/abc.png",
        "width": 1200,
        "height": 630
      }
    },
    {
      "url": "https://example2.com",
      "status": "completed",
      "image": {
        "url": "https://cdn.renderscreenshot.com/def.png",
        "width": 1280,
        "height": 4500
      }
    },
    {
      "url": "https://example3.com",
      "status": "failed",
      "error": {
        "type": "target_error",
        "code": "timeout",
        "message": "Page failed to load within 30 seconds",
        "retryable": true
      }
    }
  ],
  "summary": {
    "total": 3,
    "completed": 2,
    "failed": 1
  },
  "usage": {
    "credits": 2,
    "remaining": 9997
  }
}

Asynchronous Response

Initial response:

{
  "id": "batch_abc123",
  "status": "processing",
  "total": 50,
  "progress": 0
}

Poll for status:

GET /v1/batch/batch_abc123

Webhook Integration

When a webhook is configured, you'll receive a POST request on completion:

{
  "event": "batch.completed",
  "batch_id": "batch_abc123",
  "status": "completed",
  "summary": {
    "total": 50,
    "completed": 48,
    "failed": 2
  },
  "results_url": "https://api.renderscreenshot.com/v1/batch/batch_abc123/results"
}

See Webhooks for configuration details.

Examples

Simple Batch

curl

curl -X POST https://api.renderscreenshot.com/v1/batch \
  -H "Authorization: Bearer rs_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": [
      "https://github.com",
      "https://stripe.com",
      "https://linear.app"
    ],
    "options": {
      "preset": "og_card"
    }
  }'

Java

import com.renderscreenshot.sdk.Client;
import com.renderscreenshot.sdk.TakeOptions;
import com.renderscreenshot.sdk.model.BatchResponse;
import com.renderscreenshot.sdk.model.BatchResult;
import java.util.Arrays;

Client client = new Client("rs_live_xxxxx");

BatchResponse results = client.batch(
    Arrays.asList("https://github.com", "https://stripe.com", "https://linear.app"),
    TakeOptions.url("").preset("og_card")
);

System.out.println("Completed: " + results.getCompleted() + "/" + results.getTotal());
for (BatchResult item : results.getResults()) {
    String url = item.isSuccess() ? item.getResponse().getUrl() : "failed";
    System.out.println(item.getUrl() + ": " + url);
}

Node.js

import { Client, TakeOptions } from 'renderscreenshot';

const client = new Client('rs_live_xxxxx');

const results = await client.batch(
  ['https://github.com', 'https://stripe.com', 'https://linear.app'],
  TakeOptions.url('').preset('og_card')
);

console.log(`Completed: ${results.completed}/${results.total}`);
for (const item of results.results) {
  console.log(`${item.url}: ${item.success ? item.response?.url : 'failed'}`);
}

PHP

use RenderScreenshot\Client;
use RenderScreenshot\TakeOptions;

$client = new Client('rs_live_xxxxx');

$results = $client->batch(
    ['https://github.com', 'https://stripe.com', 'https://linear.app'],
    TakeOptions::url('')->preset('og_card')
);

echo "Completed: {$results['completed']}/{$results['total']}\n";
foreach ($results['results'] as $item) {
    $url = $item['success'] ? ($item['response']['url'] ?? 'failed') : 'failed';
    echo "{$item['url']}: {$url}\n";
}

Python

from renderscreenshot import Client, TakeOptions

client = Client('rs_live_xxxxx')

results = client.batch(
    ['https://github.com', 'https://stripe.com', 'https://linear.app'],
    TakeOptions.url('').preset('og_card')
)

print(f"Completed: {results['completed']}/{results['total']}")
for item in results['results']:
    url = item.get('response', {}).get('url', 'failed') if item.get('success') else 'failed'
    print(f"{item['url']}: {url}")

Ruby

require 'net/http'
require 'json'

uri = URI('https://api.renderscreenshot.com/v1/batch')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Authorization'] = 'Bearer rs_live_xxxxx'
request['Content-Type'] = 'application/json'
request.body = {
  urls: ['https://github.com', 'https://stripe.com', 'https://linear.app'],
  options: { preset: 'og_card' }
}.to_json

response = http.request(request)
results = JSON.parse(response.body)

puts "Completed: #{results['summary']['completed']}/#{results['summary']['total']}"
results['results'].each do |item|
  url = item['status'] == 'completed' ? item['image']['url'] : 'failed'
  puts "#{item['url']}: #{url}"
end

Advanced Batch with Per-URL Options

Java

import com.renderscreenshot.sdk.Client;
import com.renderscreenshot.sdk.TakeOptions;
import java.util.Arrays;

Client client = new Client("rs_live_xxxxx");

BatchResponse results = client.batchAdvanced(Arrays.asList(
    new Client.BatchRequest("https://github.com",
        TakeOptions.url("https://github.com").preset("og_card")),
    new Client.BatchRequest("https://stripe.com",
        TakeOptions.url("https://stripe.com").fullPage()),
    new Client.BatchRequest("https://linear.app",
        TakeOptions.url("https://linear.app").width(1920).darkMode())
));

Node.js

import { Client } from 'renderscreenshot';

const client = new Client('rs_live_xxxxx');

const results = await client.batch([
  { url: 'https://github.com', options: { preset: 'og_card' } },
  { url: 'https://stripe.com', options: { preset: 'full_page' } },
  { url: 'https://linear.app', options: { width: 1920, darkMode: true } },
]);

PHP

use RenderScreenshot\Client;

$client = new Client('rs_live_xxxxx');

$results = $client->batchAdvanced([
    ['url' => 'https://github.com', 'options' => ['preset' => 'og_card']],
    ['url' => 'https://stripe.com', 'options' => ['preset' => 'full_page']],
    ['url' => 'https://linear.app', 'options' => ['width' => 1920, 'dark_mode' => true]],
]);

Python

from renderscreenshot import Client

client = Client('rs_live_xxxxx')

results = client.batch([
    {'url': 'https://github.com', 'options': {'preset': 'og_card'}},
    {'url': 'https://stripe.com', 'options': {'preset': 'full_page'}},
    {'url': 'https://linear.app', 'options': {'width': 1920, 'dark_mode': True}},
])

Ruby

require 'net/http'
require 'json'

uri = URI('https://api.renderscreenshot.com/v1/batch')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Authorization'] = 'Bearer rs_live_xxxxx'
request['Content-Type'] = 'application/json'
request.body = {
  requests: [
    { url: 'https://github.com', preset: 'og_card' },
    { url: 'https://stripe.com', preset: 'full_page' },
    { url: 'https://linear.app', viewport: { width: 1920 } }
  ]
}.to_json

response = http.request(request)
results = JSON.parse(response.body)

Polling Batch Status

Java

import com.renderscreenshot.sdk.Client;
import com.renderscreenshot.sdk.model.BatchResponse;
import java.util.Arrays;

Client client = new Client("rs_live_xxxxx");

// Start a batch
BatchResponse batch = client.batch(
    Arrays.asList("https://example1.com", "https://example2.com"),
    TakeOptions.url("").preset("og_card")
);

// Poll for completion
BatchResponse status = client.getBatch(batch.getId());
while ("processing".equals(status.getStatus())) {
    Thread.sleep(1000);
    status = client.getBatch(batch.getId());
    System.out.println("Progress: " + status.getCompleted() + "/" + status.getTotal());
}

Node.js

import { Client } from 'renderscreenshot';

const client = new Client('rs_live_xxxxx');

// Start a batch
const batch = await client.batch(['https://example1.com', 'https://example2.com']);

// Poll for completion
let status = await client.getBatch(batch.id);
while (status.status === 'processing') {
  await new Promise(resolve => setTimeout(resolve, 1000));
  status = await client.getBatch(batch.id);
  console.log(`Progress: ${status.completed}/${status.total}`);
}

PHP

use RenderScreenshot\Client;

$client = new Client('rs_live_xxxxx');

// Start a batch
$batch = $client->batch(['https://example1.com', 'https://example2.com']);

// Poll for completion
$status = $client->getBatch($batch['id']);
while ($status['status'] === 'processing') {
    sleep(1);
    $status = $client->getBatch($batch['id']);
    echo "Progress: {$status['completed']}/{$status['total']}\n";
}

Python

import time
from renderscreenshot import Client

client = Client('rs_live_xxxxx')

# Start a batch
batch = client.batch(['https://example1.com', 'https://example2.com'])

# Poll for completion
status = client.get_batch(batch['id'])
while status['status'] == 'processing':
    time.sleep(1)
    status = client.get_batch(batch['id'])
    print(f"Progress: {status['completed']}/{status['total']}")

Ruby

require 'net/http'
require 'json'

base_uri = 'https://api.renderscreenshot.com/v1'

# Start a batch
uri = URI("#{base_uri}/batch")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Authorization'] = 'Bearer rs_live_xxxxx'
request['Content-Type'] = 'application/json'
request.body = { urls: ['https://example1.com', 'https://example2.com'] }.to_json

response = http.request(request)
batch = JSON.parse(response.body)

# Poll for completion
loop do
  status_uri = URI("#{base_uri}/batch/#{batch['id']}")
  status_request = Net::HTTP::Get.new(status_uri)
  status_request['Authorization'] = 'Bearer rs_live_xxxxx'

  status_response = http.request(status_request)
  status = JSON.parse(status_response.body)

  puts "Progress: #{status['summary']['completed']}/#{status['summary']['total']}"
  break unless status['status'] == 'processing'

  sleep(1)
end

Rate Limits

Batch size limits vary by plan:

Plan Max batch size
Free 5
Starter 20
Growth 50
Scale 100

See Rate Limits for more details.

See Also

Was this page helpful?