ScreenshotNeo

BlogHow-to

How to capture a website screenshot with a custom CSS selector in CaptureKit

Capture a specific page element with CaptureKit’s API using the `selector` parameter. Learn how to choose a target, wait for it to load, and troubleshoot common issues.

By the ScreenshotNeo team4 October 20267 min read

To screenshot one element with CaptureKit, send a GET request to /v1/capture with the page URL in url, your API key in the x-api-key header, and the CSS selector for the element in the selector query parameter. The selector chooses what to capture; wait_for_selector instead tells CaptureKit to wait for an element to appear before capture.

1. Get an API key and keep it private

Create an API key through CaptureKit’s dashboard. Keep it in a server-side environment variable or secret store. Do not put it in browser JavaScript, a public repository, or a URL that may be logged. CaptureKit’s documentation describes API keys, credits, logs, and billing controls in its documentation.

2. Choose the element selector

Use a CSS selector that identifies the page element you want in the screenshot. For example, main article targets an article nested in the main content area, while #pricing targets an element with that ID. These are ordinary CSS selector examples; confirm that your target page contains the element you intend to capture.

CaptureKit documents selector as a string used to capture a specific element instead of the full viewport. Its endpoint reference does not specify how multiple matches or unmatched selectors are handled, so avoid relying on undocumented behavior. Test the selector against the page and use a unique target where possible.

3. Make the CaptureKit request

The endpoint is GET https://api.capturekit.dev/v1/capture (the documented route is /v1/capture). Include the required url, the selector, and the x-api-key header. PNG is the documented default. The following cURL example saves the response body to a file:

export CAPTUREKIT_API_KEY="YOUR_API_KEY"
curl -G "https://api.capturekit.dev/v1/capture" \
  -H "x-api-key: $CAPTUREKIT_API_KEY" \
  --data-urlencode "url=https://example.com/products" \
  --data-urlencode "selector=main article" \
  --data-urlencode "format=png" \
  -o element.png

Use --data-urlencode for the page URL and selector so characters such as #, spaces, and punctuation are encoded correctly. Replace the example page and selector with values from your site.

4. Add readiness and output options when needed

If the target is rendered after the initial page load, ask CaptureKit to wait for that element with wait_for_selector. This is separate from selector: one selects the capture target, the other waits for an element to appear. For example:

curl -G "https://api.capturekit.dev/v1/capture" \
  -H "x-api-key: $CAPTUREKIT_API_KEY" \
  --data-urlencode "url=https://example.com/products" \
  --data-urlencode "selector=main article" \
  --data-urlencode "wait_for_selector=main article" \
  --data-urlencode "wait_until=domcontentloaded" \
  --data-urlencode "delay=1" \
  --data-urlencode "format=webp" \
  -o element.webp

The endpoint reference lists these readiness settings:

  • wait_until: networkidle2, load, domcontentloaded, or networkidle0.
  • delay: a delay from 0 to 10 seconds.
  • wait_for_selector: wait for an element to appear before capture.

Choose a wait condition that matches how the page renders. A page that keeps analytics or live connections open may not settle quickly under a network-idle strategy; a selector wait or short delay can be more suitable. Avoid adding a long delay by default because it increases time per request.

Output formats

CaptureKit documents PNG as the default and lists JPEG, JPG, WebP, and PDF as formats. Image quality is documented for JPEG and WebP. Choose PNG when preserving sharp text and edges is useful; use a lossy image format when smaller image files matter. A PDF is a document output, so check that it fits the downstream workflow before treating it as an image.

Other relevant capture settings

The endpoint reference also lists viewport width and height, device emulation, scale factor, full-page capture, lazy-load scrolling, resource blocking, URL blocking, ad removal, caching, and S3 output. These are optional context settings, not substitutes for selector. Consult the current CaptureKit capture reference for exact parameter names and accepted values before adding them. The documented charge is one credit per call; the research available for this article did not establish current plan prices.

5. Use Python

This example sends the same GET request, checks for an HTTP error, and writes the returned bytes to a PNG file:

import os
import requests

api_key = os.environ["CAPTUREKIT_API_KEY"]
response = requests.get(
    "https://api.capturekit.dev/v1/capture",
    headers={"x-api-key": api_key},
    params={
        "url": "https://example.com/products",
        "selector": "main article",
        "format": "png",
    },
    timeout=90,
)
response.raise_for_status()
with open("element.png", "wb") as image_file:
    image_file.write(response.content)

For a delayed target, add "wait_for_selector": "main article" and, if useful, a documented wait_until or delay parameter to params. Keep the API key outside the source file.

6. Use Node.js

With a Node.js version that provides fetch, URL-encode parameters with URLSearchParams and write the binary response:

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

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

const query = new URLSearchParams({
  url: "https://example.com/products",
  selector: "main article",
  format: "png",
});

const response = await fetch(
  `https://api.capturekit.dev/v1/capture?${query}`,
  { headers: { "x-api-key": apiKey } },
);
if (!response.ok) {
  throw new Error(`CaptureKit request failed: ${response.status} ${await response.text()}`);
}
await writeFile("element.png", Buffer.from(await response.arrayBuffer()));

For targets rendered late, add the documented wait_for_selector, wait_until, or delay fields to the URLSearchParams object.

7. Verify the result and handle edge cases

  1. Open the saved file and confirm it contains the intended element and not the full page.
  2. If the result is empty or unexpected, inspect the target page and verify that the selector matches an element at capture time.
  3. If the element is rendered asynchronously, set wait_for_selector for a suitable element and choose a readiness strategy or short delay.
  4. If a selector contains special characters, let your HTTP client encode it instead of concatenating an unescaped query string.
  5. If the target depends on a particular viewport or device layout, set the documented viewport or device-emulation options and verify the layout at that size.
  6. Keep full-page capture and element capture conceptually separate: use selector to target an element; use the full-page option when the goal is a page-length capture.

The endpoint documentation does not establish selector matching rules for multiple elements, exact behavior for invalid selectors, or a particular error response for a missing match. Treat those cases as implementation details to verify against the live endpoint rather than assuming a specific result.

8. Troubleshoot common problems

Symptom Likely cause What to do
Authentication fails The API key is absent, incorrect, or sent under the wrong header. Send the key as x-api-key; verify the environment variable and regenerate or update the key in the dashboard if needed.
The request is rejected The required url is missing or a query value was malformed. Provide a complete page URL and URL-encode query values with your HTTP library.
The wrong thing is captured selector is not specific enough or does not identify the intended element. Use a more specific selector and validate it on the target page. The docs do not define multiple-match selection behavior.
The target is not ready The page creates the element after its initial load. Use wait_for_selector; tune wait_until or add a modest delay within the documented 0–10 second range.
The screenshot layout differs The page responds to viewport or device settings. Set the documented viewport dimensions or device emulation to match the desired rendering context.
The saved file cannot be opened The response may be an HTTP error body rather than an image. Check the HTTP status before saving bytes; inspect the error response and correct the request.
Requests are slower than expected A long delay, network-idle wait, or page resources are extending readiness. Use the narrowest wait condition that reliably makes the target available; consider documented resource blocking where appropriate.

9. Performance, reliability, and cost

Each CaptureKit call is documented as one credit. The cited endpoint documentation does not establish current plan prices, so check the provider’s current dashboard or pricing information before estimating a production budget. Reduce avoidable latency by not adding unnecessary delays and by selecting only the resources and readiness conditions your page needs. Resource blocking is available in the endpoint options, but test that blocked resources do not remove styles or content required by the target.

For production jobs, set client-side timeouts, check HTTP status codes, and retain enough request context to diagnose failures without logging secret keys. Retry only transient failures with a bounded retry policy; repeated calls may consume credits because the documented billing unit is per call. If you need managed storage or batch orchestration, evaluate the documented S3 and caching options in the provider reference and validate their behavior for your workflow.

10. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo. One GET request returns a screenshot or PDF, and its API supports capture by CSS selector. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com/products \
  --data-urlencode selector="main article" \
  -o element.webp

With ScreenshotNeo, cookie and consent banners, newsletter popups, and chat widgets are removed 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 per month with no card, and paid plans start at $5 for 3,000 screenshots. Sign up free for ScreenshotNeo.

FAQ

Does wait_for_selector choose the element in the screenshot?

No. Use selector to choose the capture target. Use wait_for_selector to wait for an element to appear.

Can I capture a full page instead?

The endpoint lists a full-page option. Use that when you need the page-length capture; use selector when you need a specific element.

How many credits does a CaptureKit request use?

The endpoint reference states one credit per call. It does not establish plan prices in the material used here.

Which output format should I choose?

PNG is the documented default. JPEG, JPG, WebP, and PDF are also listed; select the output that fits the system consuming the response.