How to automate website screenshots with the LambdaTest Screenshot API
Automate hosted cross-browser screenshots with LambdaTest: discover supported environments, submit a test, and retrieve its status and image URLs.
To automate website screenshots with the LambdaTest Screenshot API, discover the currently supported browser and resolution options, submit a JSON test request with HTTP Basic authentication, save the returned test_id, and fetch that test’s status and screenshot details. The API runs captures on LambdaTest’s cloud servers, so you can request screenshots across browser and operating system configurations without managing those browsers locally.
This guide covers the documented workflow and request fields. Browser inventories, resolutions, schemas, account limits, and service behavior can change; check the official Automated Screenshot API guide and API references before deploying an integration.
1. Prepare API credentials
The API uses HTTP Basic authentication with your LambdaTest (also referred to in the guide as TestMu AI) username and access key. Create or locate these credentials in your account, then keep them outside source control. The examples below read them from environment variables.
export LAMBDATEST_USERNAME="your_username"
export LAMBDATEST_ACCESS_KEY="your_access_key"
Do not commit a populated .env file or paste credentials into client-side code. If a credential is exposed, rotate it through the account’s credential controls.
2. Discover supported browsers and resolutions
Before building a matrix, query the guide’s documented OS/browser availability and resolution endpoints. Use the current response as the source of truth: examples in older documentation may show versions that are no longer available. Keep the returned values and the date you fetched them with your integration configuration if you need to audit changes later.
Choose operating systems, browser families and versions, and resolutions based on the users and layouts you need to cover. The API’s response includes these dimensions, which makes it possible to confirm what actually ran. There is no universally correct matrix; select it using your audience and product requirements rather than copying an old example.
3. Submit a screenshot test
The documented start endpoint is POST https://api.lambdatest.com/screenshots/v1/. Send JSON with the target URL and a configs matrix built from currently supported values. A successful start response includes a test_id, which you must retain to retrieve results.
The following Python example uses requests. Replace the illustrative configuration entries with exact values from the live inventory before running it; the old examples in documentation should not be assumed current.
import json
import os
import requests
username = os.environ["LAMBDATEST_USERNAME"]
access_key = os.environ["LAMBDATEST_ACCESS_KEY"]
payload = {
"url": "https://example.com",
"configs": [
{
"os": "REPLACE_WITH_SUPPORTED_OS",
"browser": "REPLACE_WITH_SUPPORTED_BROWSER",
"browser_version": "REPLACE_WITH_SUPPORTED_VERSION",
"resolution": "REPLACE_WITH_SUPPORTED_RESOLUTION"
}
]
}
response = requests.post(
"https://api.lambdatest.com/screenshots/v1/",
auth=(username, access_key),
json=payload,
timeout=60,
)
response.raise_for_status()
result = response.json()
test_id = result["test_id"]
print("Started test:", test_id)
print(json.dumps(result, indent=2))
Install the dependency with python -m pip install requests. The response parsing deliberately fails if the API does not return the expected test ID, rather than silently continuing with an invalid identifier.
Request fields
The API reference documents these request fields. Include only the options your workflow needs, and confirm exact accepted values and required fields in the current reference.
| Field | Purpose | Practical note |
|---|---|---|
url |
Target page to capture. | Use a fully qualified URL accessible to the hosted capture environment. |
configs |
Browser and operating system configurations, including version and resolution in the documented examples. | Build from the live availability inventory. More configurations mean more requested captures. |
mac_res, win_res |
Resolution settings shown in the API reference. | Check current supported resolution values and how they relate to the chosen OS configuration. |
defer_time |
Defers capture according to the API’s documented behavior. | Use only when the page needs additional time before capture; verify units and allowed range in the current reference. |
email |
Email notification option. | Check the current schema for accepted values and notification behavior. |
callback_url |
Callback URL option for completion notification. | Make the endpoint reachable by the service and validate incoming requests as described by current documentation. |
tunnel, tunnel_identifier |
Tunnel settings for a target that is not publicly reachable. | Configure the corresponding tunnel as required by LambdaTest’s current tunnel instructions. |
username, password |
Credentials for a target site requiring HTTP Basic authentication. | These authenticate to the target page, distinct from the API Basic authentication credentials. |
Do not assume every field is required or that the illustrative matrix keys above are accepted unchanged. The live API reference defines the current schema.
4. Fetch test status and screenshot metadata
Once you have the ID, retrieve the test details with GET /screenshots/v1/{test_id}. The documented response includes test_status and a screenshots array. Screenshot records can include operating system, browser, browser version, individual status, screenshot URL, thumbnail URL, activity ID, and resolution.
import os
import requests
username = os.environ["LAMBDATEST_USERNAME"]
access_key = os.environ["LAMBDATEST_ACCESS_KEY"]
test_id = "YOUR_TEST_ID"
response = requests.get(
f"https://api.lambdatest.com/screenshots/v1/{test_id}",
auth=(username, access_key),
timeout=60,
)
response.raise_for_status()
result = response.json()
print("Test status:", result.get("test_status"))
for shot in result.get("screenshots", []):
print({
"os": shot.get("os"),
"browser": shot.get("browser"),
"browser_version": shot.get("browser_version"),
"status": shot.get("status"),
"resolution": shot.get("resolution"),
"screenshot_url": shot.get("screenshot_url"),
"thumbnail_url": shot.get("thumbnail_url"),
"activity_id": shot.get("activity_id"),
})
The API reference describes fetching a test’s details; if the response says the run is still in progress, request its details again according to your application’s polling policy. Avoid tight polling loops. Use the callback option where it fits your workflow and confirm its current delivery semantics in the docs.
5. Make the request with cURL
cURL is useful for a one-off request or to inspect the API response from a shell. This example passes the username and access key for Basic authentication via environment variables and submits a minimal configuration. Replace the configuration placeholders with values discovered from the current inventory.
curl --fail-with-body --silent --show-error \
--user "$LAMBDATEST_USERNAME:$LAMBDATEST_ACCESS_KEY" \
--header 'Content-Type: application/json' \
--data '{
"url": "https://example.com",
"configs": [
{
"os": "REPLACE_WITH_SUPPORTED_OS",
"browser": "REPLACE_WITH_SUPPORTED_BROWSER",
"browser_version": "REPLACE_WITH_SUPPORTED_VERSION",
"resolution": "REPLACE_WITH_SUPPORTED_RESOLUTION"
}
]
}' \
'https://api.lambdatest.com/screenshots/v1/'
Save the returned test_id. To retrieve the outcome:
curl --fail-with-body --silent --show-error \
--user "$LAMBDATEST_USERNAME:$LAMBDATEST_ACCESS_KEY" \
"https://api.lambdatest.com/screenshots/v1/YOUR_TEST_ID"
6. Make the request with Node.js
This Node.js example uses the built-in fetch API available in modern Node.js releases. It sends Basic auth and checks HTTP status before reading JSON.
const username = process.env.LAMBDATEST_USERNAME;
const accessKey = process.env.LAMBDATEST_ACCESS_KEY;
if (!username || !accessKey) {
throw new Error('Set LAMBDATEST_USERNAME and LAMBDATEST_ACCESS_KEY');
}
const auth = Buffer.from(`${username}:${accessKey}`).toString('base64');
const payload = {
url: 'https://example.com',
configs: [
{
os: 'REPLACE_WITH_SUPPORTED_OS',
browser: 'REPLACE_WITH_SUPPORTED_BROWSER',
browser_version: 'REPLACE_WITH_SUPPORTED_VERSION',
resolution: 'REPLACE_WITH_SUPPORTED_RESOLUTION'
}
]
};
const start = await fetch('https://api.lambdatest.com/screenshots/v1/', {
method: 'POST',
headers: {
authorization: `Basic ${auth}`,
'content-type': 'application/json'
},
body: JSON.stringify(payload)
});
if (!start.ok) {
throw new Error(`Start failed: HTTP ${start.status} ${await start.text()}`);
}
const started = await start.json();
if (!started.test_id) throw new Error('Response did not include test_id');
console.log('Started test:', started.test_id);
const details = await fetch(
`https://api.lambdatest.com/screenshots/v1/${encodeURIComponent(started.test_id)}`,
{ headers: { authorization: `Basic ${auth}` } }
);
if (!details.ok) {
throw new Error(`Fetch failed: HTTP ${details.status} ${await details.text()}`);
}
console.log(JSON.stringify(await details.json(), null, 2));
The second request may arrive before all captures finish. In production, check the returned status and implement bounded polling or use the documented callback mechanism instead of assuming immediate completion.
7. Choose a useful capture matrix
- Start with a small representative set. Select the OS, browser families and versions, and resolutions that match your actual support requirements.
- Add coverage for meaningful differences. Include environments where layout, rendering, or supported browser behavior is likely to matter.
- Expand deliberately. The request supports multiple configurations; asking for more configurations increases the number of requested captures. This follows from the request structure, not a vendor benchmark or fixed runtime claim.
- Read the response per screenshot. Match each image URL and status to its reported OS, browser, version, and resolution before comparing images.
Keep the matrix maintainable by storing it as configuration and refreshing supported values from the service rather than scattering browser-version strings through application code.
8. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| HTTP 401 or 403 | Missing, incorrect, or unauthorized API credentials. | Check that both environment variables are set correctly, use HTTP Basic authentication, and confirm the account has API access. Do not confuse API credentials with target-site credentials. |
| Request rejected or configuration unavailable | An OS, browser version, or resolution is invalid or no longer supported. | Query the current inventory endpoints and replace stale values; validate the request against the current API schema. |
No test_id in the response |
The request did not start successfully or the response shape differs from the expected success response. | Inspect the HTTP status and response body before parsing. Do not attempt the details request until a successful response supplies an ID. |
| Details request returns an error | The ID is mistyped, unknown, or not associated with the authenticated account. | Use the exact ID from the start response and the same account credentials; inspect the full API error body. |
| Test is not complete yet | Hosted browser work is still running. | Use bounded polling with a delay between requests, or configure the documented callback URL and handle completion asynchronously. |
| Target page requires login | The capture service cannot access the page unauthenticated. | For a page using HTTP Basic authentication, use the documented target username and password fields. For other access patterns or private network pages, consult current tunnel and service documentation. |
| Private target is unreachable | The hosted browser cannot reach an internal address without the required tunnel setup. | Configure the documented tunnel options and matching tunnel identifier, following current LambdaTest tunnel instructions. |
| Some screenshots have an error status | A particular environment or target load failed even though the overall test was accepted. | Inspect each screenshot record’s status and environment dimensions. Retry only the affected configuration after checking URL reachability and current environment availability. |
9. Reliability, performance, and cost considerations
- Reliability: Persist the test ID as soon as the start request succeeds. Treat submission and completion as separate steps, inspect both the overall test status and per-screenshot statuses, and make retries bounded. Do not blindly resubmit after a client-side timeout until you determine whether the original request produced a test ID.
- Performance: Keep the matrix focused on required environments. Each additional configuration requests another capture, so broad matrices add work. Use a callback or measured polling interval instead of repeatedly requesting status in a tight loop.
- Target readiness: A hosted screenshot captures what the page renders under the configured workflow. If the page depends on delayed content or authentication, use the documented defer or target credential options where appropriate and verify the resulting images.
- Cost: The research sources do not establish current LambdaTest prices, quotas, or account limits. Check your account and current official pricing before estimating costs. Matrix size is a practical cost driver to verify against your plan, but no per-capture rate is asserted here.
- Retention and access: The details response provides image and thumbnail URLs. Follow current service documentation for their availability and handling; avoid exposing sensitive target content through public application pages.
Or skip the browser setup
If you need screenshots without assembling a cloud browser matrix, ScreenshotNeo is a website screenshot API and MCP server for developers. Its single GET request accepts a URL and returns PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation.
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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo accepts cookie banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers say the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account for 1,000 screenshots a month, with no card required.
FAQ
Does the API take screenshots on my machine?
No. The documented workflow starts a hosted screenshot test on LambdaTest cloud servers and returns results for retrieval by test ID.
Can one request cover multiple environments?
The guide shows a configuration matrix. Use the live supported-environment inventory to select its entries, then inspect each returned screenshot record.
Where do I get the image files?
Fetch the test details by ID and use the screenshot and thumbnail URLs in the returned screenshot records, subject to current service behavior.
Can I capture a page behind a login?
The reference documents username and password fields for target sites using HTTP Basic authentication. Tunnel options are also documented for tunnel-based access. Check current documentation for other authentication patterns.


