ScreenshotNeo

BlogHow-to

How to Download and Share BrowserStack Screenshots Results

Share BrowserStack Screenshots results with a job link, reopen completed sessions from History, and retrieve image files through the Screenshots API.

By the ScreenshotNeo team4 October 20268 min read

To share BrowserStack Screenshots results, click Generate Screenshots and copy the resulting URL. BrowserStack updates that URL with a unique job ID for the session; collaborators opening it can see the results, including a processing state if generation is still underway. To retrieve the image files programmatically, request the job’s JSON result and download the returned image_url values. BrowserStack’s reviewed support material does not confirm a dedicated download button in the Screenshots interface, so use the API route when you need the actual files. BrowserStack explains sharing by job URL, and its Screenshots API documentation describes result retrieval.

Share a Screenshots session

  1. Open BrowserStack Screenshots and enter the page URL and the browser or device configurations you need.
  2. Click Generate Screenshots.
  3. Copy the updated address-bar URL. It contains a unique job ID for that screenshot session.
  4. Send the URL to collaborators. If the screenshots are still rendering when they open it, they can see the processing state.

This link is the documented sharing method. It points to the session results; it is not a direct image-file URL.

Reopen completed results

If you leave the results page and return later, check the History dropdown in the URL bar. BrowserStack Support says completed Screenshots are available there. The history route is useful for finding a past session; use the API below if your goal is to download the underlying image files.

Retrieve and download screenshot images with the API

The Screenshots API returns job result data, including an image_url for each completed screenshot. The basic workflow is: obtain the job ID from the generated results URL, authenticate the API request using the credentials required by your BrowserStack account, inspect the JSON response, then download each image URL.

BrowserStack’s API is available to Automate plans that include browsers. Live-only subscribers can use Screenshots through the webpage. Check the current API reference for the endpoint’s authentication requirements, response schema, and account access details.

cURL: request the job result

curl --user "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
  "https://www.browserstack.com/screenshots/<JOB-ID>.json"

Replace <JOB-ID> with the ID from the generated session URL. Supply credentials according to BrowserStack’s current API documentation. The example uses environment variables so credentials are not embedded in a script or committed to source control.

Python: fetch the JSON and save the images

import os
from pathlib import Path
from urllib.parse import urlparse

import requests

username = os.environ["BROWSERSTACK_USERNAME"]
access_key = os.environ["BROWSERSTACK_ACCESS_KEY"]
job_id = os.environ["BROWSERSTACK_JOB_ID"]
result_url = f"https://www.browserstack.com/screenshots/{job_id}.json"

response = requests.get(
    result_url,
    auth=(username, access_key),
    timeout=60,
)
response.raise_for_status()
result = response.json()

# Confirm the response structure against the current API schema.
# The API returns image_url values for completed screenshot results.
def find_image_urls(value):
    if isinstance(value, dict):
        for key, item in value.items():
            if key == "image_url" and isinstance(item, str):
                yield item
            else:
                yield from find_image_urls(item)
    elif isinstance(value, list):
        for item in value:
            yield from find_image_urls(item)

image_urls = list(dict.fromkeys(find_image_urls(result)))
if not image_urls:
    raise RuntimeError("No image_url values found; check job status and API response.")

output_dir = Path("browserstack-screenshots")
output_dir.mkdir(parents=True, exist_ok=True)

for index, image_url in enumerate(image_urls, start=1):
    image_response = requests.get(image_url, timeout=60)
    image_response.raise_for_status()
    suffix = Path(urlparse(image_url).path).suffix or ".png"
    (output_dir / f"screenshot-{index}{suffix}").write_bytes(image_response.content)
    print(f"Saved screenshot-{index}{suffix}")

Install the dependency with python -m pip install requests. The recursive extraction accommodates nested result data, but always validate the response against the API schema for your account and API version. The image URLs are retrieved separately from the authenticated job response.

Node.js: fetch the JSON and save the images

import { mkdir, writeFile } from 'node:fs/promises';
import { extname } from 'node:path';

const username = process.env.BROWSERSTACK_USERNAME;
const accessKey = process.env.BROWSERSTACK_ACCESS_KEY;
const jobId = process.env.BROWSERSTACK_JOB_ID;
if (!username || !accessKey || !jobId) {
  throw new Error('Set BROWSERSTACK_USERNAME, BROWSERSTACK_ACCESS_KEY, and BROWSERSTACK_JOB_ID.');
}

const credentials = Buffer.from(`${username}:${accessKey}`).toString('base64');
const resultUrl = `https://www.browserstack.com/screenshots/${encodeURIComponent(jobId)}.json`;
const resultResponse = await fetch(resultUrl, {
  headers: { Authorization: `Basic ${credentials}` },
  signal: AbortSignal.timeout(60_000),
});
if (!resultResponse.ok) {
  throw new Error(`Result request failed: ${resultResponse.status} ${resultResponse.statusText}`);
}
const result = await resultResponse.json();

function collectImageUrls(value, found = []) {
  if (Array.isArray(value)) {
    for (const item of value) collectImageUrls(item, found);
  } else if (value && typeof value === 'object') {
    for (const [key, item] of Object.entries(value)) {
      if (key === 'image_url' && typeof item === 'string') found.push(item);
      else collectImageUrls(item, found);
    }
  }
  return found;
}

const imageUrls = [...new Set(collectImageUrls(result))];
if (imageUrls.length === 0) {
  throw new Error('No image_url values found; check job status and API response.');
}

await mkdir('browserstack-screenshots', { recursive: true });
for (const [index, imageUrl] of imageUrls.entries()) {
  const imageResponse = await fetch(imageUrl, { signal: AbortSignal.timeout(60_000) });
  if (!imageResponse.ok) {
    throw new Error(`Image ${index + 1} download failed: ${imageResponse.status}`);
  }
  const extension = extname(new URL(imageUrl).pathname) || '.png';
  const filename = `browserstack-screenshots/screenshot-${index + 1}${extension}`;
  await writeFile(filename, Buffer.from(await imageResponse.arrayBuffer()));
  console.log(`Saved ${filename}`);
}

This example uses the built-in fetch available in current Node.js releases. Confirm the authentication scheme and response shape against the BrowserStack API reference for your account.

Save one image URL with cURL

Once you have copied an image_url from the job response, download that resource directly:

curl --fail --location "<IMAGE_URL>" --output screenshot.png

Use the actual URL returned by the API. Do not assume that the job JSON endpoint itself returns image bytes; it returns result data containing image URLs.

Keep Screenshots separate from Automate Visual Logs

BrowserStack Screenshots creates a screenshot session that can be shared by its job URL. Automate Visual Logs are a different workflow: their screenshots appear in the Automate dashboard. To save a Visual Logs screenshot to your local machine, capture it in the test script and save it there. Do not use the Screenshots job ID workflow as if it were the Visual Logs download mechanism. BrowserStack documents Visual Logs separately.

Troubleshooting

Symptom Likely cause What to do
The shared link shows processing. The screenshot job has not finished rendering. Wait for completion and reopen the same session URL. Recipients can also see processing while the job runs.
You cannot find an old result. You opened a fresh session or no longer have the result URL at hand. Check the URL bar’s History dropdown for completed screenshots.
The API request is unauthorized. Credentials are missing, incorrect, or sent using an authentication method that does not match the current API requirements. Check the account’s Automate access and the current API reference. Keep credentials in environment variables and send them as documented.
The API request returns an error or no useful result. The job ID may be wrong, the session may still be processing, or the account may not include API access. Copy the ID from the generated session URL, confirm the job is complete, and verify plan eligibility in BrowserStack’s documentation.
The script finds no image_url. The result may not be complete, or the response schema may differ from the assumed shape. Inspect the JSON response, wait for completion, and adapt extraction to the documented response schema. Avoid assuming a fixed browser configuration or stale example schema.
The image download returns an error. The URL may be incomplete, expired, or not directly accessible in the current context. Copy the full returned URL, check the HTTP status, and use any access requirements documented for that image resource.
You see dashboard screenshots but cannot find a Screenshots job link. You may be looking at Automate Visual Logs. Use the test’s explicit screenshot capture and save flow for local files; Visual Logs and Screenshots are separate products/workflows.

Performance, reliability, and cost considerations

  • Wait for completion: sharing the URL before rendering finishes is supported, but recipients initially see a processing state. For handoffs that need finished images immediately, wait for completion first.
  • Download images independently: the result JSON provides image URLs, so scripts should check the result request and each image request separately. Use timeouts and surface failed HTTP statuses instead of writing error responses as image files.
  • Plan for schema changes: use the current API reference rather than copying old example browser configurations or assuming an undocumented response layout.
  • Check plan access and account pricing: API availability described in the reviewed material is tied to Automate plans that include browsers. Pricing and included capacity depend on the account and should be checked with BrowserStack.
  • Protect credentials: do not place access keys in shared URLs, client-side code, or checked-in scripts. Use a server-side environment or secret manager.

Or skip the browser setup

For a fresh screenshot of a URL, ScreenshotNeo provides a website screenshot API and MCP server. See the API documentation. One GET request returns an image or PDF:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. 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 for free.

FAQ

Can I share results while screenshots are still generating?

Yes. BrowserStack says recipients opening the session URL during generation can see its processing state.

Does the Screenshots page have a download button?

The official support material reviewed confirms URL sharing, History, and API image URLs, but does not confirm a current GUI download control. Use the API image URLs when you need files.

Can a Live-only subscriber retrieve results with the API?

The reviewed BrowserStack API documentation ties API access to Automate plans that include browsers. Live-only subscribers can use the Screenshots webpage.

Are Automate Visual Logs the same as Screenshots results?

No. Visual Logs are shown in the Automate dashboard; local copies require screenshot capture and saving in the test script.