ScreenshotNeo

BlogHow-to

CaptureKit Screenshot API Example in Node.js for Indian Developers

Call CaptureKit’s screenshot API from Node.js with a server-side API key. Learn formats, response handling, credit use, and common fixes.

By the ScreenshotNeo team4 October 20266 min read

Use CaptureKit’s HTTP API from a Node.js backend: send a GET request to https://api.capturekit.dev/v1/capture, pass the page address in the url query parameter, and authenticate with your API key in the x-api-key header. A successful screenshot call costs one credit. The same API setup applies to developers in India; the reviewed documentation describes no India-specific endpoint, pricing, or configuration.

What you need

  1. A CaptureKit account and API key. The current dashboard is at app.capturekit.dev.
  2. Node.js with the built-in fetch API (Node.js 18 or later is a convenient baseline).
  3. Credits for successful synchronous captures. CaptureKit’s endpoint documentation says one screenshot call costs one credit.

CaptureKit describes itself as an HTTP API called from your backend, an automation platform, or an AI agent. Keep the key on the server: do not put it in browser JavaScript or a public repository. See the CaptureKit documentation for current setup details.

Complete Node.js example

This runnable example reads the key from an environment variable, requests a PNG, checks for HTTP errors before reading the body, and writes the returned bytes to a file.

import { writeFile } from "node:fs/promises";

const apiKey = process.env.CAPTUREKIT_API_KEY;
if (!apiKey) {
  throw new Error("Set CAPTUREKIT_API_KEY in the environment");
}

const endpoint = new URL("https://api.capturekit.dev/v1/capture");
endpoint.searchParams.set("url", "https://example.com");
endpoint.searchParams.set("format", "png");

const response = await fetch(endpoint, {
  method: "GET",
  headers: { "x-api-key": apiKey }
});

if (!response.ok) {
  const detail = await response.text();
  throw new Error(`CaptureKit returned HTTP ${response.status}: ${detail}`);
}

const image = Buffer.from(await response.arrayBuffer());
await writeFile("screenshot.png", image);
console.log(`Saved screenshot.png (${image.byteLength} bytes)`);

Save as capture.mjs, then run CAPTUREKIT_API_KEY=your_key node capture.mjs on macOS/Linux. In PowerShell, set the variable for the session with $env:CAPTUREKIT_API_KEY="your_key", then run node capture.mjs. The sample writes to the current directory; use an application-controlled storage location in a service.

Request parameters and output formats

Input Purpose Notes
url Address of the webpage to capture. Required. Build the request with URL and searchParams so reserved characters are encoded correctly.
format Requested output type. PNG is the documented default. The endpoint also documents JPEG/JPG, WebP, and PDF. Choose a format your downstream code can store and serve.
x-api-key Authentication header. Send the key from server-side configuration, never as a query parameter or frontend value.

PNG is a practical default when preserving crisp details matters. JPEG can suit photographic pages where a smaller lossy image is acceptable; WebP is useful when your consumers support it. PDF is a document output, so handle and name its bytes as a PDF rather than assuming they are an image. Confirm the current endpoint reference for accepted parameter values and response behavior.

Handle the response safely

On success, consume the response as bytes. Do not call response.json() for an image or PDF body. Check response.ok first because error responses are not the requested capture. The example reads an error body as text for diagnostic context; avoid returning internal details or secrets to an untrusted client.

For an application endpoint, validate the requested target URL before forwarding it, constrain who can trigger captures, and set an application-level timeout or cancellation policy appropriate to your service. Avoid exposing an unrestricted screenshot proxy: arbitrary target URLs can create server-side request risks. Store outputs with a filename and content type that match the requested format.

cURL and Python equivalents

cURL

curl --get "https://api.capturekit.dev/v1/capture" \
  --header "x-api-key: $CAPTUREKIT_API_KEY" \
  --data-urlencode "url=https://example.com" \
  --data-urlencode "format=png" \
  --output screenshot.png

Python

import os
import requests

api_key = os.environ["CAPTUREKIT_API_KEY"]
response = requests.get(
    "https://api.capturekit.dev/v1/capture",
    params={"url": "https://example.com", "format": "png"},
    headers={"x-api-key": api_key},
    timeout=90,
)
if not response.ok:
    raise RuntimeError(f"CaptureKit returned HTTP {response.status_code}: {response.text}")

with open("screenshot.png", "wb") as output:
    output.write(response.content)

These examples use the current /v1/ endpoint and x-api-key header. Older examples using an access_key parameter do not match the current migration guidance.

Storage, S3, and choosing a plan

The endpoint reference documents S3-related upload options. Use them when you want the capture workflow to deliver output into your configured storage path; check the endpoint reference for the exact option names and required credentials. Otherwise, the example’s application-managed file or object storage flow is straightforward for small jobs.

Estimate monthly usage from successful synchronous screenshot calls: the endpoint lists one credit per capture. The pricing page advertises a free tier and paid monthly tiers, and its allowances and prices can change. Compare your expected monthly successful captures with the live CaptureKit pricing page before choosing a plan. The general billing documentation says successful synchronous calls are billed and errors are generally free subject to endpoint-specific exceptions, so do not treat every status code as having identical billing behavior. Async modes, where supported, have separate billing behavior; polling is documented as free. This example is synchronous and does not use async mode.

Reliability, performance, and cost considerations

  • Bound waiting time: network calls can take longer than expected. Set a timeout strategy suitable for your service and use cancellation where supported by your Node.js runtime.
  • Retry selectively: transient server failures may merit a bounded retry with backoff. Do not repeatedly retry invalid requests, invalid keys, payment-required responses, or rate limits without correcting the cause or respecting the service’s limits.
  • Control concurrency: queue bulk work and cap parallel requests to avoid bursts that trigger rate limits or overwhelm your own storage and worker capacity.
  • Track bytes and format: capture output size affects transfer, memory, and storage. For large volumes, stream or upload using the documented storage options instead of accumulating many buffers in memory.
  • Budget by actual calls: one credit is listed per screenshot call. Check current plan allowances and endpoint billing exceptions before forecasting cost.

Troubleshooting

Symptom Likely cause Fix
HTTP 401 Key is invalid, inactive, expired, or missing. Check the current dashboard key and ensure the request sends it in x-api-key. Do not use legacy access_key examples.
HTTP 402 Payment or available credits are insufficient. Review account billing and the live plan allowance.
HTTP 400 Malformed or missing request input, often the target URL or an unsupported option. Inspect the error body, encode parameters through URL.searchParams, and check the endpoint reference.
HTTP 429 or rate limit Too many requests for the current limit. Reduce concurrency, queue work, and retry with backoff where appropriate.
HTTP 500 Internal service error. Record the status and diagnostic response, then retry only with a bounded policy.
File contains unreadable text or JSON An error response was saved as if it were an image, or the body was parsed with the wrong method. Check response.ok before writing and consume successful output as bytes.
Output is missing or has the wrong extension The requested format and saved filename/content type do not agree. Choose a supported format and keep the output name and serving content type consistent with it.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF, and its parameter names also work with those used by other screenshot APIs to make switching easier. Its API documentation is at screenshotneo.com/docs.

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up free for ScreenshotNeo.

FAQ

Does the India location change the API request?

The reviewed sources show no India-only endpoint or setup. Use the same documented endpoint and authentication pattern, and check the vendor for region-specific matters not covered in those docs.

Can I put the API key in a web page?

No. Keep it in server-side environment or secret configuration. A key in browser code can be copied and used by others.

Does one request always cost one credit?

The capture endpoint lists one credit per screenshot call. General billing documentation distinguishes successful synchronous calls from errors and notes endpoint-specific exceptions, so consult the current billing terms for edge cases.