How to Use a Screenshot API with Python in India
Capture and save website screenshots with Python using a hosted API or Playwright. Includes secure credentials, output options, error handling, and India-specific considerations.
To capture a webpage through a screenshot API with Python, send the page URL and capture options to a hosted service, then save the returned image bytes. You need an account and API credentials for the provider you choose. The example below uses ScreenshotOne’s documented Python SDK; API syntax and options vary by provider.
For India, the code works the same way as elsewhere. The reviewed API documentation does not establish India-specific execution regions, latency, data residency, billing, or payment methods, so confirm those details with your provider if they affect your project.
1. Install the Python SDK and configure credentials
ScreenshotOne’s SDK requires an access key and secret key. Store both in environment variables or a secrets manager. Do not commit them to source control, put the secret key in a public URL, or print authenticated request URLs to logs. Use HTTPS for API requests.
python -m pip install screenshotone
Set the credentials in your shell before running the script. In a Unix-like shell:
export SCREENSHOTONE_ACCESS_KEY="your-access-key"
export SCREENSHOTONE_SECRET_KEY="your-secret-key"
On Windows PowerShell, set them for the current session with $env:SCREENSHOTONE_ACCESS_KEY="your-access-key" and $env:SCREENSHOTONE_SECRET_KEY="your-secret-key". Get the keys from your provider account. See the ScreenshotOne Python SDK documentation, API documentation, and options documentation for the provider-specific details.
2. Capture a page and save it as PNG
This complete script requests a 1280 by 800 viewport screenshot and writes the response stream to screenshot.png. The SDK call and option names follow the provider’s documented Python example, adapted to read credentials from the environment.
import os
import shutil
from screenshotone import Client, TakeOptions
access_key = os.environ["SCREENSHOTONE_ACCESS_KEY"]
secret_key = os.environ["SCREENSHOTONE_SECRET_KEY"]
client = Client(access_key, secret_key)
options = (
TakeOptions.url("https://example.com")
.format("png")
.viewport_width(1280)
.viewport_height(800)
)
image_stream = client.take(options)
with open("screenshot.png", "wb") as output:
shutil.copyfileobj(image_stream, output)
print("Saved screenshot.png")
Run it with python capture.py. The result is image bytes, so open the output file in binary mode (wb). Opening it as text can corrupt the image.
3. Choose capture dimensions and output
Decide what part of the page your application needs before setting options:
| Need | What to configure | Consideration |
|---|---|---|
| A standard page preview | Viewport width and height | The capture shows the rendered viewport, not necessarily the entire document. |
| The whole document | Full-page capture | Long pages can take more time and produce larger files. Lazy-loaded content may need special handling. |
| A particular downstream format | PNG, JPEG, WebP, or PDF, as supported by the provider | Choose a format your next tool can read; PDF is a document output rather than a raster image. |
| A different kind of source | URL, HTML, or Markdown input, when supported | Input modes and their options are provider-specific. |
The sample uses viewport emulation. A mobile-sized viewport does not mean the image was captured on a physical phone; the documented service emulates device rendering. If actual hardware or browser-specific pixel fidelity matters, validate the page on the target device and browser.
ScreenshotOne supports GET and POST requests to its take endpoint, with options in the query string or, for POST, a JSON body. Its API returns binary content for image formats and JSON errors with appropriate HTTP status codes. Consult the provider’s current options reference for exact parameter names and supported combinations rather than assuming one provider’s syntax works with another.
4. Handle errors and verify the output
A successful HTTP response does not remove the need to validate the result in your workflow. Catch provider or network exceptions using the SDK’s documented exception types, and avoid treating an error payload as an image. For a direct HTTP integration, check the status code and response content type before writing bytes to an image file. The provider documents invalid options, internal errors, and usage limits as possible error conditions.
# For direct HTTP clients, follow this general validation pattern:
# 1. Require a successful status code.
# 2. Confirm the response is the expected image content type.
# 3. Save bytes only after validation.
# 4. Log a request identifier and concise error details, never secrets.
5. Use cURL, Python requests, or Node.js with ScreenshotNeo
ScreenshotNeo is a website screenshot API and MCP server for developers. Its API takes a URL in one GET request and returns a screenshot or PDF. The parameter names used by other screenshot APIs also work, which can make migration easier. Read the ScreenshotNeo API documentation for the available options and response headers. The service documents which page verdict occurred and whether a request was billed.
Python
import os
import requests
api_key = os.environ["SCREENSHOTNEO_API_KEY"]
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": api_key, "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
content_type = r.headers.get("Content-Type", "")
if not content_type.startswith("image/"):
raise RuntimeError(f"Expected image response, received {content_type!r}")
with open("shot.webp", "wb") as output:
output.write(r.content)
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Node.js
const apiKey = process.env.SCREENSHOTNEO_API_KEY;
if (!apiKey) throw new Error('Set SCREENSHOTNEO_API_KEY first');
const q = new URLSearchParams({
access_key: apiKey,
url: 'https://example.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const contentType = res.headers.get('content-type') || '';
if (!contentType.startsWith('image/')) {
throw new Error(`Expected image response, received ${contentType}`);
}
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
Set SCREENSHOTNEO_API_KEY in the process environment before running these examples. Do not expose the key in browser-side code or public pages. For the full option list and response behavior, use the ScreenshotNeo docs.
6. Or use Playwright locally
If you want to run and control the browser in your own environment instead of calling a hosted screenshot API, Playwright provides Python screenshot methods. Its documentation covers synchronous and asynchronous use, viewport and full-page screenshots, element screenshots, and returning screenshot bytes.
python -m pip install playwright
python -m playwright install chromium
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={"width": 1280, "height": 800})
page.goto("https://example.com", wait_until="networkidle")
page.screenshot(path="screenshot.png", full_page=True)
browser.close()
For reliable automation, close the browser in a finally block if you add steps that may raise exceptions. Choose a readiness condition that matches the page: waiting for network idle can hang on sites with persistent connections, while capturing too early can miss late content. See the Playwright Python screenshot guide.
7. Or skip the browser setup
With ScreenshotNeo, one request returns the capture. Cookie banners are accepted like a visitor, and 60+ known consent platforms, newsletter popups, and chat widgets are removed before the shot; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. One thousand screenshots a month are free with no card; paid plans start at $5 for 3,000.
import os
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": os.environ["SCREENSHOTNEO_API_KEY"], "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
See the docs for capture settings, including full-page capture, element selectors, device presets, PDF output, custom CSS and JavaScript, wait conditions, request blocking, headers and cookies, caching, signed links, async jobs, bulk capture, and usage details. Sign up for 1,000 free screenshots a month with no card.
8. India-specific account and data questions
The reviewed provider documentation does not say that screenshot requests execute from India or that data is stored there. It also does not establish which payment methods work for Indian customers. If your application has residency, processing-location, invoicing, tax, or payment requirements, ask the provider directly and review its terms before sending sensitive URLs, cookies, or page content.
For either hosted or local capture, treat target pages and credentials as potentially sensitive. Avoid placing private tokens in query strings that may be retained in logs, limit access to saved screenshots, and send only the cookies or headers needed for the capture.
9. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Missing environment variable or authentication error | The key is unset, misspelled, or belongs to a different provider/account. | Check the variable names and account credentials in the same shell or process that runs Python. Never paste the secret into source control. |
| Invalid options response | An option name or value is unsupported, or incompatible with the selected output. | Check the provider’s current API reference and reduce the request to URL plus format and viewport, then add options incrementally. |
| Usage limit response | The account reached its provider limit. | Inspect the response status and provider usage page; adjust volume or plan as appropriate. |
| Output file is unreadable | Error JSON or text was saved as though it were an image, or the file was written in text mode. | Check status and content type before saving, and open the file with wb. |
| Screenshot is blank or incomplete | The target did not finish rendering, content loads after a delay, or access is blocked. | Use a suitable wait condition, verify the URL is accessible to the capture environment, and inspect the provider’s error details. For pages behind authentication, pass only the necessary supported cookies or headers. |
| Full page omits lower content | Some page content loads only when scrolled into view. | Use the provider’s documented full-page/lazy-loading behavior or a browser workflow that scrolls and waits for the needed content. |
| Playwright browser launch fails | The browser binaries or system dependencies are missing. | Run the Playwright browser installation command for the browser you launch, and consult its installation documentation for the host environment. |
| Playwright never reaches network idle | The page maintains long-lived network connections or continuous requests. | Wait for a specific selector or use a bounded timeout/readiness condition that matches the content you need. |
10. Performance, reliability, and cost
For both hosted APIs and local browsers, larger viewports, full-page images, and complex pages can increase processing time and output size. Keep captures to the dimensions and content your workflow actually needs, and choose an output format supported by the next step. Set finite client timeouts and decide whether your job should retry transient network failures; avoid retrying invalid options or authentication failures unchanged.
A hosted API removes the need for your application to launch and maintain browser processes, but it makes the workflow depend on the provider, account limits, and network access. Playwright gives you direct browser control, while your environment must install and operate the browser. The cited documentation does not provide a basis for comparing India-specific speed, prices, or execution locations across providers.
For ScreenshotNeo, the stated plans are Free: 1,000 shots/month with no card; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is available on every plan. Only clean shots are billed: bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Check the current plan and usage details before deploying a high-volume job.
11. FAQ
How do I take a screenshot of a webpage using Python?
Use a provider SDK or HTTP client to send the URL and capture options, then save the returned image bytes in binary mode. The SDK example above uses ScreenshotOne; the one-call requests example uses ScreenshotNeo.
How can I save a website screenshot as a PNG file?
Choose PNG in the provider’s output options and write the returned bytes to a filename ending in .png. A filename extension alone does not convert another image format into PNG.
Does the India context change the Python code?
No. It changes the operational questions to verify, such as billing, execution region, and data residency, none of which the reviewed provider docs establish for India.
Is an API screenshot the same as a physical phone screenshot?
No. A configured mobile viewport is an emulation. Validate on actual target hardware when physical-device rendering is a requirement.


