How to Use ScreenshotAPI.net with Python Requests
Call ScreenshotAPI.net’s v3 screenshot endpoint with Python requests, check the response, and save the image safely as binary data.
Use Python’s requests library to send a GET request to ScreenshotAPI.net’s v3 endpoint, pass your token and target page URL as query parameters, check for an HTTP error, and write the image response as bytes. The documented endpoint is https://shot.screenshotapi.net/v3/screenshot. For an image response, use response.content and open the output in binary mode; do not save response.text as an image. See ScreenshotAPI.net’s render documentation for current parameter details.
1. Get a key and prepare Python
Get an API key through the ScreenshotAPI.net account or dashboard flow. Keep it out of source control and client-side code. The example below reads the key from an environment variable so it does not need to be written into the script.
python -m pip install requests
export SCREENSHOTAPI_TOKEN="your-token"
On Windows PowerShell, set the variable for the current session with $env:SCREENSHOTAPI_TOKEN = "your-token". The environment-variable pattern is a code organization choice; the API examples use a query parameter named token.
2. Make a request and save the image
import os
from pathlib import Path
import requests
endpoint = "https://shot.screenshotapi.net/v3/screenshot"
params = {
"token": os.environ["SCREENSHOTAPI_TOKEN"],
"url": "https://example.com",
"output": "image",
"file_type": "png",
}
# This is an example client-side limit, not a ScreenshotAPI.net service timeout.
response = requests.get(endpoint, params=params, timeout=60)
response.raise_for_status()
Path("screenshot.png").write_bytes(response.content)
Replace https://example.com with the page to capture. The endpoint is the ScreenshotAPI.net service URL; the url parameter is the website being rendered. The params dictionary lets requests encode the nested URL and other values correctly. raise_for_status() stops on unsuccessful HTTP statuses, and write_bytes() preserves the response without text decoding. The documented v3 endpoint and parameter approach are in the provider render guide; the 60-second timeout is an example choice you should adjust to your application’s latency needs and the provider’s current limits.
Save to a chosen path and handle errors
import os
from pathlib import Path
import requests
endpoint = "https://shot.screenshotapi.net/v3/screenshot"
params = {
"token": os.environ["SCREENSHOTAPI_TOKEN"],
"url": "https://example.com/pricing?plan=starter&ref=docs",
"output": "image",
"file_type": "webp",
}
try:
response = requests.get(endpoint, params=params, timeout=(5, 60))
response.raise_for_status()
except requests.exceptions.Timeout as exc:
raise SystemExit(f"Screenshot request timed out: {exc}")
except requests.exceptions.HTTPError as exc:
raise SystemExit(f"Screenshot API returned an HTTP error: {exc}")
except requests.exceptions.RequestException as exc:
raise SystemExit(f"Could not reach ScreenshotAPI.net: {exc}")
output_path = Path("artifacts/page.webp")
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_bytes(response.content)
print(f"Saved {len(response.content)} bytes to {output_path}")
The two-value timeout sets a connection timeout and a read timeout in requests. They are client safeguards, not promises about how long the rendering service takes. The query string in the target URL is safe to pass in params; avoid hand-concatenating the request URL.
3. Choose output and capture options
| Need | What to configure | Notes |
|---|---|---|
| Image file | output=image and a supported file_type, such as png |
Use a matching filename extension and preserve response bytes. |
| Different image format | Set the documented file type to the desired format, such as PNG or JPEG | Check the provider’s current accepted values. Do not infer the format from the filename alone. |
| Full page or a particular viewport | Use the provider’s current full-page and viewport parameters | These settings affect what part of the page appears and its dimensions. Consult the provider help for current names and behavior. |
| Page needs authentication | Use the provider’s documented authenticated-capture options for the target site | Authentication methods vary by website; a single cookie or header recipe does not work everywhere. |
| Remove page content or change styling | Consider documented CSS injection or banner/ad controls | Confirm current option names and check the resulting capture for the target site. |
The v3 example uses token and url query parameters. Do not replace the token parameter with a bearer authorization header unless the current documentation for this endpoint explicitly supports it. ScreenshotAPI.net’s render guide and help pages describe available options; their exact names and limits may change.
4. Equivalent requests in cURL, Python, and Node.js
These examples use the same endpoint and query-based credentials. Store the token securely in your environment in real applications.
cURL
curl --get "https://shot.screenshotapi.net/v3/screenshot" \
--data-urlencode "token=$SCREENSHOTAPI_TOKEN" \
--data-urlencode "url=https://example.com" \
--data-urlencode "output=image" \
--data-urlencode "file_type=png" \
--output screenshot.png
Python requests
import os
from pathlib import Path
import requests
response = requests.get(
"https://shot.screenshotapi.net/v3/screenshot",
params={
"token": os.environ["SCREENSHOTAPI_TOKEN"],
"url": "https://example.com",
"output": "image",
"file_type": "png",
},
timeout=60,
)
response.raise_for_status()
Path("screenshot.png").write_bytes(response.content)
Node.js
const endpoint = new URL("https://shot.screenshotapi.net/v3/screenshot");
endpoint.search = new URLSearchParams({
token: process.env.SCREENSHOTAPI_TOKEN,
url: "https://example.com",
output: "image",
file_type: "png",
});
const response = await fetch(endpoint);
if (!response.ok) {
throw new Error(`ScreenshotAPI.net returned HTTP ${response.status}`);
}
const bytes = new Uint8Array(await response.arrayBuffer());
await import("node:fs/promises").then(({ writeFile }) => writeFile("screenshot.png", bytes));
The Node.js snippet uses the built-in fetch API and writes the binary response. Use a Node version with global fetch, or substitute your HTTP client of choice. In production, add an abort signal or client timeout appropriate to your service.
5. Verify the file and diagnose common problems
| Symptom | Likely cause | What to do |
|---|---|---|
| Image viewer says the file is invalid | Response text was saved, the output mode is not image, or the server returned an error payload. | Use response.content, request image output, call raise_for_status(), and inspect the response before writing when the request fails. |
| 401 or 403 response | Missing, incorrect, revoked, or unauthorized token. | Check that the environment variable is set and the token is current in the provider account. Avoid printing the token in logs. |
| Request fails when the page URL has a query string | The nested URL was concatenated without encoding. | Pass it in the requests params dictionary. Requests will encode the query parameter. |
| Screenshot shows a login, challenge, or access-denied page | The target website returned a restricted or unauthenticated state that was itself rendered. | Check the target site’s access requirements and response state. Use the provider’s supported authentication options where applicable; support varies by site. |
| Image is cropped or too small | Viewport dimensions or capture mode do not match the page. | Review viewport and full-page options in the current help documentation, then choose settings for the intended result. |
| Banner or unwanted element appears | The capture includes page content that was not hidden or removed. | Check the provider’s documented CSS injection and banner/ad controls. Verify behavior on that page. |
| Connection or read timeout | Network trouble, a slow target page, or a client timeout shorter than the operation needs. | Handle requests.exceptions.Timeout, choose a suitable client limit, and retry selectively with a cap rather than looping indefinitely. |
A successful HTTP response only establishes that the API returned a response; it does not prove the rendered page is the intended content. For sensitive workflows, validate that the bytes form the expected image and inspect representative captures. Avoid treating a login or error screen as a successful page capture.
6. Reliability, performance, and cost considerations
- Timeouts: Set a client timeout so a worker does not wait forever. Tune it to your own latency budget and the current service behavior; the 60-second example is not a provider guarantee.
- Retries: Retry transient connection failures or selected server errors with exponential backoff and a small attempt limit. Do not automatically retry authentication errors or malformed requests. Confirm the provider’s billing behavior before retrying paid operations.
- Concurrency: Bound parallel requests to fit your account limits and downstream workload. More simultaneous renders can increase load and make it harder to diagnose failures.
- Payloads and storage: Screenshots can be large. Choose an appropriate format and dimensions, stream or store bytes as needed by your application, and apply retention policies to saved files.
- Secrets: Keep API tokens on the server, restrict access to environment/configuration stores, and rotate compromised credentials using the dashboard controls. Provider key policies can change, so verify current account settings.
- Cost: The dossier does not establish current ScreenshotAPI.net prices, quota, or retry billing rules. Check the provider’s current account and pricing pages before estimating production spend.
7. Or skip the browser setup
ScreenshotNeo offers a one-request screenshot API, with an API guide for its options. It accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say the page verdict and whether it was billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
See ScreenshotNeo’s documentation for the API and configuration options. ScreenshotNeo also supports PNG, JPEG, WebP, and PDF output, element and full-page capture, device presets, custom CSS and JavaScript, waits, request blocking, caching, signed links, asynchronous jobs, bulk capture, and a usage API. Sign up free for 1,000 screenshots a month with no card.
8. FAQ
Do I need a ScreenshotAPI.net Python SDK?
No dedicated SDK is needed for this example; Python requests can call the documented HTTP endpoint directly.
Can I use this flow to capture any website?
The request can target a website URL, but the rendered result depends on that site’s availability, access controls, and authentication requirements.
Why does the official sample print response text?
Text output is useful for text responses, but image bytes should be saved from response.content to avoid decoding binary data.
Where should I check for option changes?
Refer to the provider’s current render documentation and help center before relying on advanced parameter names or limits.


