How to Capture a Website Screenshot with Abstract Screenshot API in Python
Call Abstract’s screenshot endpoint from Python, save the returned image, and troubleshoot common capture problems. Includes a ScreenshotNeo alternative.
Use Python’s requests library to make a GET request to Abstract’s Website Screenshot API at https://screenshot.abstractapi.com/v1/. Pass your Abstract API key and a fully qualified target URL as query parameters, then save the image response to a file. Abstract’s product page shows this endpoint and those two parameters in its request example. Abstract Website Screenshot API.
1. Get an API key and prepare Python
- Create or sign in to an Abstract account and obtain an API key from the provider.
- Install Python 3 and the
requestspackage:
python -m pip install requests
Keep the API key in an environment variable rather than committing it to source control. In a shell, set ABSTRACT_API_KEY to your key before running the example below.
2. Capture and save a screenshot
This example sends only the required key and target URL. It checks the HTTP response and content type before writing bytes, so a JSON or HTML error response is not mistakenly saved as an image.
import os
from pathlib import Path
import requests
API_URL = "https://screenshot.abstractapi.com/v1/"
API_KEY = os.environ.get("ABSTRACT_API_KEY")
TARGET_URL = "https://example.com"
OUTPUT = Path("screenshot.jpg")
if not API_KEY:
raise SystemExit("Set ABSTRACT_API_KEY in your environment before running this script.")
try:
response = requests.get(
API_URL,
params={"api_key": API_KEY, "url": TARGET_URL},
timeout=(10, 90),
)
except requests.Timeout as exc:
raise SystemExit(f"The screenshot request timed out: {exc}") from exc
except requests.RequestException as exc:
raise SystemExit(f"Could not reach the screenshot API: {exc}") from exc
if not response.ok:
detail = response.text[:1000]
raise SystemExit(f"API returned HTTP {response.status_code}: {detail}")
content_type = response.headers.get("Content-Type", "").lower()
if not content_type.startswith("image/"):
raise SystemExit(
f"Expected an image but received Content-Type {content_type!r}: "
f"{response.text[:1000]}"
)
OUTPUT.write_bytes(response.content)
print(f"Saved {len(response.content)} bytes to {OUTPUT}")
For example, on macOS or Linux, run export ABSTRACT_API_KEY='your-key' and then python capture.py. In PowerShell, use $env:ABSTRACT_API_KEY='your-key' before python .\capture.py. The target URL must include https:// or http://.
3. Make the equivalent cURL request
cURL is useful for separating an API problem from a Python problem. The -G flag puts the parameters in the query string, and -o writes the response body to a file.
curl -G "https://screenshot.abstractapi.com/v1/" \
--data-urlencode "api_key=$ABSTRACT_API_KEY" \
--data-urlencode "url=https://example.com" \
--output screenshot.jpg
Check the HTTP status and response headers if the output file is not an image. Do not share a URL containing your API key in logs or support requests.
4. Choose capture options
Abstract describes viewport dimensions, CSS injection, capture delay, and output format as configurable options. Its Python SDK reference lists WebsiteScreenshot.capture parameters for url, capture_full_page, width, height, delay, css_injection, user_agent, and export_format. See the product page and confirm the current API parameter names and accepted values in Abstract’s live documentation before relying on optional settings.
| Choice | When to use it | What to check |
|---|---|---|
| Viewport or full page | Use a viewport for a first-screen preview; use full-page capture when the whole document matters. | SDK and third-party references disagree about the full-page default. Set it explicitly when using the SDK and confirm the current REST parameter spelling and behavior. |
| Width and height | Match the target layout you need to inspect, such as a desktop or narrow mobile viewport. | Confirm allowed dimension limits and whether dimensions mean viewport size or output size. |
| Delay | Allow a page time to render content that appears shortly after navigation. | Use the smallest delay that produces the required state. Extra waiting increases request time. |
| CSS injection | Hide a page element or adjust styles for a controlled capture. | Check how CSS is encoded and whether the API accepts it as a query parameter or through another request format. |
| User agent | Request a page layout tailored to a particular browser or device class. | Changing the user agent does not guarantee the site will serve the same content as a real device. |
| PNG or JPEG | Choose PNG for crisp text and interface details; JPEG may suit photographic previews. | The older SDK reference lists JPEG and PNG, with JPEG as its default. Verify current supported formats and defaults before depending on them. |
The SDK parameter list is not a guarantee that REST query parameters have identical names or encoding. The references available for this article do not establish the current SDK installation command or a verified SDK file-saving recipe, so the HTTP example above avoids guessing those details.
5. Make the capture more reliable
- Use a complete URL. Include the scheme and verify that the page is reachable from the public internet.
- Set the options you care about. In particular, explicitly choose full-page behavior and output format where the current interface permits it; do not rely on defaults that may differ between SDK and API references.
- Allow enough response time. The example uses a 10-second connection timeout and a 90-second read timeout. Tune these for your workload and the provider’s current limits.
- Validate the response. Check the status and content type before saving. Preserve error details in a secure log without exposing the API key.
- Retry selectively. For transient connection failures or server errors, use a small bounded retry count with backoff. Do not repeatedly retry authentication or invalid-parameter errors.
- Test dynamic pages carefully. A fixed delay can help pages that render asynchronously, but it cannot guarantee that every third-party widget or lazy-loaded section has completed.
6. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Authentication error | The key is missing, mistyped, revoked, or sent under the wrong parameter name. | Confirm the account key and send it as api_key for the REST request shown in Abstract’s endpoint example. Keep it out of public code. |
| Invalid URL or capture failure | The target lacks an HTTP scheme, is malformed, or cannot be reached by the capture service. | Pass a complete https:// URL and open it independently. Check redirects, DNS, and whether access requires a private network or login. |
| HTTP error response | The API rejected the request or encountered a service-side problem. | Inspect the status and a short, safely logged response body. Correct request or account errors; retry transient server errors sparingly. |
| Output is JSON or HTML | The API returned an error document instead of image bytes. | Check status and content type as in the Python sample. Do not treat every successful-looking response as an image. |
| Page looks incomplete | Content may load late, depend on scripts, or appear below the viewport. | Confirm full-page settings and use a documented delay if needed. Check current provider documentation for how those options are passed. |
| Layout differs from a browser | Viewport dimensions, user agent, or responsive breakpoints differ from your expected browser. | Set dimensions and, if supported, a user agent explicitly. Compare the same page state and viewport. |
| Request hangs or times out | The target is slow, the connection is unstable, or the read timeout is too short for the capture. | Check target availability, adjust timeouts within provider limits, and use bounded retries for transient failures. |
| Image format or extension mismatch | The actual response format differs from the assumed extension or configured export format. | Verify the current format option and response content type; use a matching filename extension. |
7. Performance, reliability, and cost considerations
Capture time depends on both the target page and the rendering service. Large pages, late-loading assets, and deliberate delays can increase latency. Start with the smallest viewport and delay that meet the requirement, and avoid capturing the same page repeatedly when your application can reuse an existing result.
Abstract’s product page advertises a 99.99% uptime SLA. That is a vendor-published service claim, not an independently measured result; design your integration to handle timeouts and API errors rather than assuming every request succeeds. Abstract’s product page.
Check Abstract’s current account and pricing information for request limits and charges before deploying. The research available for this article does not establish current pricing or quota terms, so no price or free-tier amount is stated here. For production, track request volume, error rates, and response times, and avoid logging credentials embedded in request URLs.
8. Or skip the browser setup
If you want a screenshot API with capture cleanup built in, ScreenshotNeo takes a URL in one GET request and returns an image or PDF. Its cookie and consent handling accepts banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before the capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for AI agents.
Python example (install requests first):
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 the ScreenshotNeo API documentation for authentication and options. The same endpoint supports cURL:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Or use 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}`);
ScreenshotNeo includes 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
9. FAQ
Does the target page need to be public?
The capture service must be able to reach the target. A page limited to your local machine or private network will generally not be reachable from a hosted API.
Can I capture a page that requires authentication?
Do not assume that an ordinary URL request has your browser’s login session. Check Abstract’s current documentation for supported authentication options and avoid placing sensitive credentials in a URL unless the provider explicitly documents a safe method.
Why can’t I rely on the default full-page behavior?
The available SDK reference and third-party specification give conflicting defaults. Set the behavior explicitly and verify the current contract before shipping.
Is the SDK required?
No. The endpoint is a REST API, so Python’s HTTP client can call it directly. The documented SDK interface is another route, but confirm its current install and response instructions in Abstract’s live documentation.


