Bulk URL Screenshots with HTMLCSStoImage: API Workflow and Limits
Create URL screenshots in batches with HTMLCSStoImage. See the request structure, plan limits, rate limits, retries, and runnable client examples.
Direct answer: HTMLCSStoImage (HCTI) creates multiple URL screenshots in one request with POST https://hcti.io/v1/image/batch. Put shared settings, including the page URL, in default_options and per-image differences in variations. Authenticate with HTTP Basic using your API ID as the username and API key as the password. The published batch capacity is up to 25 or 100 images depending on plan; check your account’s actual limit before building a batch around either number.
Image creation has no documented per-second or per-minute request limit, but it still consumes image credits and is subject to plan limits. Management API calls have separate throttles. A 429 can mean throttling or exhausted image credits, and the right fix depends on which one occurred.
1. Understand the batch request
The batch endpoint accepts a shared default_options object and a variations array. Each variation produces an image using the shared defaults, with any supplied values overriding those defaults. This is useful for generating a set of viewport or color-scheme variants for one page in a single API request.
default_options: shared rendering inputs, such asurl, viewport, and other supported options.variations: one object per screenshot, containing only the settings that differ.- The response contains image IDs and URLs corresponding to the requested variations.
Use a fully qualified, publicly reachable webpage URL. For a single-image request, url overrides html; supply one or the other, not both. CSS can be supplied to inject styles into a URL render. For batch requests, verify the exact supported fields and constraints in the current API documentation before relying on less common settings.
2. Authenticate and prepare credentials
Use HTTP Basic authentication: API ID as the username and API key as the password. The create endpoint requires the images:create permission. Treat the API key like a password, grant only the needed permissions, and keep it on a server or in a secret manager. Do not put it in browser-side JavaScript or a public repository.
3. Submit a URL screenshot batch
This cURL example shares one URL and viewport, then requests two variations. Replace the credentials and adjust variation fields to match the current parameter reference and your account’s batch allowance.
curl --user "$HCTI_API_ID:$HCTI_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"default_options": {
"url": "https://example.com",
"viewport_width": 1280,
"viewport_height": 800
},
"variations": [
{"color_scheme": "light"},
{"color_scheme": "dark", "full_screen": true}
]
}' \
"https://hcti.io/v1/image/batch"
Set HCTI_API_ID and HCTI_API_KEY in your shell environment first. The request body shape and option names should be checked against HCTI’s current API workflow and parameter documentation; supported options and exact accepted values can change.
For a single screenshot rather than a batch, use POST https://hcti.io/v1/image with the same Basic authentication. Accepted inputs can be sent as JSON or form data. A successful response includes an image url and id.
4. Runnable Python and Node.js examples
These examples use the batch endpoint and environment variables for credentials. They print the response so you can inspect returned IDs and URLs. Install Python’s dependency with python -m pip install requests; Node.js 18 or later includes fetch.
Python
import json
import os
import requests
api_id = os.environ["HCTI_API_ID"]
api_key = os.environ["HCTI_API_KEY"]
payload = {
"default_options": {
"url": "https://example.com",
"viewport_width": 1280,
"viewport_height": 800,
},
"variations": [
{"color_scheme": "light"},
{"color_scheme": "dark", "full_screen": True},
],
}
response = requests.post(
"https://hcti.io/v1/image/batch",
auth=(api_id, api_key),
json=payload,
timeout=90,
)
response.raise_for_status()
print(json.dumps(response.json(), indent=2))
Node.js
const apiId = process.env.HCTI_API_ID;
const apiKey = process.env.HCTI_API_KEY;
if (!apiId || !apiKey) throw new Error('Set HCTI_API_ID and HCTI_API_KEY');
const payload = {
default_options: {
url: 'https://example.com',
viewport_width: 1280,
viewport_height: 800,
},
variations: [
{ color_scheme: 'light' },
{ color_scheme: 'dark', full_screen: true },
],
};
const credentials = Buffer.from(`${apiId}:${apiKey}`).toString('base64');
const response = await fetch('https://hcti.io/v1/image/batch', {
method: 'POST',
headers: {
Authorization: `Basic ${credentials}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
signal: AbortSignal.timeout(90000),
});
if (!response.ok) {
throw new Error(`HCTI request failed: ${response.status} ${await response.text()}`);
}
console.log(await response.json());
5. Choose batch size and options
| Decision | What to check |
|---|---|
| Batch capacity | The pricing page lists capacities up to 25 or 100 images per batch depending on plan. Confirm your account’s entitlement; do not assume the top limit. |
| Credits | Each render consumes image credits unless the documented deduplication behavior applies to that request and is available on your plan. |
| Viewport | When setting viewport width or height, the parameter reference says both dimensions must be set. |
| Dynamic content | The parameter reference documents max_wait_ms from 500 to 10,000 ms and a render_when_ready option. Consult current documentation for precise behavior. |
| CSS | Optional CSS is injected into a URL render. Check CSS and URL support details in the current parameter reference. |
| Deduplication | Identical requests may reuse an existing result according to the plan’s deduplication settings. Batch requests do not support dedupe_duration_s. |
For saved templates, HCTI documents a separate POST https://hcti.io/v1/image/batch/templated endpoint. Each variation must resolve to a template owned by the organization, and supplied values must satisfy the template’s required variables. Templated results preserve input order; plan, usage, authentication, and rate limits still apply.
6. Rate limits, billing limits, and safe retries
HCTI documents no per-second or per-minute rate cap for creating or rendering images. That does not mean unlimited free rendering: image credits and other plan restrictions still apply. Management operations use separate organization-level sliding 60-second windows for covered resource families: 100 reads and 20 writes per minute. REST and MCP calls share those allowances.
When a request returns 429 Too Many Requests, inspect the response and determine whether it was a management throttle or an image-credit limit. For a management throttle, follow Retry-After if present; otherwise wait 60 seconds and space retries. Waiting does not replenish exhausted image credits. Check the billing period, dashboard, and overage settings, or choose a plan with more allowance.
Avoid blindly resubmitting an entire batch after an ambiguous timeout. First determine whether the request was accepted and whether results are available; use returned IDs and URLs to track completed work. The dossier does not establish a universal idempotency guarantee for batch submissions, so do not assume that repeating a request cannot create additional billable renders.
7. Performance, reliability, and cost planning
- Batching: A batch reduces the number of API calls your application needs to orchestrate, but does not remove the per-image credit and plan constraints.
- Size conservatively: Keep batches within the confirmed plan cap. For large URL lists, split them into bounded groups and record progress per submitted batch.
- Dynamic pages: Pages that load data or images late may need readiness configuration or a longer supported wait. A capture taken too early can be incomplete; increasing wait can also increase total workflow time.
- Deduplication: Identical requests may reuse an existing result under account settings. Do not build cost estimates around deduplication unless the account supports it and the request matches the documented rules.
- Plan comparison: Check batch maximum, included image credits, deduplication window, overage behavior, and needed features such as storage destinations or proxies. Published pricing and entitlements can change.
The available research contains no hands-on throughput or rendering-fidelity measurements, so no performance benchmark is claimed here.
8. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
401 |
Missing or invalid API ID or API key. | Check both environment variables and Basic authentication formatting. Rotate any key that was exposed. |
403 |
The key lacks required permissions. | Grant the key the required images:create permission, following least privilege. |
429 on management call |
Read/write management allowance exceeded. | Honor Retry-After; if absent, wait 60 seconds and retry with spacing. |
429 on image creation |
Image credits or another plan limit exhausted. | Check usage, billing period, and overage settings. Waiting alone does not restore credits. |
| Batch rejected for size | Variation count exceeds the account’s plan limit. | Confirm the account entitlement and split the work into smaller batches. |
| Invalid request or missing input | Malformed JSON, unsupported option, or missing URL/HTML input. | Validate JSON and field names against the current API documentation. For URL captures, use a fully qualified public URL. |
| Unexpected viewport | Only one viewport dimension was supplied or an option value is invalid. | Provide both width and height and check the parameter reference for accepted values. |
| Incomplete dynamic page | The page was captured before client-side content was ready. | Use the documented readiness option or an appropriate max_wait_ms, within its supported range. |
| Duplicate work after retry | The first request may have succeeded despite a client timeout. | Inspect any available response/result identifiers before resubmitting; do not assume batch idempotency. |
9. Or skip the browser setup
If your goal is simply to get clean website screenshots without managing a rendering API workflow, ScreenshotNeo is a website screenshot API and MCP server for developers. Its one-call endpoint accepts a URL and returns PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for the available parameters.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie banners, popups, and chat widgets are removed before the screenshot; each cleanup step can be turned off.
- Bot checks, blank pages, failed loads, timeouts, and cache hits are never billed. Response headers identify the page verdict and billing status.
- An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs.
- 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo and get 1,000 free screenshots a month with no card.
10. FAQ
Can one batch contain screenshots of different URLs?
The documented pattern shares defaults and varies settings per image. Confirm the current batch schema for whether each variation can override the URL before relying on mixed-URL batches; the common documented use case is multiple variations of a shared page.
Does the absence of a render rate cap mean I can send unlimited batches?
No. Image credits and plan limits still apply, and management API calls have their own throttles.
Does waiting after every 429 fix the problem?
Only a management throttle is cleared by waiting. An image-credit limit requires an allowance or billing change.
Are HCTI’s batch limits permanent?
No. The 25 and 100 image capacities are published plan details that may change. Verify current pricing and your account dashboard before rollout.


