How to Add an API Key to a Website Screenshot Request
Learn where to put a screenshot API key, how to call the endpoint safely, and how to handle common authentication and rendering errors.
Put the screenshot API key where the provider’s specific endpoint expects it. For ScreenshotEngine’s documented POST endpoint, send it in an Authorization: Bearer header and put the target URL and capture options in a JSON body. Its GET endpoint instead requires api_key in the query string. In a website, make the authenticated request from your backend; do not expose a secret key in browser JavaScript or a public image URL. ScreenshotNeo is another option: its API takes a GET request with an access key and target URL.
1. Choose the right authentication location
There is no universal screenshot API authentication format. Check the documentation for the exact provider, endpoint, and HTTP method. A key may belong in a request header, a query parameter, or another documented mechanism. The body may hold the page URL and capture settings, but that does not mean the credential belongs there.
| Request pattern | Credential location | What to check |
|---|---|---|
| ScreenshotEngine POST | Authorization: Bearer YOUR_API_KEY |
Send JSON with the target URL and options. |
| ScreenshotEngine GET | api_key query parameter |
The documented GET schema requires it; a Bearer header alone does not replace it. |
| ScreenshotNeo GET | access_key query parameter |
Use its documented endpoint and parameter names. |
For a provider that supports header authentication, prefer that over placing a secret in a URL. URLs can be copied, stored in logs, or otherwise exposed. OWASP advises against including authorization in a query string. Still, do not substitute a header for a query parameter when the endpoint explicitly requires the query parameter.
2. Store the key on your server
- Create a key in the provider’s dashboard and store it as a deployment secret or server environment variable.
- Keep it out of source code, browser bundles, public environment variables, client-side configuration, and version control.
- Have your backend call the screenshot API, then return the image bytes or a controlled result to the browser.
- Do not log authorization headers or full request URLs that contain query-string keys.
ScreenshotEngine’s quickstart uses the environment variable SCREENSHOTENGINE_API_KEY. Configure the variable in your deployment platform’s secret settings; the example below reads it from the server process.
3. Call ScreenshotEngine from a backend
This documented POST pattern sends the key in a Bearer header and capture parameters as JSON. It expects image bytes on success.
curl --fail-with-body --request POST 'https://api.screenshotengine.com/v1/screenshot' \
--header "Authorization: Bearer $SCREENSHOTENGINE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"url": "https://example.com",
"format": "png"
}' \
--output screenshot.png
Keep the variable set in the shell or deployment environment. Avoid typing a real key into a command that might be saved in shell history or process logs.
Python
Install the HTTP client with python -m pip install requests. This script reads the key from the environment, checks the response, and writes the returned bytes.
import os
import requests
api_key = os.environ["SCREENSHOTENGINE_API_KEY"]
response = requests.post(
"https://api.screenshotengine.com/v1/screenshot",
headers={"Authorization": f"Bearer {api_key}"},
json={"url": "https://example.com", "format": "png"},
timeout=90,
)
response.raise_for_status()
content_type = response.headers.get("Content-Type", "")
if not content_type.startswith("image/"):
raise RuntimeError(f"Expected image bytes, got Content-Type: {content_type}")
with open("screenshot.png", "wb") as image_file:
image_file.write(response.content)
Node.js
Run this in a server-side Node.js process with SCREENSHOTENGINE_API_KEY configured. It uses the built-in fetch available in current Node.js versions.
const apiKey = process.env.SCREENSHOTENGINE_API_KEY;
if (!apiKey) throw new Error("SCREENSHOTENGINE_API_KEY is not set");
const response = await fetch("https://api.screenshotengine.com/v1/screenshot", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ url: "https://example.com", format: "png" }),
signal: AbortSignal.timeout(90_000),
});
if (!response.ok) {
throw new Error(`Screenshot API returned ${response.status}: ${await response.text()}`);
}
const contentType = response.headers.get("content-type") ?? "";
if (!contentType.startsWith("image/")) {
throw new Error(`Expected image bytes, got Content-Type: ${contentType}`);
}
const bytes = new Uint8Array(await response.arrayBuffer());
await import("node:fs/promises").then(({ writeFile }) => writeFile("screenshot.png", bytes));
If the provider requires a GET query key
ScreenshotEngine documents its GET shape with api_key in the query string. This is an example of that provider’s schema, not a universal convention:
https://api.screenshotengine.com/v1/screenshot?url=https%3A%2F%2Fexample.com&api_key=YOUR_API_KEY
Construct and encode query parameters with an HTTP library where possible. Make the call on the server, keep the full URL out of logs, and never publish it as an <img src> URL because that would disclose the credential to anyone who can inspect the page.
4. Put the screenshot behind your website safely
A public frontend should call your own backend route, not the screenshot provider with your secret embedded. Your backend can authenticate to the provider and return the image bytes with an appropriate image content type, or save the output and return an application-controlled reference. Apply your own access checks and request limits so visitors cannot use your backend as an unrestricted screenshot proxy.
Do not confuse two kinds of authentication:
- API authentication: proves to the screenshot service that your application is allowed to call its API.
- Target-site authentication: gives the renderer access to a page that requires a login.
A screenshot API key does not automatically log the renderer into the target website. Verify whether the selected endpoint documents target cookies, HTTP basic authentication, or other login support. ScreenshotEngine’s documented endpoint accepts public URLs and does not provide custom target-site cookies, target authorization headers, or login scripts. Cloudflare’s screenshot API reference documents target-page cookie and basic-auth options for its endpoint.
5. Verify the response before treating it as an image
Check the HTTP status and response format. Some screenshot endpoints return image bytes directly; others return JSON or a link. ScreenshotEngine’s quickstart describes successful output as file bytes. Do not assume every successful response is a PNG: inspect the provider’s documentation and, when practical, validate the response’s content type before writing it with an image extension.
Also handle non-success responses without returning internal provider details or secrets to a public browser. Log a safe error code and request identifier if available, but redact credentials and sensitive query parameters.
6. Troubleshoot common errors
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 or 403 response | Missing, invalid, expired, or unauthorized key; wrong authentication scheme. | Confirm the key is present in the server environment and use the exact method documented for that endpoint. Check account or key permissions. |
| GET request rejected despite Bearer header | The GET schema requires api_key in the query string. |
Follow that endpoint’s documented GET schema. A header is not a substitute unless the provider says it is accepted. |
| POST request rejected despite query key | The POST endpoint expects Bearer authentication and a JSON body. | Move the key to the Authorization header and send valid JSON with the required content type. |
| Browser reports CORS failure | The browser is calling the provider directly or the provider does not allow that origin. | Call the provider from your backend and expose a route on your own site for the browser to use. |
| Downloaded file is JSON or an error page | The API returned an error body or a different success format than expected. | Check HTTP status and content type before saving. Read the provider’s response documentation. |
| Image is blank or target shows a login page | The target failed to load, requires login, or the endpoint does not support target credentials. | Check the target URL and renderer support. Use documented target cookies or authentication only when the provider supports them. |
| Works locally, fails after deployment | The environment variable was not configured in the deployed server, or the runtime cannot reach the endpoint. | Add the secret to the deployment environment, redeploy if required, and check outbound network policy. Never fix this by putting the key in frontend code. |
| Key appears in logs or a public page | A URL, header, error, or browser bundle exposed the credential. | Issue a replacement key, update the server secret, then revoke the exposed key. Review logging and frontend delivery paths. |
7. Reliability, performance, and cost considerations
- Timeouts: Set a bounded request timeout appropriate to the provider’s documented behavior. A slow target should not leave your web request hanging indefinitely.
- Retries: Retry only transient failures, with a small limit and backoff. Avoid retrying authentication errors or malformed requests; those will not resolve on their own.
- Concurrency: If users can submit many capture requests, queue or limit them so a burst does not overwhelm your application or exceed provider limits.
- Response size: Screenshots can be large. Stream or store bytes appropriately for your application instead of keeping many full images in memory.
- Cost: Check the chosen provider’s current pricing and billing rules, including whether failed captures, retries, cache hits, or asynchronous work count toward usage. Do not infer billing from HTTP status alone.
- Secrets: Restrict access to deployment secrets, rotate exposed credentials, and redact keys from logs and error reporting.
8. Or skip the browser setup
ScreenshotNeo’s API documentation shows the available request options. One GET request can return an image or PDF; use the access key on your server:
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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`ScreenshotNeo returned ${res.status}`);
const image = new Uint8Array(await res.arrayBuffer());
ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up free for 1,000 screenshots a month with no card.
FAQ
Can I put an API key in an image URL?
Do not put a secret key in a public image URL. Use a backend route that keeps provider authentication on the server.
Does the screenshot API key unlock a private target page?
Not by itself. It authenticates your call to the screenshot provider. Target-page login support is a separate, endpoint-specific capability.
What if my provider only supports a query-string key?
Use that documented schema from a backend, limit URL logging, and never expose the full credential-bearing URL publicly.
Should I return raw image bytes or a URL to my frontend?
Either can work, depending on your application and provider response. Keep the provider key server-side; only return bytes or a reference that is safe for the intended audience.


