Screenshot API Options and Settings in Python
A complete Python guide to screenshot API options: formats, cookies, CSS, geolocation, browser emulation, errors, and production patterns.

Use a screenshot API when you need a rendered browser view without installing or operating a browser in your application. In Python, send a GET request to https://shot.screenshotapi.net/v3/screenshot, authenticate with token, provide url, choose an output format, and write the response bytes to a file. The same request can preserve cookies, inject CSS, emulate a client, set geolocation, add headers, or route traffic through a proxy.
This guide explains the documented ScreenshotAPI.net options, provides runnable Python, cURL, and Node.js examples, and covers the edge cases that usually cause blank, unauthorized, or incorrectly sized captures. At the end, you will also see a browser-free option from ScreenshotNeo.
1. The basic Python request
The shortest useful implementation uses requests. The API returns the rendered file when output=image is selected.

import requests
TOKEN = "YOUR_API_KEY"
params = {
"token": TOKEN,
"url": "https://example.com",
"output": "image",
"file_type": "png",
}
response = requests.get(
"https://shot.screenshotapi.net/v3/screenshot",
params=params,
timeout=60,
)
response.raise_for_status()
with open("screenshot.png", "wb") as image_file:
image_file.write(response.content)
print("Saved screenshot.png")
requests URL-encodes the query parameters for you. Keeping the URL in params, rather than concatenating it into the endpoint string, avoids errors with query strings, ampersands, spaces, and non-ASCII characters.
Using Python’s standard library
If you do not want a third-party dependency, urllib follows the same request model.
import urllib.parse
import urllib.request
TOKEN = "YOUR_API_KEY"
target = urllib.parse.quote_plus("https://example.com")
query = (
"https://shot.screenshotapi.net/v3/screenshot"
f"?token={TOKEN}&url={target}&output=image&file_type=png"
)
urllib.request.urlretrieve(query, "screenshot.png")
Keep the token out of source control. Read it from an environment variable or your deployment secret store in production.
2. cURL and Node.js equivalents
cURL
curl -G "https://shot.screenshotapi.net/v3/screenshot" \
--data-urlencode "token=YOUR_API_KEY" \
--data-urlencode "url=https://example.com" \
--data-urlencode "output=image" \
--data-urlencode "file_type=png" \
-o screenshot.png
Node.js
const params = new URLSearchParams({
token: 'YOUR_API_KEY',
url: 'https://example.com',
output: 'image',
file_type: 'png'
});
const response = await fetch(
`https://shot.screenshotapi.net/v3/screenshot?${params}`
);
if (!response.ok) {
throw new Error(`Screenshot request failed: ${response.status}`);
}
const image = Buffer.from(await response.arrayBuffer());
await require('node:fs').promises.writeFile('screenshot.png', image);
3. Response type and file format
| Setting | What it does | When to use it |
|---|---|---|
output=image |
Returns raw rendered media bytes. | Save or stream a PNG, JPG, WebP, or supported document format. |
output=JSON |
Returns structured render information. | Inspect render results or metadata before deciding what to store. |
file_type |
Selects the output media/document format. | Choose PNG for lossless UI detail, JPG for smaller photographic images, WebP where your consumer supports it, or PDF where supported. |
The documented examples use file_type=png. Check the service documentation for the exact formats enabled for your account and endpoint version before hard-coding validation rules. A binary response must be written with wb in Python; opening it as text corrupts the file.
Saving a different format
params = {
"token": TOKEN,
"url": "https://example.com",
"output": "image",
"file_type": "webp",
}
response = requests.get(
"https://shot.screenshotapi.net/v3/screenshot",
params=params,
timeout=60,
)
response.raise_for_status()
with open("screenshot.webp", "wb") as image_file:
image_file.write(response.content)
4. Page source and visual controls
Capture supplied HTML with custom_html
custom_html renders supplied markup instead of loading the URL. URL-encode the HTML, especially when it contains CSS, ampersands, quotes, or inline SVG. This is useful for invoices, generated reports, and deterministic templates.
html = """
<!doctype html>
<html>
<body>
<h1>Invoice 1042</h1>
<p>Total: $120.00</p>
</body>
</html>
"""
params = {
"token": TOKEN,
"url": "https://example.com", # required by some clients; custom_html takes precedence
"custom_html": html,
"output": "image",
"file_type": "png",
}
response = requests.get("https://shot.screenshotapi.net/v3/screenshot", params=params, timeout=60)
response.raise_for_status()
open("invoice.png", "wb").write(response.content)
Hide elements with CSS
The css option injects CSS before capture. Hide cookie notices, navigation, ads, or test-only elements with a selector. For example, .module-content{display:none} removes matching content from the rendered image. Escape CSS correctly when passing it in a shell command or as a Python parameter.
params = {
"token": TOKEN,
"url": "https://example.com/article",
"css": ".cookie-banner, .newsletter-modal { display: none !important; }",
"output": "image",
"file_type": "png",
}
Prefer a narrow selector. Hiding a broad container such as body can produce a blank result and make the failure look like a network problem.
5. Cookies, authentication, and request state
Pass cookies when the page changes based on a session, consent choice, feature flag, or login. The documented syntax supports semicolon-separated cookie pairs.

params = {
"token": TOKEN,
"url": "https://example.com/account",
"cookies": "session_id=abc123; theme=dark; consent=yes",
"output": "image",
"file_type": "png",
}
response = requests.get("https://shot.screenshotapi.net/v3/screenshot", params=params, timeout=60)
response.raise_for_status()
open("account.png", "wb").write(response.content)
Only send cookies that are necessary for the capture. Treat session cookies as credentials: do not log the complete query string, commit it to code, or expose it in client-side JavaScript. If a login flow requires several browser interactions rather than a reusable cookie, the API request may not reproduce that state; create a valid session first or use a capture service that supports scripted actions.
6. Browser and network emulation
These options let you reproduce the context in which a page is rendered:
| Option | Purpose | Example |
|---|---|---|
user_agent |
Represent a browser, device, crawler, or application. | Desktop or mobile user-agent string |
accept_languages |
Set the browser language preference. | en-US,en;q=0.9 |
headers |
Send custom HTTP headers before rendering. | Preview or authorization headers |
proxy |
Route the request through a network address, optionally with authentication. | Regional or internal-network testing |
latitude, longitude |
Set browser geolocation context. | Numeric coordinates for a localised page |
params = {
"token": TOKEN,
"url": "https://example.com/store",
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 Mobile/15E148 Safari/604.1",
"accept_languages": "fr-FR,fr;q=0.9",
"headers": "X-Preview: true; X-Request-Source: screenshot",
"latitude": "48.8566",
"longitude": "2.3522",
"output": "image",
"file_type": "png",
}
Use a fixed set of emulation values in visual regression jobs. Changing the user agent, language, cookies, or coordinates can legitimately change text, layout, prices, and available content.
7. A practical option checklist
- Start with
url,output=image, and a knownfile_type. - Add
custom_htmlonly when the page is generated markup rather than a URL. - Add
cssfor deterministic visual cleanup. - Add
cookiesfor consent, sessions, or feature flags. - Add
user_agentandaccept_languageswhen reproducing a client experience. - Add
headersfor preview or request metadata. - Add
latitudeandlongitudefor location-sensitive pages. - Add
proxywhen the page must be fetched from a specific network origin.
8. Troubleshooting common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 or authentication error | Missing, invalid, or rotated token. | Read the current token from your secret store. Rolling a key revokes the previous key, so update every worker. |
| 400 or malformed request | Unencoded URL, CSS, HTML, or headers. | Pass values through requests parameters or --data-urlencode; do not build a raw query string manually. |
| Downloaded file will not open | Binary bytes were saved as text, or an error body was saved as an image. | Use wb, call raise_for_status(), and inspect the response content type before storing. |
| Blank page | The URL failed, content is hidden, JavaScript did not finish, or CSS selected a parent container. | Open the URL directly, remove the CSS rule, verify cookies and headers, and try a simpler page. |
| Login page instead of account page | Cookies are absent, expired, scoped to another domain, or formatted incorrectly. | Send the required cookie pairs with the documented semicolon syntax and confirm they belong to the target domain. |
| Wrong language or location | Missing or conflicting language and geolocation settings. | Set accept_languages and numeric coordinates explicitly; keep them fixed between comparisons. |
| Layout differs from a user’s browser | User agent, viewport defaults, fonts, or responsive breakpoints differ. | Set an appropriate user_agent and compare the same client context consistently. |
| Requests time out | The page or a third-party resource is slow. | Use a bounded timeout, retry transient failures with backoff, and capture a simpler URL to isolate the slow dependency. |
9. Reliability, performance, and cost considerations
Screenshot work is render work, so response time depends on the page, its scripts, images, and external resources. Keep your application responsive by setting a client timeout, limiting concurrent requests to the service limits on your plan, and retrying only transient network or server failures. Do not blindly retry authentication or malformed-request errors.
For repeatable output, use stable URLs, explicit cookies and emulation values, and a consistent format. Store a content hash with each capture if you need deduplication. PNG preserves sharp text but can be larger; JPG and WebP can reduce storage when their quality characteristics fit your use case. If you request JSON output, retain the structured result for diagnostics instead of discarding it.
Estimate cost from the number of successful renders, output size, storage, and retries. Cache identical requests in your own application when the page does not change frequently. Before production rollout, confirm the current provider limits, supported formats, and account pricing in the provider documentation; the research material for this guide does not specify quota or price figures.
10. Or skip the browser setup
ScreenshotNeo provides a single GET request for a PNG, JPEG, WebP, or PDF. Its capture flow accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response reports the page verdict and billing status in X-Page-Verdict and X-Billed headers. Every feature is available on every plan, including an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
See the ScreenshotNeo API documentation for the complete option list. The minimal call is:
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 request failed: ${res.status}`);
ScreenshotNeo also supports full-page captures with lazy images loaded, CSS element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page settings, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, custom headers and cookies, user agents, timezone and geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free. Create a free ScreenshotNeo account.
11. FAQ
Can I return metadata instead of an image?
Yes. Set output=JSON when you need structured render information rather than raw media bytes.
How do I hide one element without changing the source page?
Pass a CSS rule through css, targeting the element’s selector and using display:none when appropriate.
Which option handles an authenticated page?
Use cookies for an existing session and headers for request metadata. Verify that the values are current and scoped to the target site.
Can geolocation change the screenshot?
Yes. latitude and longitude set the browser geolocation context, which can affect local content and availability.
Should I use a URL or custom HTML?
Use url for a live website. Use custom_html for markup your application generates and wants rendered directly.