How to Call ScreenshotMachine from a Python Script to Capture Web Pages
Call ScreenshotMachine’s HTTP GET API from Python, save the image, and choose dimensions, format, caching, and wait options for your page.
To capture a webpage with ScreenshotMachine from Python, send an HTTP GET request to https://api.screenshotmachine.com/ with your customer key and target URL as query parameters, then save the returned image bytes to a file. You can use Python’s standard library for a small script or the requests package for more explicit timeouts and HTTP error handling. ScreenshotMachine documents an HTTP GET API and a Python example that builds a request URL and saves it with urllib.request.urlretrieve. ScreenshotMachine API endpoint.
1. Get a key and choose a target
- Get your ScreenshotMachine customer key from your account profile.
- Choose the page URL you want to capture. Pass it as a query parameter so it is percent-encoded correctly.
- Choose the image format and capture options you need. The examples below save a PNG.
Keep your customer key out of source code that you publish. The examples read it from an environment variable instead.
2. Runnable Python example
This version uses only Python’s standard library. It builds a GET request, checks for an HTTP error, and writes the response to a local file. Set SCREENSHOTMACHINE_KEY before running it.
import os
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import urlopen
API_ENDPOINT = "https://api.screenshotmachine.com/"
CUSTOMER_KEY = os.environ["SCREENSHOTMACHINE_KEY"]
PAGE_URL = "https://example.com"
OUTPUT_PATH = "screenshot.png"
params = {
"key": CUSTOMER_KEY,
"url": PAGE_URL,
"dimension": "1366x768",
"device": "desktop",
"format": "png",
"cacheLimit": "0",
"delay": "2000",
"zoom": "100",
}
request_url = API_ENDPOINT + "?" + urlencode(params)
try:
with urlopen(request_url, timeout=90) as response:
image_bytes = response.read()
with open(OUTPUT_PATH, "wb") as image_file:
image_file.write(image_bytes)
except HTTPError as exc:
raise SystemExit(f"ScreenshotMachine returned HTTP {exc.code}: {exc.reason}")
except URLError as exc:
raise SystemExit(f"Could not reach ScreenshotMachine: {exc.reason}")
print(f"Saved {OUTPUT_PATH}")
Run it from a shell after setting the key, for example:
export SCREENSHOTMACHINE_KEY="YOUR_CUSTOMER_KEY"
python capture.py
The timeout=90 is the client-side network timeout in this example, not a documented ScreenshotMachine capture limit. Choose a timeout appropriate to your own job runner.
Using requests
If your project already uses requests, pass the parameters separately and let the library encode them. Check the HTTP status before saving the body.
import os
import requests
response = requests.get(
"https://api.screenshotmachine.com/",
params={
"key": os.environ["SCREENSHOTMACHINE_KEY"],
"url": "https://example.com",
"dimension": "1366x768",
"device": "desktop",
"format": "png",
"cacheLimit": "0",
"delay": "2000",
"zoom": "100",
},
timeout=90,
)
response.raise_for_status()
with open("screenshot.png", "wb") as image_file:
image_file.write(response.content)
The official vendor sample uses a helper to generate the API URL from a key, secret phrase, and options dictionary, then calls urllib.request.urlretrieve. Its helper implementation and imports are not reproduced here; the examples above construct the documented GET request directly.
3. cURL and Node.js equivalents
These are useful for checking the request outside Python or integrating the same endpoint into another service.
cURL
curl -G "https://api.screenshotmachine.com/" \
--data-urlencode "key=YOUR_CUSTOMER_KEY" \
--data-urlencode "url=https://example.com" \
--data-urlencode "dimension=1366x768" \
--data-urlencode "device=desktop" \
--data-urlencode "format=png" \
--data-urlencode "cacheLimit=0" \
--data-urlencode "delay=2000" \
--data-urlencode "zoom=100" \
-o screenshot.png
Node.js
const params = new URLSearchParams({
key: process.env.SCREENSHOTMACHINE_KEY,
url: 'https://example.com',
dimension: '1366x768',
device: 'desktop',
format: 'png',
cacheLimit: '0',
delay: '2000',
zoom: '100',
});
const response = await fetch(`https://api.screenshotmachine.com/?${params}`);
if (!response.ok) {
throw new Error(`ScreenshotMachine returned HTTP ${response.status}`);
}
const fs = await import('node:fs/promises');
await fs.writeFile('screenshot.png', Buffer.from(await response.arrayBuffer()));
4. Configure the capture
ScreenshotMachine’s API reference describes these query parameters and defaults. Include only options you need; pass parameter values as strings when constructing a query dictionary.
| Option | What it controls | Documented values and behavior |
|---|---|---|
key |
Customer authentication | Your unique customer API key; required. |
url |
Target page | The page URL to capture; required. URL-encode it. |
dimension |
Viewport and page extent | widthxheight; width 100–1920, height 100–9999. Use full for full-page height. Default: 120x90. |
device |
Device profile | desktop, phone, or tablet. Default: desktop. |
format |
Image type | jpg, png, or gif. Default: jpg. Match the output filename extension to the selected format. |
cacheLimit |
Maximum cache age | 0–14 days; default 14. Set to 0 to request a fresh screenshot. Decimal values are documented for sub-day periods. |
delay |
Wait before capture | 0–10,000 milliseconds in documented increments; default 200 ms. The API documentation recommends a longer delay, such as 2,000 ms or more, for full-page captures where images or animations need time to load. |
zoom |
Screenshot zoom | 10–400%; default 100%. The vendor notes it may be ignored for screenshots smaller than typical device dimensions. |
click |
Click before capture | A CSS selector for an element to click, for example to dismiss a cookie banner. |
selector |
Capture a particular element | A CSS selector that limits the capture to a selected DOM element. |
cookies |
Send page cookies | Cookie values may need percent-encoding, especially when they contain reserved characters. |
accept-language |
Set language preference | Supplies the page’s language header; encode reserved characters in the value. |
user-agent |
Set user agent | Overrides the user-agent header; encode reserved characters in the value. |
crop |
Capture a region | Specify x,y,width,height in pixels. |
Secret phrase and request hash
If you have configured a secret phrase, the API reference describes an optional hash: an MD5 digest of the URL value concatenated with the secret phrase. When a secret phrase is configured, requests with a missing or incorrect hash are ignored. Follow ScreenshotMachine’s account and API instructions for generating it. Do not put the secret phrase in browser-side or other public code; the vendor recommends the hash protection for calls from public HTML pages.
5. Full-page and element captures
For a full-page capture, set dimension to full and allow the page enough time to load content. The vendor specifically recommends a longer delay for full-page screenshots when images or animations need to render.
params = {
"key": CUSTOMER_KEY,
"url": "https://example.com/article",
"dimension": "1366xfull",
"device": "desktop",
"format": "png",
"delay": "2000",
}
To capture one element, provide its CSS selector. To click a control before capture, provide its selector through click. These options depend on the target page having the corresponding element when the capture runs.
params = {
"key": CUSTOMER_KEY,
"url": "https://example.com",
"selector": "main article",
"click": "button.accept-cookies",
"format": "png",
}
6. Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
| Request is ignored when a secret phrase is configured | The required hash is missing or incorrect. | Confirm the account’s secret phrase setting and generate the documented MD5 hash from the URL value plus secret phrase. |
| Spaces, ampersands, or other URL characters break the request | A query value was concatenated without percent-encoding. | Use urlencode, requests’ params, URLSearchParams, or cURL’s --data-urlencode. |
| Output does not match the requested file type | The format and filename extension differ, or the default JPG was used. |
Set format explicitly and use a matching extension such as .png for PNG. |
| Images or animation are missing | The page had not finished rendering at capture time. | Increase delay; the vendor suggests 2,000 ms or more for full-page cases where images or animations need time. |
| Screenshot is unexpectedly small | The default dimension is only 120x90, or zoom may not apply at small dimensions. |
Set dimension explicitly and check the documented zoom caveat. |
| Cookie banner covers page content | The banner remains visible when the capture runs. | Try click with the banner’s CSS selector, then verify that the selector exists and is actionable on that page. |
| Python reports a URL or network error | Connectivity, DNS, TLS, or client timeout prevented a response. | Check the endpoint and network access, then choose a suitable client timeout. A client timeout is distinct from ScreenshotMachine’s documented delay option. |
The cited vendor material gives parameter ranges and examples, but does not establish latency, uptime, or behavior on every website. A successful HTTP response alone should not be treated as proof that the image shows the intended page state; inspect the saved file in your own workflow.
7. Performance, reliability, and cost choices
- Prefer cache reuse when acceptable: the documented default cache limit is 14 days. Use
cacheLimit=0when freshness matters, understanding that it requests a fresh screenshot. - Keep waits specific: a longer
delaygives a page more rendering time but also lengthens the request. Use the shortest delay that captures the content you need. - Be deliberate with full-page output: use
fullheight when the whole page is needed; otherwise a viewport dimension avoids requesting an unnecessarily tall image. - Protect credentials: load the customer key from a secret store or environment, and keep any configured secret phrase server-side.
- Plan retries at the caller: catch network errors and retry transient failures with a bounded policy appropriate to your application. The research sources provide no service latency, uptime, or retry guarantees.
The API reference documents cache and capture settings, but the available research does not specify plan prices or per-capture charges. Check your account’s current terms before estimating production cost; do not infer cost from image dimensions or delay alone.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. One GET request can return a PNG, JPEG, WebP, or PDF. Its clean-shot flow accepts cookie and consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses identify the page verdict and billing status in headers. AI agents can use its MCP tools, including take_screenshot, get_page_info, and capture_pdf.
See the ScreenshotNeo API documentation. Example request:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Python:
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)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed; an MCP server lets AI agents take screenshots; and 1,000 screenshots a month are free with no card, with paid plans starting at $5 for 3,000. Sign up for ScreenshotNeo free.
FAQ
Can I save the response directly with urlretrieve?
Yes. ScreenshotMachine’s Python sample uses urllib.request.urlretrieve to save the generated API URL to a filename. Construct the query URL with proper encoding and ensure the extension matches the requested format.
Does setting a longer delay guarantee every page element loads?
No such guarantee is established by the cited documentation. The vendor recommends a longer delay for full-page captures when images or animations need more time, but page behavior varies.
Can I request a fresh capture instead of a cached one?
Set cacheLimit to 0, which the API reference describes as requesting a fresh screenshot.


