How to Capture a Website Screenshot with Browserless from a Google Sheet
Read a URL from Google Sheets, capture it with Browserless using Apps Script, and save the image to Drive. Includes full-page options, troubleshooting, and a no-code alternative.
To capture a website screenshot from a Google Sheet with Browserless, use a bound Google Apps Script to read a URL from a cell, POST that URL to Browserless’s Screenshot API, and save the returned image bytes as a Google Drive file. The script below uses a token stored in Script Properties and writes the new file’s URL back to the sheet.
How the workflow works
- Google Sheets stores the page URL, for example in
A2. - Apps Script reads the cell and sends an HTTPS request with
UrlFetchApp. - Browserless opens the page and returns screenshot image data.
- Google Drive can store that image as a file; the script can put its link in another cell.
This is a documented integration pattern, not a tested, ready-made deployment. You may need to adapt the sheet name, endpoint region, scopes, and waits to your account and target site.
Set up the spreadsheet and Browserless token
- Open the Google Sheet that will hold the URL. This example expects a tab named
Sheet1, the target URL inA2, and the output Drive link inB2. - In Browserless, obtain an API token from your account dashboard. The API passes it as the
tokenquery parameter. - From the sheet, open Extensions → Apps Script to create a script bound to the spreadsheet.
- In Apps Script, open Project Settings, find Script Properties, and add
BROWSERLESS_TOKENwith your token as its value. - Use the endpoint and region shown in your current Browserless account documentation. The documented example endpoint below uses the production SFO region.
Keep the token in Script Properties. Do not put it in a sheet cell, a shared script example, or a URL that other spreadsheet users can see.
Complete Apps Script example
Paste this into the bound script project. It reads A2, requests a full-page PNG, saves the response as a Drive file, and writes the file URL into B2.
function captureScreenshot() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
if (!sheet) throw new Error('Sheet1 was not found. Update the sheet name in the script.');
const targetUrl = String(sheet.getRange('A2').getValue()).trim();
if (!targetUrl) throw new Error('Enter a website URL in cell A2.');
if (!/^https?:\/\//i.test(targetUrl)) {
throw new Error('The URL in A2 must begin with http:// or https://.');
}
const token = PropertiesService.getScriptProperties().getProperty('BROWSERLESS_TOKEN');
if (!token) throw new Error('Set BROWSERLESS_TOKEN in Apps Script Script Properties.');
const endpoint = 'https://production-sfo.browserless.io/screenshot?token=' + encodeURIComponent(token);
const response = UrlFetchApp.fetch(endpoint, {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({
url: targetUrl,
options: { fullPage: true, type: 'png' }
}),
muteHttpExceptions: true
});
const status = response.getResponseCode();
if (status < 200 || status >= 300) {
throw new Error('Browserless request failed with HTTP ' + status + ': ' + response.getContentText());
}
const imageBlob = response.getBlob().setName('website-screenshot.png');
const file = DriveApp.createFile(imageBlob);
sheet.getRange('B2').setValue(file.getUrl());
}
Run captureScreenshot from the Apps Script editor once. Google will prompt for authorization to access the spreadsheet, make external requests, and create Drive files. The script uses SpreadsheetApp.getActiveSpreadsheet(), which is appropriate for a script bound to a Sheets file.
Apps Script may require the script.external_request scope for UrlFetchApp. Drive file creation also needs Drive authorization. If the project defines explicit OAuth scopes in its manifest, include the required scopes and reauthorize.
Choose screenshot options
Browserless accepts a POST to its /screenshot endpoint with a URL and optional screenshot options. The documented API supports PNG, JPEG, and WebP output, as well as full-page capture. Check the current Browserless API reference for the complete option set and any account-specific behavior.
| Need | Setting or choice | What to expect |
|---|---|---|
| Entire document | options.fullPage: true |
Captures the full page rather than just the current viewport. Very long pages can produce large images. |
| Visible screen only | Omit fullPage or set it to false |
Captures the viewport. Choose this when a fixed-size preview is the desired output. |
| PNG | options.type: 'png' |
Lossless output; useful when fine text or sharp edges matter. |
| JPEG | options.type: 'jpeg' |
Often useful when a smaller photographic image is preferred; check the API’s accepted type spelling for your account. |
| WebP | options.type: 'webp' |
Useful when the next system supports WebP and file size matters; verify downstream compatibility. |
| Delayed content | Use the documented wait or navigation options | Some sites render content after the initial page load. A wait may help, but adds time and cannot guarantee a site has finished updating. |
The example writes a PNG filename because its request asks for PNG. If you change the output type, change the file extension too. Some pages lazy-load images as you scroll or render content only after interaction; confirm that the chosen capture and wait behavior includes the content you need.
Save the image somewhere other than Drive
response.getBlob() exposes the returned image as a blob. The example uses DriveApp.createFile(blob) for persistent storage, then writes the Drive URL into the sheet. If you do not need a Drive file, you can instead process the blob in the script or send it to another destination supported by your workflow. Account for destination permissions and retention when sharing the resulting file.
To save results for multiple rows, loop over a bounded range, validate each URL, and record each outcome next to its input. Avoid an unbounded loop in a single execution: Apps Script executions have runtime and response-size limits, and each URL creates another external request.
cURL, Python, and Node.js reference calls
These examples show the same Browserless request shape outside Apps Script. They are useful for isolating API or token issues from spreadsheet authorization. Replace the placeholder with a private token and use the endpoint configured for your account.
cURL
curl -X POST 'https://production-sfo.browserless.io/screenshot?token=YOUR_BROWSERLESS_TOKEN' \
-H 'Content-Type: application/json' \
--data '{"url":"https://example.com","options":{"fullPage":true,"type":"png"}}' \
--output website-screenshot.png
Python
import requests
endpoint = "https://production-sfo.browserless.io/screenshot"
response = requests.post(
endpoint,
params={"token": "YOUR_BROWSERLESS_TOKEN"},
json={
"url": "https://example.com",
"options": {"fullPage": True, "type": "png"},
},
timeout=90,
)
response.raise_for_status()
with open("website-screenshot.png", "wb") as image_file:
image_file.write(response.content)
Node.js
const endpoint = new URL('https://production-sfo.browserless.io/screenshot');
endpoint.searchParams.set('token', process.env.BROWSERLESS_TOKEN);
const response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
url: 'https://example.com',
options: { fullPage: true, type: 'png' }
})
});
if (!response.ok) {
throw new Error(`Browserless request failed: HTTP ${response.status} ${await response.text()}`);
}
const image = Buffer.from(await response.arrayBuffer());
const { writeFile } = await import('node:fs/promises');
await writeFile('website-screenshot.png', image);
Or skip the browser setup
If your task is simply to turn a URL in a workflow into an image, ScreenshotNeo provides a screenshot API and an MCP server. Its [docs](https://screenshotneo.com/docs/) describe a one-call capture; the direct call below returns an image response:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers indicate the page verdict and billing status. Its MCP server includes screenshot, page-info, and PDF-capture tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan. See the ScreenshotNeo API docs and sign up free for 1,000 screenshots a month, with no card.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Script says the sheet is missing | The tab name does not match Sheet1. |
Change the name in getSheetByName() to the exact tab name. |
| URL validation fails or Browserless rejects the request | The input cell is empty, malformed, or lacks a scheme. | Use a complete publicly reachable https:// or http:// URL and trim accidental whitespace. |
| HTTP 401/403 or an authorization error | The token is missing, invalid, exposed incorrectly, or the endpoint/account configuration does not match. | Check Script Properties and the endpoint in your Browserless account documentation. Keep the token private. |
| Response is an error instead of an image | The API returned a non-success status, or the request shape/options are invalid. | Inspect the status and response body surfaced by the script. Verify the endpoint, token, JSON payload, and supported options. |
| Screenshot is blank, shows a CAPTCHA, or has access denied | The site may block automated browsers or require a human challenge. | Check the target page in a normal browser and review Browserless guidance. A screenshot API cannot guarantee a successful capture of every site. |
| Important content is missing | The page renders content asynchronously, lazily, or after interaction. | Use Browserless’s documented wait/navigation options where appropriate and verify the result. Some content may require site-specific interaction. |
| Drive file is not created or permission prompt appears | Drive scope has not been granted, or the script is running under an account without access. | Run interactively to authorize Drive access and ensure the executing account can create files. |
| Large run stops before finishing | Apps Script runtime, URL Fetch quota, or response-size limits were reached. | Process a smaller batch per execution, keep a progress column, and resume from the next unprocessed row. |
Performance, reliability, and quotas
Each capture requires a page load and an external request, so total run time depends on site response and page rendering. Full-page captures and pages with delayed content can take longer and return larger files than viewport captures. Choose the smallest useful output, avoid unnecessary waits, and process rows in manageable batches. Retain the input URL and a per-row status so failures can be retried without recapturing successful rows.
Google’s Apps Script quota page currently lists 20,000 URL Fetch calls per day for consumer accounts and 100,000 per day for Workspace accounts, a six-minute maximum execution time, and a 50 MB URL Fetch response limit per call. These values were checked on 2026-10-03 and Google says quotas can change. A script can hit its execution limit well before its daily request quota if individual pages are slow. See Google Apps Script quotas.
Browserless documents that automation can encounter blank captures, CAPTCHA pages, access-denied responses, or missing elements on sites that block automated browsing. Plan for failures: record the status, preserve the source URL, and retry selectively rather than treating every response as a valid screenshot.
FAQ
Can Browserless capture a full page?
Yes. Set options.fullPage to true in the screenshot request.
Does this put the image directly inside a cell?
No. The example saves the image to Drive and writes its file URL in the cell. A URL can be displayed in a sheet with spreadsheet formulas or other sheet features, but the image data itself is not stored by this script in the cell.
Can I run captures on a schedule?
Apps Script supports installable triggers. Scheduled runs still count toward execution limits and quotas, so use bounded batches and check the current quota page before scaling up.
Will every website render the same as it does in my browser?
No. Site behavior, automation blocking, delayed content, and authentication can change what the capture sees. Validate important pages and do not assume a successful HTTP response means the screenshot contains the expected content.


