How to Use Browshot with Node.js and Fetch Screenshots by URL
Install Browshot’s Node.js package, capture a URL with the simple API, or create, poll, and download a screenshot with the full API.
Browshot’s Node.js package can capture a screenshot from a URL in two ways: use client.simple() for a straightforward download, or use the full API to create a screenshot, check its status, and retrieve the image when it is ready. The simple API takes less code; Browshot describes it as easier but slower than the complete API. This guide uses the CommonJS syntax shown in Browshot’s Node.js examples.
1. Install Browshot and provide your API key
Use Node.js and npm, then install the browshot package:
npm init -y
npm install browshot
Set the API key in your environment rather than placing a real credential in source code. On macOS or Linux:
export BROWSHOT_API_KEY='YOUR_API_KEY'
In PowerShell:
$env:BROWSHOT_API_KEY = 'YOUR_API_KEY'
Get your own key from Browshot. Keep it out of committed files and logs.
2. Capture a URL with the simple API
For a single URL and a file download, client.simple() is the shortest route. This complete CommonJS script checks the result code and writes the returned image bytes to screenshot.png:
'use strict';
const Browshot = require('browshot');
const fs = require('node:fs');
const apiKey = process.env.BROWSHOT_API_KEY;
if (!apiKey) {
throw new Error('Set BROWSHOT_API_KEY before running this script.');
}
const client = new Browshot(apiKey);
client.simple({ url: 'https://example.com/' }, (result) => {
if (!result || result.code !== 200) {
console.error('Screenshot failed. Browshot response code:', result && result.code);
process.exitCode = 1;
return;
}
fs.writeFile('screenshot.png', result.data, (err) => {
if (err) {
console.error('Could not save screenshot:', err);
process.exitCode = 1;
return;
}
console.log('Saved screenshot.png');
});
});
Save this as screenshot.js and run node screenshot.js. The image data is written as received; use a filename and extension that match the image format returned for your request. The package’s callback result does not expose the X-Error explanation described by the API, so if a request fails you may need to inspect the response or use the full API for more control.
3. Create, poll, and download with the full API
Choose the full workflow when you need to select an instance, choose screen or full-page capture, or control retrieval after processing. The sequence is: create a screenshot, inspect the returned status, poll while it is in progress, then retrieve the screenshot or a thumbnail. Browshot documents screenshotCreate and screenshotInfo; its Node.js library page shows the download flow.
const screenshot = await client.screenshotCreate({
url: 'https://example.com/',
instance_id: 12,
size: 'page'
});
if (screenshot.status === 'in_process') {
// Call client.screenshotInfo(screenshot.id, {}) until status is
// 'finished' or 'error', then retrieve the screenshot or thumbnail.
}
The API is callback-based in Browshot’s CommonJS examples. Keep the library’s callback pattern for your installed package version; the promise-style presentation above only shows the sequence and option names. A callback-shaped polling outline is:
client.screenshotCreate(
{ url: 'https://example.com/', instance_id: 12, size: 'page' },
(created) => {
if (!created || !created.id) {
console.error('Could not create screenshot');
return;
}
function checkStatus() {
client.screenshotInfo(created.id, {}, (info) => {
if (info.status === 'finished') {
// Use the library's documented screenshot or thumbnail download
// method for this screenshot ID, then save the returned bytes.
console.log('Screenshot is ready:', created.id);
return;
}
if (info.status === 'error') {
console.error('Browshot could not capture the URL');
return;
}
if (info.status === 'in_process') {
setTimeout(checkStatus, 1500);
return;
}
console.error('Unexpected screenshot status:', info.status);
});
}
if (created.status === 'finished') {
console.log('Screenshot is ready:', created.id);
} else if (created.status === 'error') {
console.error('Browshot could not capture the URL');
} else if (created.status === 'in_process') {
checkStatus();
}
}
);
Use the download method and callback signature documented for the installed Browshot Node.js library to retrieve the final file. Treat finished and error as terminal states; do not assume every create request is immediately downloadable. The API reference covers the create, info, thumbnail, and screenshot endpoints: Browshot API documentation.
4. Choose the screenshot options
| Option | What it controls | Practical guidance |
|---|---|---|
url |
Required target page URL. | Pass a complete URL with scheme, such as https://example.com/. |
instance_id |
The Browshot browser instance used to capture the page. | Select an instance appropriate to the device/browser you need. Some shared or private instances require a positive account balance. |
size |
screen captures the viewport; page requests a full-page image. The default is screen. |
Use page for a whole-document capture. Long pages can produce larger files and take longer. |
cache |
Reuse a screenshot of the same URL on the same instance within the configured interval. The documented default is 24 hours. | Set cache: 0 when you need a fresh capture rather than a reusable result. |
delay |
Extra seconds to wait after the page loads so JavaScript can run. The documentation has version/instance-specific ranges; consult the API page for the selected instance. | Increase it for content that appears after initial load; keep it low when speed matters and the page is already stable. |
| Dimensions and thumbnails | Screen width and height configure desktop viewport dimensions; thumbnail parameters control a smaller returned image. | Check documented limits and instance compatibility before requesting custom sizes. |
For options beyond these common settings, including additional browser behavior, see the official parameter reference. It is the source of truth for parameters supported by the instance and API version you use.
5. Handle redirects, processing, and errors
The simple endpoint uses response codes. Browshot documents 200 for image data, 404 when screenshot execution fails, 400 for an invalid request, and 302 when processing is still underway. Callers must follow 302 and 307 redirects; some pages can take up to two minutes to load. With the full API, check status and continue polling only while it is in_process.
| Symptom | Likely cause | What to do |
|---|---|---|
| HTTP 400 or request rejected | Malformed request or missing/invalid required parameter, often the URL or instance. | Check the URL includes https://, confirm the instance ID, and review the API parameter names. |
HTTP 404 or status error |
The screenshot job failed while loading or executing the page. | Verify the page is reachable, retry later, and inspect the API response for its error details. The simple Node.js result may not include the X-Error explanation. |
| HTTP 302/307 or status remains in progress | The page is still rendering, or a redirect is part of the retrieval flow. | Follow the redirect for the simple endpoint. For the full API, poll screenshotInfo at a measured interval and stop on finished or error. |
| Screenshot is blank or misses content | The site may render content asynchronously or require additional time after load. | Try an appropriate delay, confirm the chosen page and instance, and inspect whether the content is visible in that browser context. |
| File is missing or zero bytes | The result was not a successful image response, or the local write failed. | Check result.code before writing, handle the filesystem callback error, and use the full workflow when you need explicit status checks. |
| Authentication or balance error | The API key is absent/incorrect or the selected shared/private instance requires available balance. | Load the intended key from the environment, confirm account access, and review the instance and current account terms. |
6. Performance, reliability, and cost
- Latency: The simple API is easier but documented as slower than the complete API. Use the full flow when you want to track progress and fetch the result separately.
- Waits: A larger rendering delay can capture late JavaScript content, but adds time. A delay of zero is faster when the page needs no extra render time; the available range depends on API/instance documentation.
- Polling: Use a modest interval and a maximum elapsed-time policy in production. Record the screenshot ID and terminal status so a process restart does not cause you to mistake an unfinished job for a failed one.
- Caching: Browshot’s cache can reuse a capture for the same URL and instance within its interval, documented as 24 hours by default. Disable it with
cache: 0when fresh page state matters. - Cost: Browshot’s API documentation states that the default free instance is limited to 100 screenshots per month. Paid instances use credits, with usage varying by instance and capture type. Check the current features and pricing page before estimating a production budget.
7. cURL, Python, and Node.js alternatives with ScreenshotNeo
If you want the same URL-to-image workflow without managing a browser instance and status polling, ScreenshotNeo provides a screenshot API and MCP server. Its documented API supports PNG, JPEG, WebP, and PDF output, along with full-page capture, viewport and device options, custom waits, caching, and other capture settings. See the ScreenshotNeo API documentation for parameters.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python
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()
with open("shot.webp", "wb") as output:
output.write(r.content)
Node.js
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(`ScreenshotNeo returned HTTP ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) =>
writeFile('shot.webp', Buffer.from(await res.arrayBuffer()))
);
Replace YOUR_API_KEY with your ScreenshotNeo key. The examples save the response as WebP; choose the matching output format when configuring a different format.
Or skip the browser setup
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks/CAPTCHAs, blank pages, failed loads, timeouts, and cache hits are not billed, and responses include X-Page-Verdict and X-Billed headers. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
Frequently asked questions
Does Browshot capture the URL in my Node.js process?
No. Your Node.js code sends a request to Browshot; Browshot’s service runs the browser capture and returns or exposes the screenshot result.
Should I use simple() or the full API?
Use simple() for the shortest single capture flow. Use the full API when selecting an instance or size and when you need to track processing and retrieval explicitly.
Can I use this package from an ES module project?
The cited Browshot examples use CommonJS. If your project uses ES modules, adapt the import according to your Node.js/package configuration and verify it against the installed package.
How many free Browshot screenshots are included?
The cited API documentation states 100 per month for the default free instance. Verify the current terms on Browshot’s official pages before planning usage.


