ScreenshotMachine CLI vs API: Which Should You Use for Bulk Website Captures?
ScreenshotMachine documents an HTTP screenshot API, not a separate CLI or batch endpoint. Here is how to choose an API workflow and run bulk captures safely.
Short answer: ScreenshotMachine documents an HTTP GET screenshot API and provides a Bash example that calls it with curl. The official material reviewed does not establish a separate ScreenshotMachine CLI product or a batch endpoint. For bulk captures, use the API as the capture interface and write a shell script or application that reads URLs, names files, handles errors, and limits concurrency. Confirm throughput limits with ScreenshotMachine before a high-volume run.
That distinction matters: a shell script can feel like a CLI to your team, but it is your local orchestration around the documented API, not evidence of a vendor-supported command-line client. The documented request takes one URL at a time. See the ScreenshotMachine API documentation and check its current pricing page before planning a large run.
CLI vs API: which approach fits your bulk job?
| Approach | Good fit | What you manage |
|---|---|---|
| Direct API request | A one-off capture, an existing application, or a job system that already handles files and retries. | Build the request, inspect the response, store the image, and handle failures. |
| Shell script calling the API | A URL list, a local folder of results, CI, or a simple scheduled run. | Input parsing, safe file names, retries, concurrency, logs, and resume behavior. |
| A vendor CLI | Use this only if ScreenshotMachine confirms a supported CLI that meets your needs. | Verify its installation, supported options, maintenance, and bulk semantics with the vendor. |
For most bulk jobs, the shell-script approach is a practical starting point. Use direct API calls from your application when you already have a durable queue and storage workflow. The reviewed official documentation shows an API example, not a separate CLI, and describes one url parameter per request.
What the ScreenshotMachine API supports
Each documented screenshot request includes a customer key and one page URL. The API uses HTTP GET. The documentation describes these capture settings:
- Dimensions:
dimensionaccepts a width and height, such as1366x768. Documented widths are 100–1920 pixels; heights are 100–9999 pixels, orfullfor a full-page capture, such as1366xfull. - Device:
desktop,phone, ortablet. - Format:
jpg,png, orgif. - Cache:
cacheLimitsets the maximum age in days for a cached capture;0requests a fresh capture. The docs allow decimal values for shorter intervals. The pricing page says the cache lasts 14 days and cached repeats are not charged as fresh screenshots. - Delay:
delaysupports the documented values 0, 200, 400, 600, 800, 1000, and 2000–10000 milliseconds in 1000 ms increments. A longer delay can help when pages need time for images or animations. - Zoom:
zoomsupports 10–400 percent; the documented default is 100. - Interaction and selection:
clickcan click a CSS selector,selectorcan capture a DOM element, andcropcan select a pixel rectangle inx,y,width,heightform. - Page request context:
cookies,accept-language, anduser-agentcan customize the request. Percent-encode values that contain reserved characters.
For exact accepted values and any details not covered here, use the vendor’s API parameter reference. A bulk script should not assume the service accepts options beyond those documented there.
Build a bulk capture script with Bash and curl
The example below reads one URL per line from urls.txt, sends one GET request per URL, writes captures into captures/, and records failures in a CSV file. It deliberately runs requests sequentially, which keeps the initial workflow easy to reason about. Add parallel workers only after you have confirmed an acceptable request rate with the vendor.
Set SCREENSHOTMACHINE_KEY in the environment. Do not commit your key to source control or put it in a publicly served page. The documentation describes a hash option for requests from public HTML; use the vendor’s guidance if that applies to your setup.
#!/usr/bin/env bash
set -u
: "${SCREENSHOTMACHINE_KEY:?Set SCREENSHOTMACHINE_KEY in your environment}"
input="${1:-urls.txt}"
out_dir="${2:-captures}"
mkdir -p "$out_dir"
failures="$out_dir/failures.csv"
printf 'line,url,error\n' > "$failures"
line_no=0
while IFS= read -r url || [[ -n "$url" ]]; do
line_no=$((line_no + 1))
[[ -z "$url" || "$url" == \#* ]] && continue
if [[ "$url" != http://* && "$url" != https://* ]]; then
printf '%s,%q,%q\n' "$line_no" "$url" "URL must start with http:// or https://" >> "$failures"
continue
fi
# Stable numeric names avoid unsafe URL characters and duplicate basenames.
output="$out_dir/$(printf '%06d' "$line_no").png"
tmp="$output.part"
if curl --fail --silent --show-error --get \
--retry 2 --retry-delay 1 --retry-connrefused \
--connect-timeout 15 --max-time 120 \
--data-urlencode "key=$SCREENSHOTMACHINE_KEY" \
--data-urlencode "url=$url" \
--data-urlencode "dimension=1366xfull" \
--data-urlencode "device=desktop" \
--data-urlencode "format=png" \
--data-urlencode "cacheLimit=0" \
--data-urlencode "delay=2000" \
"https://api.screenshotmachine.com" -o "$tmp"; then
mv "$tmp" "$output"
else
status=$?
rm -f "$tmp"
printf '%s,%q,%q\n' "$line_no" "$url" "curl exit $status" >> "$failures"
fi
done < "$input"
Save that as capture-bulk.sh, then run:
chmod +x capture-bulk.sh
export SCREENSHOTMACHINE_KEY='YOUR_CUSTOMER_KEY'
./capture-bulk.sh urls.txt captures
Put one fully qualified URL on each line. Blank lines and lines beginning with # are skipped. Numeric filenames preserve input order and avoid collisions when different sites share a path such as /. The temporary file prevents an interrupted transfer from looking like a completed image.
Equivalent one-request examples in Python and Node.js
These examples show the same API operation for one URL. A bulk program can loop over its input and apply the same checks, naming scheme, retry policy, and concurrency limit described above.
Python
import os
from pathlib import Path
import requests
key = os.environ["SCREENSHOTMACHINE_KEY"]
url = "https://example.com"
response = requests.get(
"https://api.screenshotmachine.com",
params={
"key": key,
"url": url,
"dimension": "1366xfull",
"device": "desktop",
"format": "png",
"cacheLimit": "0",
"delay": "2000",
},
timeout=(15, 120),
)
response.raise_for_status()
content_type = response.headers.get("Content-Type", "")
if "image/" not in content_type:
raise RuntimeError(f"Expected image response, got {content_type!r}")
Path("capture.png").write_bytes(response.content)
Install the dependency with python -m pip install requests. Check the returned content type because an HTTP success alone is not enough to establish that the body is the expected image.
Node.js
import { writeFile } from "node:fs/promises";
const key = process.env.SCREENSHOTMACHINE_KEY;
if (!key) throw new Error("Set SCREENSHOTMACHINE_KEY");
const params = new URLSearchParams({
key,
url: "https://example.com",
dimension: "1366xfull",
device: "desktop",
format: "png",
cacheLimit: "0",
delay: "2000",
});
const response = await fetch(`https://api.screenshotmachine.com/?${params}`,
{ signal: AbortSignal.timeout(120_000) });
if (!response.ok) throw new Error(`Screenshot request failed: HTTP ${response.status}`);
const contentType = response.headers.get("content-type") ?? "";
if (!contentType.includes("image/")) {
throw new Error(`Expected image response, got ${contentType}`);
}
await writeFile("capture.png", Buffer.from(await response.arrayBuffer()));
This uses the built-in fetch available in current Node.js releases. Keep the API key in a server-side environment variable, not browser JavaScript.
How to make bulk captures reliable
- Validate inputs first. Require a URL with an
http://orhttps://scheme, reject blank entries, and decide how to handle duplicates. - Use deterministic output names. Numbered names or a stable hash of the full URL avoid collisions and make it possible to map files back to inputs. Store that mapping in a manifest for later review.
- Check the response. Detect HTTP errors and verify that the response is an image before marking a URL complete. ScreenshotMachine documents an
X-Screenshotmachine-Responseheader with specific error codes; preserve response headers and error details in logs when diagnosing failures. - Retry selectively. Retry transient network failures and server errors with a small bounded retry count and backoff. Do not endlessly retry invalid keys, invalid URLs, invalid selectors, invalid crops, or exhausted credits.
- Make runs resumable. Maintain a manifest with URL, output path, status, attempt count, and last error. Skip successful entries on restart; write downloads to a temporary path and rename only after validation.
- Control request rate. Start sequentially. The official pages reviewed do not publish a rate ceiling, concurrency ceiling, or bulk completion guarantee. Ask the vendor before increasing parallelism, and stop or back off on repeated failures.
- Choose cache behavior intentionally. Use a nonzero
cacheLimitwhen an existing capture within that age is acceptable. UsecacheLimit=0when freshness matters. The pricing page says cached repeats are not billed as fresh screenshots and describes a 14-day cache. - Keep credentials private. Pass the customer key from a secret store or environment variable. Avoid logging the full request URL if it contains credentials, and do not expose the key in client-side HTML.
Pricing, runtime, and operational trade-offs
ScreenshotMachine’s public pricing page currently lists 100 fresh screenshots per month on its free tier, 2,500 for Basic at €9/month, 20,000 for Pro at €59/month, and 50,000 for Enterprise at €99/month. It lists additional screenshot rates of €0.004, €0.003, and €0.002 for Basic, Pro, and Enterprise respectively, with additional captures counted in groups of 1,000 rounded down. It says cached requests are not charged as fresh screenshots and describes a 14-day cache. These are vendor-published figures observed in 2026; verify the live pricing page before budgeting because terms can change.
Estimate the fresh-capture count rather than the raw request count if cache reuse is part of your design. For reproducible visual baselines, request fresh captures and account for the added quota use. For periodic monitoring where a recent image is acceptable, a cache window may reduce fresh capture usage. The docs do not establish how quickly a large set completes or what concurrency the service permits, so test a small representative batch and ask the vendor before committing to a deadline.
Full-page captures and pages with images or animations may take longer; the documentation advises allowing more delay for long pages with images or animation. A fixed delay is a trade-off: too little may capture before content appears, while more waiting increases elapsed time for each request. Begin with a representative set of URLs, inspect the resulting images, and tune dimensions, delay, cache, and device to the actual page behavior.
Common errors and fixes
| Symptom | Likely cause | What to do |
|---|---|---|
| Invalid key or missing key | The customer key is absent, mistyped, or not passed as key. |
Check the environment variable and request parameters. Keep the key private. |
| Invalid URL or missing URL | The url parameter is missing or malformed. |
Validate each input and include its scheme. Use URL encoding through curl’s --data-urlencode or the HTTP library’s parameter support. |
| Credits exhausted | The account’s fresh screenshot allowance has been consumed. | Check account usage and current plan terms; avoid repeatedly requesting fresh captures when a cached result is sufficient. |
| Invalid selector | The CSS selector is invalid or does not resolve as expected on the rendered page. | Confirm the selector against the target page and test a single URL before the batch. |
| Invalid crop | The crop coordinates or dimensions are malformed or outside the intended capture region. | Use the documented x,y,width,height form and verify the region against the viewport. |
| HTML or error content saved with an image extension | The response was treated as a file without checking status, headers, or the documented error header. | Check HTTP status and Content-Type; record X-Screenshotmachine-Response when present, and do not count the file as a successful capture. |
| Cut-off page or missing images | The page needed more rendering time, or full-page content loaded later. | Try an allowed longer delay, verify dimension uses a full height when needed, and inspect the result before scaling up. |
| Partial output after interruption | The transfer stopped after creating the destination file. | Write to a temporary file and rename after success; keep a manifest so the job can resume. |
| Slow run or repeated transient failures | Pages take longer to render, network timeouts are too short, or the request rate is too high. | Use a suitable timeout, bounded retries, and sequential requests initially. Ask ScreenshotMachine about supported throughput before adding concurrency. |
The vendor documentation lists errors such as invalid key, invalid URL, missing key, missing URL, exhausted credits, invalid selector, invalid crop, and generic system errors. Use its response header details to distinguish a capture failure from a transport or script failure.
Or skip the browser setup
If you want a single HTTP call instead of maintaining a capture service or browser automation, ScreenshotNeo is a website screenshot API and MCP server for developers. It returns a PNG, JPEG, WebP, or PDF from a URL. The request below follows the supplied ScreenshotNeo API pattern; see the ScreenshotNeo API documentation for options.
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 the shot; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response says which outcome occurred. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
FAQ
Does ScreenshotMachine have an official CLI?
The official materials reviewed establish an HTTP API and a Bash/curl example, not a separate CLI product. Confirm with the vendor if you need a supported command-line tool.
Is there a documented batch endpoint?
The reviewed screenshot API documentation describes one URL per request. Plan to orchestrate requests locally unless ScreenshotMachine confirms another supported option.
Can I use the same script for PDFs?
The research reviewed a separate ScreenshotMachine webpage-to-PDF API with its own endpoint and parameters. Do not simply change the screenshot output extension; consult the vendor’s PDF API documentation.
How many requests can I send in parallel?
The reviewed official pages do not publish a concurrency ceiling or bulk completion guarantee. Start sequentially and ask the vendor before running a large parallel job.
Should every request force a fresh capture?
Only when freshness is required. cacheLimit=0 requests a fresh capture; a cache age allows reuse, which may suit repeated monitoring when a recent image is acceptable.
