How to Automate Website Screenshots with Browserless in Python from India
Capture website screenshots with Browserless in Python: make an authenticated request, save the image, choose capture options, and troubleshoot incomplete results.
To automate a website screenshot with Browserless in Python, send an authenticated POST request to its /screenshot endpoint. Put your Browserless token in the token query parameter, send the target URL and screenshot options as JSON, then save the binary response.
The example below captures a full-page PNG. It uses a public example page; replace that URL with a site you are permitted to access. The title’s “from India” wording identifies the intended audience, but the available documentation does not establish an India-specific endpoint, latency, price, tax treatment, or payment method.
1. Make a screenshot with Python
Install the only dependency:
python -m pip install requests
Set your Browserless token in an environment variable so it does not end up in source control:
export BROWSERLESS_TOKEN="your_browserless_token"
Save this as screenshot.py and run it with python screenshot.py:
import os
from pathlib import Path
import requests
TOKEN = os.environ["BROWSERLESS_TOKEN"]
ENDPOINT = "https://production-sfo.browserless.io/screenshot"
response = requests.post(
ENDPOINT,
params={"token": TOKEN},
headers={"Cache-Control": "no-cache"},
json={
"url": "https://example.com/",
"options": {"fullPage": True, "type": "png"},
},
timeout=120,
)
response.raise_for_status()
Path("screenshot.png").write_bytes(response.content)
print("Saved screenshot.png")
The endpoint, token query parameter, JSON request shape, full-page option, PNG type, and writing of response bytes follow Browserless’s [Screenshot API](https://docs.browserless.io/rest-apis/screenshot-api) and [Python screenshot walkthrough](https://docs.browserless.io/examples/screenshot). The timeout, environment variable, and raise_for_status() are practical safeguards in this example. Keep the token private.
What the request does
requests.post()sends the request to Browserless’s screenshot endpoint.params={"token": TOKEN}places the API token in the query string. Do not print the complete request URL in logs that may be shared.- The JSON body tells Browserless which page to visit and configures the screenshot.
response.raise_for_status()raises an exception for an HTTP error instead of silently saving an error response as an image.response.contentcontains the binary response. Write it as bytes; do not decode it as text.
2. Choose REST or a connected browser
Browserless describes its REST APIs as single browser tasks that do not require you to manage browser infrastructure. The screenshot endpoint is a good fit when the job is “open this URL and return an image.” For workflows that need multiple interactions or state before the capture—such as navigating, clicking, filling a form, and then taking a screenshot—use a connected Playwright or Puppeteer browser session. Browserless documents both REST and WebSocket approaches in its [screenshot walkthrough](https://docs.browserless.io/examples/screenshot) and explains the REST model in its [REST APIs overview](https://docs.browserless.io/rest-apis/intro).
| Need | Approach | Why |
|---|---|---|
| One URL capture per request | REST /screenshot |
A single HTTP request returns the image. |
| Several browser actions before capture | Connected browser session | Your script controls interactions and page state before taking the screenshot. |
| Capture a page your script generates | REST with HTML input, or a browser session | Use the documented HTML input when appropriate; do not send html and url together in one request. |
3. Useful screenshot options
Options belong in the request’s options object unless noted otherwise. Browserless documents Puppeteer-style screenshot options for the endpoint; consult the [Screenshot API reference](https://docs.browserless.io/rest-apis/screenshot-api) for the accepted fields and current details.
| Goal | Setting | When to use it |
|---|---|---|
| Capture beyond the visible viewport | options.fullPage: true |
Use for a full-page image rather than just the initially visible area. |
| Choose image encoding | options.type, such as png, jpeg, or webp |
Choose a supported format that suits your downstream use. |
| Capture a specific element | Top-level selector |
Use a CSS selector when only one page element is needed. |
| Capture a fixed rectangle | options.clip |
Use coordinates and dimensions when the capture area is known in advance. |
| Trigger lazy-loaded content | scrollPage: true |
Use when images or sections appear only after scrolling; pair with full-page capture when appropriate. |
| Wait for a page to be ready | Documented wait controls for events, functions, selectors, or timeouts | Choose a wait that matches the page’s loading behavior instead of relying on an arbitrary short delay. |
| Limit what the browser fetches | Documented request or resource filtering controls | Use only when you know which requests or resource types can be omitted without changing the desired result. |
For example, the Python request above sets fullPage and type. To request an element or clip, add the documented field at the level specified by the API reference. Avoid copying option names from a different browser library without checking Browserless’s request schema.
4. Equivalent cURL and Node.js requests
These examples send the same kind of one-shot request and save or expose the returned binary image. Use an environment variable for the token in each case.
cURL
curl --fail-with-body \
-X POST "https://production-sfo.browserless.io/screenshot?token=${BROWSERLESS_TOKEN}" \
-H "Content-Type: application/json" \
-H "Cache-Control: no-cache" \
--data '{"url":"https://example.com/","options":{"fullPage":true,"type":"png"}}' \
--output screenshot.png
Node.js
const token = process.env.BROWSERLESS_TOKEN;
if (!token) throw new Error("Set BROWSERLESS_TOKEN first");
const endpoint = new URL("https://production-sfo.browserless.io/screenshot");
endpoint.searchParams.set("token", token);
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-cache",
},
body: JSON.stringify({
url: "https://example.com/",
options: { fullPage: true, type: "png" },
}),
signal: AbortSignal.timeout(120_000),
});
if (!response.ok) {
throw new Error(`Browserless returned HTTP ${response.status}: ${await response.text()}`);
}
const image = Buffer.from(await response.arrayBuffer());
await import("node:fs/promises").then(({ writeFile }) => writeFile("screenshot.png", image));
console.log("Saved screenshot.png");
The Node.js example requires a Node version with built-in fetch and AbortSignal.timeout. If your runtime does not provide them, use a supported runtime or a compatible HTTP client with a request timeout.
5. Handle incomplete or blocked captures
A screenshot service can only return what its browser was able to access and render. A successful HTTP response does not prove that the screenshot contains the intended page. Open the image or inspect it in an automated pipeline before treating it as valid output.
| Symptom | Possible cause | What to try |
|---|---|---|
| The image is blank or mostly empty | The page has not rendered its content yet, or the site blocks automated access. | Inspect the image; choose a suitable documented wait condition. If the page shows an access-denied response, respect the site’s access controls. |
| The image contains a CAPTCHA or 403/access-denied page | The target may be blocking browser automation. | Do not treat the result as a valid capture. Browserless documents an /unblock endpoint for some bot-detection cases, but it is not a universal bypass and does not override a site’s access rules. |
| Images or lower-page sections are missing | Content may load only after scrolling, or the capture may cover only the viewport. | Try scrollPage: true for lazy-loaded content and options.fullPage: true for a full-page screenshot. |
| An element is absent | The selector may not match, or the element may not exist when capture begins. | Confirm the selector against the rendered page and use an appropriate documented wait for the selector. |
| The script saves a file but it is not a valid image | The server may have returned an error body, or an error response may have been written as bytes. | Check the HTTP status before saving. Inspect the response content type and error body when diagnosing a failed request. |
| The request times out | The page or its resources may take longer than the client timeout. | Set a timeout appropriate to your workflow and investigate slow or blocked page loads. Avoid unlimited waits in batch jobs. |
| The API reports an authentication problem | The token may be missing, invalid, or not passed as the expected query parameter. | Check that BROWSERLESS_TOKEN is set and that the request includes ?token=…. Do not expose the token in shared logs. |
| The request fails after switching to HTML input | The request may include both html and url. |
Send one input mode at a time; Browserless cautions against sending html and url together. |
For a first capture, start with a public page you are allowed to access. Check the saved image, then add full-page, wait, selector, or scrolling settings only when the page calls for them.
6. Performance, reliability, and cost considerations
- Request time: A capture requires a browser to load and render the page. A slow target, heavy assets, or a wait condition that takes too long can delay completion. Set a client timeout and choose waits deliberately.
- Output size: Full-page captures and image formats affect the amount of data written and transferred. Choose the capture area and a supported format that meet your use case.
- Reliability: Sites can change their markup, load content asynchronously, or block automation. Treat the returned image as an output to validate, especially in unattended jobs.
- Retries: Retry transient transport failures selectively. A retry cannot fix a CAPTCHA, access denial, invalid selector, or a page that consistently lacks the expected content.
- Secrets: Keep the token in environment or secret storage, restrict access to it, and avoid logging complete URLs that contain it.
- Cost and India-specific details: The research for this guide does not establish Browserless’s current price, India-specific billing or taxes, or an endpoint region closest to India. Check your Browserless account and current billing documentation before estimating costs or latency.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request can return a PNG, JPEG, WebP, or PDF. Its API accepts the parameter names used by other screenshot APIs, which can make switching easier. See the ScreenshotNeo API documentation.
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
It removes cookie banners, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan.
Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.
8. Frequently asked questions
Does “from India” change the Python code?
No India-specific code change is established by the available Browserless documentation. The example uses the documented endpoint; verify current region and account details directly with Browserless if location affects your requirements.
Can I use this to capture a page that requires login?
The basic example does not handle an authenticated browser session. If the task requires login or other interactions before capture, use a connected browser workflow and follow the target site’s access rules.
Can Browserless generate a screenshot from HTML instead of a URL?
The API can render provided HTML. Do not include both html and url in the same request; follow the request schema in the [Screenshot API reference](https://docs.browserless.io/rest-apis/screenshot-api).
How do I confirm the result is really an image?
Check the HTTP status before writing the response and inspect the saved file. For production jobs, validate the image output rather than assuming every successful request produced the intended page.


