ScreenshotNeo

BlogHow-to

How to Pass Query Parameters to a Screenshot API

Build reliable screenshot API requests with correctly encoded target URLs, provider-specific options, and safer authentication.

By the ScreenshotNeo team4 October 20268 min read

To pass query parameters to a screenshot API, send each option as its own name=value pair after the endpoint, separated by &. Encode the target page URL as the value of url, especially when it contains its own query string. Use a URL-building library or cURL’s --data-urlencode; do not concatenate nested URLs by hand.

https://api.example/v1/screenshot?url=ENCODED_PAGE_URL&width=1280&format=png

Parameter names, capitalization, types, defaults, and GET/POST support vary by provider. Always check the selected API’s reference before copying options between services.

1. Build a GET request safely

Here is a runnable cURL example. The target URL itself contains ? and &; --data-urlencode encodes it as one query parameter value.

curl --get 'https://api.example/v1/screenshot' \
  --data-urlencode 'url=https://example.com/search?q=maps&lang=en' \
  --data-urlencode 'width=1280' \
  --data-urlencode 'format=png' \
  --output screenshot.png

Replace the example endpoint and option names with the chosen provider’s documented values. The resulting request has one outer query string. The encoded target URL’s question mark and ampersand are data within the url value, not separators for the API’s other options.

Encode the nested URL, not the whole request

A target URL can contain its own query parameters, fragments, spaces, or reserved characters. Encode it as a single value. A URL builder handles this correctly and avoids errors caused by treating the target’s & as the screenshot API’s next option.

  • Correct approach: add url and its raw target value to a query-parameter builder, then let the library encode it.
  • Common failure: concatenate ?url=https://example.com/?a=1&b=2&width=1280 manually. The server may parse b as a screenshot option instead of part of the target URL.
  • Do not encode the target URL twice. Double encoding turns percent signs into encoded percent signs and can make the page URL invalid.

2. Runnable examples in common languages

Python

With requests, pass a dictionary through params. It encodes the query string, including the nested target URL.

import requests

endpoint = "https://api.example/v1/screenshot"
params = {
    "url": "https://example.com/search?q=maps&lang=en",
    "width": 1280,
    "format": "png",
}

response = requests.get(endpoint, params=params, timeout=90)
response.raise_for_status()

content_type = response.headers.get("Content-Type", "")
if not content_type.startswith("image/"):
    raise RuntimeError(f"Expected an image response, got {content_type!r}")

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

Install the dependency with python -m pip install requests. For production, use the provider’s documented timeout and inspect its error response format; a successful HTTP status alone may not mean the response is the image you expected.

Node.js

Use URL and URLSearchParams rather than hand-building the query string.

const endpoint = new URL('https://api.example/v1/screenshot');
const params = new URLSearchParams({
  url: 'https://example.com/search?q=maps&lang=en',
  width: '1280',
  format: 'png',
});

const response = await fetch(`${endpoint}?${params}`);
if (!response.ok) {
  throw new Error(`Screenshot API returned HTTP ${response.status}`);
}

const contentType = response.headers.get('content-type') || '';
if (!contentType.startsWith('image/')) {
  throw new Error(`Expected an image response, got ${contentType}`);
}

const image = Buffer.from(await response.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('screenshot.png', image));

This example uses Node.js with global fetch. If the provider requires authentication, add it as documented; do not place a production secret in client-side code.

3. Choose query options from the provider’s reference

Common screenshot API fields include a target url, output format, viewport width and height, and capture or caching settings. Treat these as examples of concepts, not a universal parameter schema.

Option kind What to verify
Target page Required parameter name, accepted schemes, and whether redirects or authentication are supported.
Dimensions Units, minimum and maximum values, defaults, and whether width/height describe a viewport or output image.
Format and quality Supported formats, quality range, and whether quality applies only to lossy formats.
Capture behavior Full-page support, wait conditions, element capture, and whether the option is available on GET.
Cache Whether caching is enabled, how a cache key is formed, and whether a cache control field changes freshness or billing.
Authentication Query key, authorization header, signed URL, or another scheme, plus the provider’s recommended use for browser-visible requests.

Providers can use different casing and naming between methods. For example, the reviewed documentation describes snake_case GET options and camelCase POST options for one service, and distinguishes basic GET options from advanced POST-only settings for another. Confirm each exact name and allowed value in the current API reference.

4. GET or POST?

Request style Useful when Things to consider
GET with query parameters The configuration is simple, or the resulting capture URL must be used in an image element or Open Graph workflow. URLs can become long. Query credentials can appear in logs, browser history, monitoring systems, and page source.
POST with JSON The API supports complex configuration or a server integration should avoid putting a key in the URL. It cannot be used as a normal <img src> request without a proxy or another integration pattern. Check which options POST accepts.

These are implementation tradeoffs, not universal API rules. Some providers offer signed URLs for public image use; others require a server request. Follow the provider’s authentication and endpoint documentation.

5. Authentication and key handling

Use the authentication method the provider documents. API keys may be accepted in query parameters, headers, or signed URLs, depending on the service. A key in a public URL is visible to anyone who can inspect the page or request, and may also be recorded in logs. For server-side requests, prefer a documented authorization header or POST approach when available. Keep secrets in server-side configuration rather than source code delivered to browsers.

If the API requires a query key for an image URL, use a provider-supported signed URL or a server-side proxy when available. Do not assume that changing GET to POST will work unless that endpoint supports POST and the provider documents the expected authentication format.

6. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its one-call API request takes a URL and returns an image or PDF. The API key and options are documented in the ScreenshotNeo API docs.

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 HTTP ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, and failed loads are not billed, and cache hits cost nothing. Responses identify the page verdict and billing status in X-Page-Verdict and X-Billed headers. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account and get 1,000 screenshots a month with no card.

7. Troubleshooting

Symptom Likely cause Fix
The captured page is missing part of its query string The target URL’s & characters were parsed as outer API separators. Pass the raw target URL as the url value through a URL builder or cURL --data-urlencode.
The target URL contains %25 or encoded text unexpectedly The value was URL-encoded twice. Pass the original target URL once to the query builder; do not pre-encode it as well.
The API reports a missing or invalid option The parameter name, case, type, or GET/POST availability differs from the provider’s API. Compare the request with that provider’s current endpoint reference and use the exact documented field and value type.
Authentication fails The key is missing, sent in the wrong location, invalid, or not permitted for that endpoint. Check the provider’s authentication reference, key status, and whether the endpoint expects a query parameter, header, or signed URL.
The response file is not an image The provider returned an error payload, often with a non-image content type. Check the HTTP status, content type, and provider error body before saving bytes with an image extension.
The browser blocks a request A browser integration may be blocked by cross-origin policy or may expose a key in page source. Use a documented public/signed image URL or call the API from your server. Check provider CORS support rather than assuming it.
The capture is blank or incomplete The page may need more time, may depend on client-side rendering, or may reject automated access. Check provider options for wait conditions and page-load behavior, then inspect its error and capture diagnostics. Do not assume every provider retries or bypasses bot checks.
The request fails only for long target URLs URL length limits in a client, proxy, or API gateway may be exceeded. Use POST if the provider supports equivalent options in a JSON body, or shorten the target URL when possible.

8. Performance, reliability, and cost

  • Keep requests small: send only documented options you need. Large URLs can encounter length limits; move complex configuration to POST when supported.
  • Set bounded timeouts: rendering a page takes longer than fetching a static file. Use a timeout suited to the provider’s documented behavior and handle timeout errors explicitly.
  • Check status and content type: avoid writing API error JSON or HTML to a file ending in .png. Log status and provider error details while redacting credentials.
  • Retry selectively: transient network failures may be retryable, but invalid options and authentication errors will not be fixed by repeating the same request. Use a bounded retry policy and account for provider billing rules.
  • Understand cache behavior: if cache options exist, verify their key and freshness semantics. A cache hit may return an older capture; it is not automatically equivalent to a fresh render.
  • Estimate usage from your plan: compare expected successful captures, retries, and any cache treatment against the provider’s published pricing. Billing rules differ across APIs; do not infer them from HTTP status alone.

9. Frequently asked questions

Can a target URL have its own query string?

Yes. Encode the entire target URL as one value for the screenshot API’s url parameter. A URL builder or --data-urlencode handles its internal separators.

Should I include the question mark before the first option?

Yes. In a manually written URL, the first query parameter follows ?; subsequent parameters follow &. Libraries usually construct those separators for you.

Can I put an API key in an image URL?

Only if the provider supports that pattern, and recognize that a public URL can expose the key. Use a signed URL or server-side request when the provider offers one.

Will the same parameters work with every screenshot API?

No. Providers differ in names, casing, accepted values, authentication, and whether options are available on GET or POST.

When should I use POST?

Use it when the provider supports the needed options and your integration benefits from a JSON body, especially for complex server-side requests or keeping credentials out of the URL.