ScreenshotNeo

BlogHow-to

How to Batch Generate Website Screenshots with APITemplate.io

Generate one template-based image per page or record with APITemplate.io, then track async jobs, retries, and results reliably.

By the ScreenshotNeo team4 October 20269 min read

Direct answer: APITemplate.io’s documented batch pattern is to create an image template, then submit one image-generation request for each page or record, passing that record’s values as named overrides. For larger batches, use its asynchronous mode, save each returned transaction_ref, and match webhook completions back to the input records. The documentation reviewed does not establish a single endpoint that accepts an arbitrary list of website URLs and returns all screenshots in one bulk request.

This approach is useful when you want consistent social preview images, Open Graph graphics, or other template-based images populated with data from many pages. If you need a pixel-for-pixel capture of each live webpage, use a browser screenshot workflow instead; a template-generated image is not automatically a screenshot of the page.

1. Create and prepare the template

  1. In the APITemplate.io image template editor, create the image layout you want to generate.
  2. Add dynamic elements for values that change per page or record. Name each element, and use those names consistently in your API overrides.
  3. Prepare a record for each output. For example, a record might contain a page title, a short description, a destination URL, and an image URL. Only include values corresponding to dynamic elements in your template.
  4. Keep a stable input identifier for every record. You will use it to deduplicate work and associate each completed image with its source.

The editor supports dynamic text, images, shapes, QR codes, and barcodes. Its documentation also lists Open Graph images among image use cases. See the first-image guide for the documented request and response pattern.

2. Generate one image per record

Send a POST request to the v2 create-image endpoint with your API key in the X-API-KEY header and the template ID and named overrides in JSON. The response includes a download_url.

Store the API key in an environment variable or secret manager. APITemplate.io’s API key guide says not to share it publicly or commit it to version control.

cURL

curl --request POST \
  --url "https://rest.apitemplate.io/v2/create-image" \
  --header "X-API-KEY: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "template_id": "YOUR_TEMPLATE_ID",
    "overrides": {
      "title": "A page title",
      "description": "A short description",
      "image": "https://example.com/preview.jpg"
    }
  }'

Replace the template ID and override names with the values configured in your template. Keep the JSON values appropriate to each element. Treat the response as JSON and read its download_url rather than assuming a fixed output URL.

Python

import os
import requests

api_key = os.environ["APITEMPLATE_API_KEY"]
endpoint = "https://rest.apitemplate.io/v2/create-image"

record = {
    "id": "page-123",
    "title": "A page title",
    "description": "A short description",
    "image": "https://example.com/preview.jpg",
}

response = requests.post(
    endpoint,
    headers={
        "X-API-KEY": api_key,
        "Content-Type": "application/json",
    },
    json={
        "template_id": "YOUR_TEMPLATE_ID",
        "overrides": {
            "title": record["title"],
            "description": record["description"],
            "image": record["image"],
        },
    },
    timeout=60,
)
response.raise_for_status()
result = response.json()
print(record["id"], result["download_url"])

Node.js

const apiKey = process.env.APITEMPLATE_API_KEY;
if (!apiKey) throw new Error("Set APITEMPLATE_API_KEY first");

const record = {
  id: "page-123",
  title: "A page title",
  description: "A short description",
  image: "https://example.com/preview.jpg",
};

const response = await fetch("https://rest.apitemplate.io/v2/create-image", {
  method: "POST",
  headers: {
    "X-API-KEY": apiKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    template_id: "YOUR_TEMPLATE_ID",
    overrides: {
      title: record.title,
      description: record.description,
      image: record.image,
    },
  }),
});

if (!response.ok) {
  throw new Error(`APITemplate.io returned HTTP ${response.status}: ${await response.text()}`);
}
const result = await response.json();
console.log(record.id, result.download_url);

3. Turn the single-record request into a batch

For a small job, iterate through the records and make one request per record. For production use, keep generation separate from input retrieval so you can resume after failures without repeating work.

for each record:
    if record already has a completed output:
        continue
    submit image-generation request with that record's overrides
    save download_url and status against the record ID

The APITemplate.io Airtable integration demonstrates selecting records, looping over them, and skipping records whose output field is already populated. The same pattern applies to a custom job: use an input ID and output state to prevent duplicate generation when a run is restarted. See the Airtable integration guide.

For a reliable batch, track at least:

  • input_id: stable ID of the page or record.
  • status: queued, submitted, complete, or failed.
  • transaction_ref: returned reference for asynchronous work.
  • download_url: output URL after completion.
  • attempt_count and last_error: retry history and diagnostic context.

This tracking schema is implementation guidance based on the documented record loop and async references; it is not a vendor-required format.

4. Use asynchronous mode for larger batches

The REST API reference documents asynchronous processing by adding async=true. The response includes a transaction_ref, and a webhook can notify your system when processing finishes. The documentation recommends async processing for large or batch jobs.

curl --request POST \
  --url "https://rest.apitemplate.io/v2/create-image?async=true" \
  --header "X-API-KEY: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "template_id": "YOUR_TEMPLATE_ID",
    "overrides": {
      "title": "A page title",
      "description": "A short description"
    }
  }'

When the request returns, save its transaction_ref next to the input ID. Configure a webhook using the API’s documented mechanism, then use the reference in the completion notification to find and update the corresponding record. Make webhook handling idempotent: a repeated notification should not create a second output or corrupt a completed record.

Consult the REST API reference for the current webhook configuration, endpoint parameters, regional endpoints, and endpoint-specific limits. Do not assume an async acknowledgment means the image is already ready to download.

5. Handle rate limits, retries, and duplicate work

The API reference lists an IP-based limit of 100 requests per 10 seconds. A batch runner should pace requests accordingly and treat rate-limit responses as retryable after a delay. The reference also lists 100 concurrent synchronous PDF-generation requests per user account; that limit is specifically about PDF generation and should not be treated as an image-specific concurrency limit.

  • Queue requests: avoid launching an unbounded number of workers. Pace the job within documented API limits.
  • Retry carefully: retry transient network errors and rate limiting with increasing delays. Record every attempt. Avoid immediately repeating permanent request errors such as invalid template data.
  • Deduplicate: check whether an input already has a submitted transaction or completed output before submitting again.
  • Make callbacks safe to repeat: use the transaction reference and current record status to handle duplicate webhook deliveries.
  • Keep outputs associated with inputs: store the input ID and request reference together; completion order may differ from submission order.

Payload and timeout limits vary by endpoint. Check the current API reference for the endpoint and region you will use rather than extrapolating a limit from another operation.

6. Choose an endpoint region

The v2 REST API base is https://rest.apitemplate.io/v2/. The reference lists regional endpoints, including Frankfurt, N. Virginia, and Sydney. Choose among the documented endpoints based on processing region, latency, and data residency needs, then verify the current endpoint details before deployment. Regional endpoints do not change the need to follow that endpoint’s own limits.

7. Common errors and fixes

Symptom Likely cause What to do
Authentication failure The API key is missing, invalid, or sent under the wrong header. Send the key in X-API-KEY; verify the environment variable and keep the key private.
Request rejected for template data The template ID is wrong, an override name does not match a named element, or the payload is malformed. Compare the template ID and exact element names with the editor, then validate the JSON and value types.
Rate limit response The batch is sending requests too quickly from an IP. Queue and pace requests within the documented limit; retry after a delay rather than immediately resubmitting.
Timeout or interrupted connection The request exceeded the client timeout or the connection failed. For large jobs, use async mode. For synchronous requests, set a suitable client timeout and retry only after checking whether the request may already have been accepted.
Async result cannot be matched to a record The transaction reference was not persisted or was not associated with the input ID. Save the returned reference immediately and use it to update the same record when the completion notification arrives.
Repeated output after restarting a job The runner resubmitted records without checking their status. Skip records that already have a submitted transaction or completed output, and make callback processing idempotent.
Download URL does not yield the expected image The response was treated as a fixed schema or the URL was not read from the generation response. Inspect the response JSON and use its returned download_url; handle request errors before parsing success data.

8. Performance, reliability, and cost considerations

Performance

Async mode is the documented choice for large or batch work. It lets your job submit and track work without holding each synchronous request open until completion. The reviewed sources do not publish a guaranteed render time, batch throughput, or image-specific concurrency limit, so estimate capacity from your own workload and current endpoint documentation.

Reliability

Persist progress as the job runs, use stable record IDs, and separate submission from completion handling. On restart, resume only records with no completed output and no active transaction. Log request failures and webhook processing outcomes so that a partial batch can be repaired without rerunning everything.

Cost and plan limits

The sources reviewed for this guide do not establish a price or plan-by-plan allowance for this workflow. Check APITemplate.io’s current plan details before estimating batch cost. Also account for any storage or retention requirements in your own system; the reviewed sources do not establish output retention for this workflow.

9. When to use an integration instead of custom code

APITemplate.io documents integrations including Airtable, Zapier, Make, and Bubble. A no-code integration can suit a straightforward trigger-and-generate flow. Use the REST API when you need to control queueing, custom retry behavior, deduplication, record state, or callback handling. Compare the integration’s available controls with the operational requirements of your batch before choosing.

Or skip the browser setup

If the job is to capture actual live webpages, ScreenshotNeo is the website screenshot API and MCP server for developers from ScreenshotNeo. One GET request returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for options and response details.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.

FAQ

Does APITemplate.io accept a list of arbitrary website URLs in one screenshot request?

The documentation reviewed here does not establish such a bulk URL endpoint. The documented pattern is to submit an image-generation request per input record, optionally using async processing for batch work.

Is an APITemplate.io template image the same as a webpage screenshot?

No. The documented workflow generates an image from a template and values supplied as overrides. Capturing a rendered live webpage requires a browser screenshot workflow.

Can I use Airtable for the batch input?

Yes. APITemplate.io documents an Airtable integration that loops through records and can skip records whose output field is already populated.

Where should I check current request limits?

Use the REST API reference for endpoint-specific limits, timeouts, payload constraints, async behavior, and regional endpoint details.