How to Take a Screenshot with the Browshot API: Python Guide
Use Browshot’s Python client to capture a page, save its PNG, and handle asynchronous jobs, rendering options, errors, and API limits.
To take a screenshot with Browshot in Python, install its client, initialize BrowshotClient with your API key, and call simple() with the page URL and an instance_id. The simple API waits for the capture to finish and returns PNG bytes when successful. For workflows that need explicit job status and polling, use the complete API: create a screenshot, check its status, then retrieve the image.
The examples below use Browshot’s documented Python client and API behavior. See the Browshot Python library documentation and Browshot API documentation for current details. API limits and account terms can change, so check Browshot’s live documentation before relying on them.
1. Install the client and prepare your API key
Install the Browshot Python package in your project environment:
python -m pip install browshot
Set your API key in an environment variable rather than committing it to source control. For example, in a Unix-like shell:
export BROWSHOT_API_KEY='your_api_key'
Use the instance ID available to your account. Browshot’s documentation currently identifies instance 12 as the default free instance and states a limit of 100 free screenshots per month. Treat that quota and instance availability as time-sensitive; verify them in Browshot’s current documentation and account before building around them.
2. Capture one screenshot with Python
This minimal script calls the blocking simple API and writes the returned PNG bytes to screenshot.png. It checks the response code before writing, so an error response is not saved as if it were an image.
import os
from browshot import BrowshotClient
api_key = os.environ["BROWSHOT_API_KEY"]
client = BrowshotClient(api_key)
result = client.simple(
"https://example.com/",
{"instance_id": 12},
)
if int(result["code"]) == 200:
with open("screenshot.png", "wb") as image_file:
image_file.write(result["png"])
print("Saved screenshot.png")
else:
print(f"Screenshot failed with code {result['code']}")
The client’s documented simple call blocks until the capture succeeds or fails. The library documentation notes that the failure reason is sent in the HTTP X-Error header but is not exposed by this wrapper. If you need that header, use a direct HTTP request or a complete-API flow where you can inspect returned error details.
3. Use the complete API when you need job status
The complete API separates job creation from status checks and image retrieval. This is useful when you want to record the job ID, report progress, or control how long your application waits. The following script uses bounded polling: it stops when Browshot reports finished or error, and it also exits after a local deadline instead of polling forever.
import os
import time
from browshot import BrowshotClient
client = BrowshotClient(os.environ["BROWSHOT_API_KEY"])
job = client.screenshot_create(
"https://example.com/",
{"instance_id": 12, "size": "screen"},
)
if job.get("status") == "error":
raise RuntimeError(f"Browshot could not create the job: {job.get('error', 'unknown error')}")
screenshot_id = job["id"]
deadline = time.monotonic() + 180
while job.get("status") not in {"finished", "error"}:
if time.monotonic() >= deadline:
raise TimeoutError(f"Browshot job {screenshot_id} did not finish before the local deadline")
time.sleep(5)
job = client.screenshot_info(screenshot_id)
if job["status"] == "error":
raise RuntimeError(f"Browshot capture failed: {job.get('error', 'unknown error')}")
image_bytes = client.screenshot_thumbnail(screenshot_id)
with open("screenshot.png", "wb") as image_file:
image_file.write(image_bytes)
print("Saved screenshot.png")
The library example retrieves a thumbnail with screenshot_thumbnail(). If you need a specific thumbnail size or a file-writing helper, consult the client documentation for screenshot_thumbnail_file() and its supported arguments. A thumbnail is not necessarily the same output dimensions as the original full screenshot.
4. Make a direct request with cURL
The simple endpoint returns the image body on success. Use -L so cURL follows Browshot’s documented 302/307 redirects, which can be used while a capture is still processing.
curl -L --get "https://api.browshot.com/api/v1/simple" \
--data-urlencode "url=https://example.com/" \
--data "instance_id=12" \
--data-urlencode "key=$BROWSHOT_API_KEY" \
--output screenshot.png
For scripts, also capture the HTTP status and response headers so you can distinguish an image from an error response. A 404 body can be Browshot’s default not-found image, rather than the requested page screenshot.
5. Make a direct request with Python requests
A direct HTTP client gives you access to the response headers, including X-Error. Requests follows redirects by default for GET requests. The timeout below is a client-side limit; choose one that fits your application, since Browshot says some pages may take up to two minutes to load.
import os
import requests
response = requests.get(
"https://api.browshot.com/api/v1/simple",
params={
"url": "https://example.com/",
"instance_id": 12,
"key": os.environ["BROWSHOT_API_KEY"],
},
timeout=(10, 180),
allow_redirects=True,
)
if response.status_code != 200:
detail = response.headers.get("X-Error", response.text[:500])
raise RuntimeError(f"Browshot returned HTTP {response.status_code}: {detail}")
with open("screenshot.png", "wb") as image_file:
image_file.write(response.content)
For large images or high-volume workloads, stream the response to disk rather than keeping all bytes in memory. Validate the final response status and content before treating the file as a screenshot.
6. Make a direct request with Node.js
This example uses the built-in fetch available in modern Node.js. It follows redirects by default, checks the final status, and writes the response bytes to a file.
import { writeFile } from "node:fs/promises";
const apiKey = process.env.BROWSHOT_API_KEY;
if (!apiKey) throw new Error("Set BROWSHOT_API_KEY first");
const params = new URLSearchParams({
url: "https://example.com/",
instance_id: "12",
key: apiKey,
});
const response = await fetch(
`https://api.browshot.com/api/v1/simple?${params}`,
{ signal: AbortSignal.timeout(180_000) },
);
if (!response.ok) {
const detail = response.headers.get("X-Error") ?? await response.text();
throw new Error(`Browshot returned HTTP ${response.status}: ${detail}`);
}
await writeFile("screenshot.png", Buffer.from(await response.arrayBuffer()));
console.log("Saved screenshot.png");
7. Choose the capture size and rendering options
The API accepts url and instance_id for screenshot creation. The available rendering options depend on the selected instance or browser; check current API documentation before assuming a parameter works for every instance.
| Option | Purpose and notes |
|---|---|
size |
screen captures the visible browser screen; page requests a full-page capture. Screen is the documented default. |
screen_width, screen_height |
Set desktop browser dimensions where supported. The documentation gives bounds of 1–5000 pixels wide and 1–10000 pixels high; full-page height is documented up to 15,000 pixels. |
delay |
Wait after page load to allow JavaScript to run. The API documentation describes a default of 5 seconds and a supported range up to 120 seconds; a simple API page extract gives a narrower range, so verify the live endpoint and selected instance. |
cache |
Reuse a prior screenshot for the same URL and instance within the configured number of seconds. The documented default is 24 hours; set cache=0 to request a fresh capture. |
width, height |
Request a resized thumbnail, such as 640×480, where supported. This changes the output thumbnail dimensions, not the browser viewport. |
target |
Select a CSS target for a focused capture, where supported by the chosen browser. |
| Custom headers, JavaScript, popup hiding, dark mode, strict SSL | Additional documented controls, with browser and instance support varying. Consult the API page for exact parameter names and compatibility. |
| Rendered HTML | The API can save rendered HTML as an additional feature; Browshot’s documentation says this costs one credit per screenshot. |
| Hosting options | The API documents Browshot or S3 hosting and optional thumbnail dimensions. S3 requires a bucket; hosting behavior and permissions should be checked in the current API reference. |
Use size="screen" when you need a viewport capture and size="page" when you need the whole page. Full-page captures can be much taller and larger. If a page renders content only after interaction or a long delay, adjust the supported delay or use the complete API to manage waiting and retries.
8. Understand simple versus complete API
| Need | Simple API | Complete API |
|---|---|---|
| One image with little orchestration | Best starting point: one blocking library call returns the image or failure. | More steps than needed for a small script. |
| Track job progress | The wrapper hides the job lifecycle. | Create the job, inspect status, and retrieve output after completion. |
| Handle slow captures | Allow for redirects in raw HTTP use and set an appropriate client timeout. | Poll status with a bounded wait; some pages may take up to two minutes. |
| Control and error detail | Simple wrapper does not expose the documented X-Error header. |
Job status and error details are available through the API flow. |
Browshot describes the simple API as easier to use but slower than the complete API. The documentation does not provide a quantified speed benchmark, so treat that as a qualitative comparison rather than a guaranteed timing difference.
9. Troubleshoot common failures
| Symptom | Likely cause | What to do |
|---|---|---|
| HTTP 400 | Invalid API key, malformed URL, or invalid request parameter. | Check the key, URL encoding, required url and instance_id, and option values. Read the X-Error header when using raw HTTP. |
| HTTP 404 from the simple endpoint | The page could not be captured, for example because it did not load or its domain was unreachable. | Inspect X-Error; check that the URL is publicly reachable and try a suitable instance. Do not save the response body as a valid screenshot. |
| HTTP 302 or 307 | The capture is still processing and Browshot is redirecting the client. | Follow redirects in direct HTTP clients. With cURL, use -L. For a controlled workflow, use the complete API and poll the job. |
Complete API status is in_process |
The capture has not finished yet. | Wait and call screenshot_info() again. Use a bounded deadline and report a timeout instead of polling forever. |
Complete API status is error |
The capture failed or the request was rejected. | Report Browshot’s error detail and correct the URL, instance, or account issue before retrying. |
| “Not enough credits” | The selected private or shared instance requires a positive balance, or the account lacks credits for the request. | Check the account balance and instance requirements. The free-instance quota and credit rules may change; verify them in the account. |
| Image looks blank or misses late content | Page scripts or deferred content had not rendered before capture, or the selected instance does not support the needed behavior. | Increase the supported post-load delay, confirm the instance’s browser capabilities, and test a screen-sized capture before requesting a very tall page. |
| Saved file is not a PNG | An error response or redirect page was written to disk as if it were image data. | Check final HTTP status, follow redirects, inspect error headers, and only write the body after confirming success. |
| Python says the package or method is missing | The package was installed into a different interpreter environment, or the installed version differs from the documentation. | Run python -m pip install browshot with the same Python executable used to run the script, then check the current library documentation for method availability. |
10. Performance, reliability, and cost
- Set realistic timeouts. Browshot says some pages may take up to two minutes to load. Set HTTP timeouts to cover your use case, but use bounded polling and surface a clear timeout to callers.
- Use caching intentionally. The documented default cache duration is 24 hours; setting
cache=0requests a fresh result. Reusing cached captures can avoid unnecessary repeat work, while freshness-sensitive pages need a shorter cache or no cache. - Keep concurrency bounded. For multiple captures, control the number of jobs you create and poll. This limits resource use and helps your application avoid flooding itself with status requests.
- Plan for variable completion times. The service uses redirects for captures still processing, and the complete API exposes states such as
in_process,finished, anderror. Do not assume a fixed completion time. - Check which instance you use. The documentation says requests to private and shared instances require a positive balance. Instance support and per-capture credit requirements can differ.
- Verify quotas and account terms. Browshot’s current API documentation states 100 free screenshots per month for free instance 12. This limit is time-sensitive and should be confirmed before estimating production cost.
- Protect credentials and output. Keep the key out of source control and logs. If screenshots contain private or authenticated content, handle saved files and any hosting configuration according to your access requirements.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. It can return an image or PDF from one GET request, so you do not need to install or poll a browser capture client for the basic workflow. See the ScreenshotNeo API documentation for parameters and formats.
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)
ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up free and capture your first 1,000 screenshots a month without a card.
FAQ
Does the Browshot Python client return PNG data or a filename?
simple() returns a response mapping that includes PNG bytes on success. The library also documents simple_file() for saving directly to a file.
Can I request only part of a page?
The API documents a CSS target option for selecting content, subject to support in the chosen browser or instance. Check the current parameter reference for its exact behavior.
Can I request a screenshot for every URL in one API call?
The complete API documents a multiple-screenshot endpoint that accepts multiple URLs and instance IDs, up to 10 of each per request. See the current API reference for request encoding and limits.
Where can I see Browshot’s current instances?
Use Browshot’s instance API and account documentation to check available instances, browser capabilities, and costs before choosing an instance for a workflow.


