Free tools Windows power users keep installed
One-click scans. No signup required.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Short answer: Google Sheets can place a screenshot into a cell area, but Apps Script does not document a browser-rendering function that turns an arbitrary webpage URL into a visual screenshot. Use one of three supported workflows: insert an image that already exists at a public URL, insert image bytes as a blob, or fetch an image response and insert that blob. If the source is a normal webpage, render it with a browser screenshot service first, then send the resulting PNG, JPEG or WebP to Sheets.
What Google Sheets can—and cannot—capture
The key distinction is between an image URL and a webpage URL. The Apps Script spreadsheet method Sheet.insertImage(url, column, row) expects a publicly accessible URL that serves image data. Passing https://example.com to that method does not mean “open the page in Chrome and photograph what a visitor sees.” It supplies a document URL where an image URL is required.
Apps Script’s UrlFetchApp can make HTTP and HTTPS requests and expose the response body, status code, bytes and blob. The documented service is an HTTP client, not a visual browser renderer. It will not, by itself, execute a page’s layout engine, wait for lazy content, accept a consent dialog or produce a screenshot of the rendered viewport.
Therefore, capturing a webpage in a sheet is a two-stage job:
#1 Best Overall
- Obtain a rendered screenshot from a browser-based step or screenshot API.
- Insert that image into the spreadsheet by public URL or blob.
The code below covers each insertion route and checks the response before writing anything to the sheet.
Route 1: insert an existing public image URL
Use this when a server already exposes a PNG, JPEG or WebP file. In Google Sheets, open Extensions → Apps Script, replace the editor contents, save, and run the function. The first run requests authorization.
function insertPublicImage() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const imageUrl = 'https://www.example.com/path/image.png';
// The URL must be publicly accessible and return image data.
sheet.insertImage(imageUrl, 2, 2); // column B, row 2
}
The image is inserted as an over-grid image anchored at the selected column and row. A private URL, a URL requiring a login, or a webpage that returns HTML will not satisfy the method’s documented requirement that the URL be publicly accessible and image-serving.
Route 2: insert image bytes as a blob
If your script already has image bytes, use the blob overload. The documented insertion method has a maximum blob size of 2 MB, so check the response before insertion. This route is useful when you need to fetch a signed or short-lived image URL and do not want Sheets to fetch that URL later.
Rank #2
function insertBlobImage() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const imageUrl = 'https://www.example.com/path/image.png';
const response = UrlFetchApp.fetch(imageUrl, {
muteHttpExceptions: true,
followRedirects: true
});
const status = response.getResponseCode();
const blob = response.getBlob();
const contentType = (blob.getContentType() || '').toLowerCase();
const size = blob.getBytes().length;
if (status < 200 || status >= 300) {
throw new Error('Image request failed with HTTP ' + status);
}
if (!contentType.startsWith('image/')) {
throw new Error('Expected an image but received ' + contentType);
}
if (size > 2 * 1024 * 1024) {
throw new Error('Image is larger than the documented 2 MB blob limit');
}
sheet.insertImage(blob, 2, 2);
}
getBlob() preserves the response content for insertion; getContentText() is for text and is not appropriate for binary image data. The size check prevents a predictable failure when a screenshot is too large.
Route 3: fetch an image, validate it, then insert it
This is the practical bridge between an image-producing endpoint and Sheets. Add the external-request OAuth scope when you manage scopes explicitly:
https://www.googleapis.com/auth/script.external_request
In a default Apps Script project, running the function normally presents the required consent screen. An explicit appsscript.json manifest can include the scope in its oauthScopes array.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →function fetchAndInsertImage() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const endpoint = 'https://www.example.com/screenshot.png';
const response = UrlFetchApp.fetch(endpoint, { muteHttpExceptions: true });
const status = response.getResponseCode();
const headers = response.getAllHeaders();
const blob = response.getBlob();
const type = (blob.getContentType() || '').toLowerCase();
if (status !== 200) {
throw new Error('Screenshot endpoint returned HTTP ' + status);
}
if (!type.match(/^image/(png|jpeg|webp)$/)) {
throw new Error('Endpoint did not return PNG, JPEG or WebP data');
}
if (blob.getBytes().length > 2 * 1024 * 1024) {
throw new Error('Reduce the screenshot dimensions or file quality below 2 MB');
}
sheet.insertImage(blob, 1, 1);
}
The headers variable is available if you need to log provider metadata; it is not required for insertion. Always validate status and content type because an error page, login page or JSON message can arrive with a successful HTTP transport.
Rendering a webpage before inserting it
When the target is an ordinary webpage, use a browser-rendering step that returns an image. Rendering matters for JavaScript-generated content, responsive layouts, fonts, cookie dialogs, lazy images and pages that require a real browser user agent. The reviewed Google APIs establish the insertion and fetching stages, not a particular rendering provider or browser workflow.
After rendering, choose:
- Public image URL: pass the image URL to
insertImage(url, column, row). - Image bytes: download the result with
UrlFetchApp, validate it, and pass the blob toinsertImage(blob, column, row).
For repeatable reports, save the capture timestamp and source URL in adjacent cells. If the page changes, the sheet then records which capture produced the image rather than silently replacing it.
Or skip the browser setup: ScreenshotNeo
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP or PDF, which you can save and then insert with the blob workflow above. Its cleanup step accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup action can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page verdict and billing result in X-Page-Verdict and X-Billed headers.
Example cURL request (replace the target URL and key):
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()
open("shot.webp", "wb").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(`HTTP ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));
See the ScreenshotNeo documentation for parameters. Options include full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or custom viewports, retina scale, PDF paper settings and page ranges, custom CSS and JavaScript, pre-capture clicks, hidden selectors, waits for selectors, delays or network idle, request and resource blocking, custom headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs are accepted to ease migration.
Rank #4
Plans include 1,000 shots per month free with no card; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing provides two months free, and every feature is available on every plan. The MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
Once shot.webp is available at a public location or uploaded by your Apps Script workflow, use Route 2 to place it in Sheets. Create a free ScreenshotNeo account to get 1,000 screenshots a month without a card.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Choosing the insertion route
| Route | Input | Best use | Constraint |
|---|---|---|---|
| Insert by URL | Public URL serving an image | Simple, stable image hosting | URL must be publicly accessible |
| Insert by blob | Image bytes already in Apps Script | Private, signed or one-time responses | 2 MB maximum for the documented blob insertion method |
| Fetch then insert | HTTP/HTTPS response | Validate status and content before insertion | Fetch is not browser rendering; external-request authorization is required |
| Render separately, then insert | Screenshot produced by a browser step | JavaScript-heavy or responsive pages | Rendering provider and workflow are separate from Sheets |
Troubleshooting common failures
“The URL is not accessible”
Check that the image URL works in an incognito browser without authentication and returns image bytes. A webpage URL, a private object-storage URL or an endpoint restricted by IP will fail the public-URL route. Fetch privately with UrlFetchApp and insert the blob instead, if permitted.
HTTP 200 but insertion fails
Inspect getBlob().getContentType(). Many sites return an HTML challenge, login form or JSON error with status 200. Reject anything that is not an image MIME type.
Authorization or scope errors
Run the function from the Apps Script editor and accept the consent prompt. If scopes are explicit, include https://www.googleapis.com/auth/script.external_request.
Blob-size error
The documented limit is 2 MB. Request a smaller viewport, lower image quality, a compressed format, or an element crop from the rendering step.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsThe screenshot is blank or missing dynamic content
That is a rendering-stage issue, not an insertion issue. Wait for a selector or network idle, allow JavaScript, and ensure the page is reachable without an interactive login. Then validate the returned image before inserting it.
Images overlap cells or look too large
insertImage creates an over-grid image. Move or resize it in the Sheets UI after insertion, or use a consistent anchor column and row for each report run. Keep source URL, capture time and verdict in neighboring cells for auditing.
Operational checklist
- Confirm whether the source URL returns an image or a webpage.
- If it is a webpage, render it separately.
- Check HTTP status, MIME type and byte size before insertion.
- Stay below the 2 MB blob limit for blob insertion.
- Authorize the external-request scope when using
UrlFetchApp. - Record the source URL and capture time beside the image.
Frequently Asked Questions
Can I pass a normal website URL directly to insertImage?
No. The documented URL method expects a publicly accessible image URL; render the webpage first.
Does UrlFetchApp run JavaScript like Chrome?
The documented service fetches HTTP/HTTPS resources and returns response data. It is not documented as a visual browser renderer.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →What is the blob limit when inserting an image?
The documented blob insertion method has a maximum blob size of 2 MB.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

