Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
Automation

How to Capture Screenshots from a List of URLs in Google Sheets

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Google Sheets cannot render a website screenshot from a URL on its own. To capture a list of pages, use Apps Script to send each URL to a browser-based screenshot renderer or screenshot API, then place the returned image in the sheet or save it to Drive and link to it. The practical workflow is: keep one URL per row, run a script from a menu or button, and record each capture or error alongside its source URL.

What the workflow does—and what Sheets does not do

A URL is an address, not an image. Google Apps Script can make HTTP and HTTPS requests with UrlFetchApp, but that service does not open a browser and render a page. The screenshot renderer must do that work and return an image or a URL for one. Google’s Apps Script documentation describes the network-request service in its UrlFetchApp reference.

The basic pipeline is:

  1. Read website URLs from a column in a Google Sheet.
  2. Send each URL to a screenshot renderer, with whatever authentication and capture options that service requires.
  3. Receive image bytes or a fetchable image URL.
  4. Insert the image in the sheet, or save it to Drive and place a durable link in the row.

Google’s documentation supports multiple requests through UrlFetchApp.fetchAll(). The right batch size, concurrency, quotas, and output limits depend on the renderer and Apps Script execution context, so test those against the service you choose rather than assuming a universal number.

Prepare the spreadsheet

Use a clear input and output layout

Put one fully qualified website URL per row in column A. Add headers in row 1, such as Website URL, Screenshot, and Status. Reserve column B for the image and column C for a status message. A sample layout:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Website URL Screenshot Status
https://example.com Image or link Pending

Use https:// URLs, remove blank rows from the processing range, and keep any headers out of the URL list. If the sheet is shared, decide who should be allowed to see the captures and the stored image files before making images public.

Authorize Apps Script for external requests

Open the spreadsheet, choose Extensions > Apps Script, and authorize the script when prompted. Apps Script’s external-request service needs the script.external_request OAuth scope when you configure scopes explicitly. If you use a renderer requiring an API key, store it as a script property rather than placing it in a visible cell; anyone who can edit the script project may still be able to access project configuration, so limit editor access accordingly.

Choose where the screenshot will appear

Insert an image from a blob over the grid

Sheet.insertImage(blob, column, row) adds an image over the cells. It is useful when the API response contains image bytes, but Google’s current reference documents a maximum supported image size of 2 MB for this insertion method. A renderer may return a larger image, so request a smaller viewport, compressed format, or reduced dimensions if necessary. The image floats over the grid rather than becoming the cell’s value.

Insert an image from a URL

Sheet.insertImage(url, column, row) requires an image URL that is publicly accessible. Google’s Class Sheet reference states that “The provided URL must be publicly accessible.” This option is not suitable for private URLs that require an authorization header or a logged-in session unless you first copy the image to storage with an appropriately accessible link.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a cell image or store the file in Drive

If the image should behave as cell content rather than an over-grid object, use a cell-image approach supported by Sheets, or save the image in Drive and place a link to the file in the row. Consider access permissions: a Drive file may not be visible to every sheet reader unless it is shared appropriately.

Do not assume a Google-hosted image content URL is a permanent storage link. The Class CellImage reference says that getContentUrl() returns a requester-tagged URL that “expires after a short period of time.” Its availability can also be affected by spreadsheet sharing settings. For a long-lived record, save the underlying image in a storage location with suitable sharing and retention, rather than treating that temporary URL as an archive.

Rank #2
Sale
Mastering Google Sheets: A Step-by-Step Handbook for Beginners to Simplify Data Analysis, Boost Productivity, and Unlock Your Full Spreadsheet Potential
  • Mastering Google Sheets: A Step by Step Handbook for Beginners to Simplify Data Analysis, Boost Productivity, and Unlock Your Full Spreadsheet Potential
  • ABIS BOOK

Build the Apps Script around your screenshot service

There is no provider-neutral screenshot endpoint or request format: each service defines its own authentication, URL parameter, response format, and capture options. The Apps Script below is therefore a safe integration skeleton, not a complete request for an unspecified service. Replace callRenderer_() with the endpoint and authentication documented by the renderer you select. It expects that function to return a successful PNG, JPEG, or WebP response as a blob.

In the spreadsheet, select Extensions > Apps Script, replace the starter code with the following, and save. On reload, a Screenshots menu appears. The menu starts the work from a normal script invocation instead of a custom cell formula.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('Screenshots')
    .addItem('Capture URLs', 'captureUrls')
    .addToUi();
}

function captureUrls() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const firstDataRow = 2;
  const urlColumn = 1;
  const imageColumn = 2;
  const statusColumn = 3;
  const lastRow = sheet.getLastRow();

  if (lastRow < firstDataRow) return;

  const rows = sheet.getRange(firstDataRow, urlColumn,
    lastRow - firstDataRow + 1, 1).getValues();

  rows.forEach((row, i) => {
    const targetRow = firstDataRow + i;
    const url = String(row[0] || '').trim();
    if (!url) return;

    try {
      if (!/^https?:///i.test(url)) {
        throw new Error('Enter a complete http:// or https:// URL.');
      }

      const blob = callRenderer_(url);
      if (!blob || !blob.getBytes().length) {
        throw new Error('Renderer returned an empty response.');
      }

      // Remove an earlier over-grid image anchored at this output cell.
      sheet.getImages().forEach(image => {
        if (image.getAnchorCell().getRow() === targetRow &&
            image.getAnchorCell().getColumn() === imageColumn) {
          image.remove();
        }
      });

      sheet.insertImage(blob, imageColumn, targetRow);
      sheet.getRange(targetRow, statusColumn).setValue('Captured');
    } catch (err) {
      sheet.getRange(targetRow, statusColumn)
        .setValue('Error: ' + (err.message || err));
    }
  });
}

function callRenderer_(url) {
  // Replace this function with your provider's documented request.
  // It must return image bytes as an Apps Script Blob.
  throw new Error('Configure callRenderer_() for your screenshot service.');
}

After you implement callRenderer_(), return the actual image blob, not a JSON response containing metadata. Keep provider-specific secrets out of the sheet. If the chosen API returns JSON with a hosted image URL instead of bytes, fetch that URL only if it is accessible to Apps Script, or save the image to suitable storage and use a method appropriate to the resulting access model.

Why a custom cell function is the wrong trigger

A formula such as =CAPTURE(A2) looks convenient, but external requests have authorization and recalculation behavior that make custom spreadsheet functions an unsuitable place for this work. A screenshot API vendor’s integration guide recommends starting external capture from a menu, button, or trigger instead. The menu approach above makes the action explicit and allows the script to update status cells. For a scheduled workflow, use an installable time-driven trigger and account for Apps Script and provider execution limits.

Scale to a longer URL list safely

For a small list, sequential processing is easier to understand and gives a clear row-level status. For a longer list, a single run may exceed a script execution limit or a provider’s request allowance. Do not assume that one invocation can process every row.

  • Process in chunks: store a next-row checkpoint in script properties and process a bounded number of rows per invocation. Resume from the checkpoint until the list is complete.
  • Skip completed work: check the status or an existing output before making another paid capture. Offer a deliberate recapture action when the source page changes.
  • Handle failures per row: record the URL and error, continue with later rows, and retry transient timeouts or rate limits separately rather than restarting every capture.
  • Use concurrency carefully: UrlFetchApp.fetchAll() can issue multiple requests, but the appropriate batch size depends on Apps Script quotas and the screenshot service’s concurrency and rate limits.
  • Track output size: large full-page images can hit the documented 2 MB limit for blob-based insertImage. Consider a smaller viewport, compression, or external storage with a link in the sheet.
  • Plan for duplicate runs: remove or replace the prior image at the output anchor, or deliberately preserve versions elsewhere. Avoid leaving overlapping images after recaptures.

For each renderer, check its authentication requirements, capture options, response size, quotas, caching, pricing, and retention behavior. The sources do not establish one universal batch limit or a best provider; those are service-specific choices.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshooting common failures

Authorization or external request errors

If Apps Script reports that the request is unauthorized or the scope is missing, approve the script’s requested permissions and confirm script.external_request is included if you explicitly maintain OAuth scopes. Check that the API key is valid and sent in the exact location required by the service. Do not paste secrets into a publicly shared sheet.

The output is not an image

A nonempty response is not necessarily an image. A service may return a JSON error, HTML challenge page, or text response. Check the HTTP status and response content type before inserting the result. Update the script to detect non-success status codes and report a short provider error instead of treating those bytes as a screenshot.

The screenshot exceeds 2 MB

insertImage(blob, ...) may fail when its image exceeds the documented 2 MB supported size. Reduce the capture dimensions, avoid unnecessarily long full-page images, use a more compact image format if supported, or save the file elsewhere and insert a link or suitable public image URL.

The image URL does not load in the sheet

URL-based insertion requires a publicly accessible image URL. A link that works only in your browser because you are signed in will not meet that requirement. Adjust access intentionally or use a blob-based or cell-image/storage workflow that fits the file’s sharing requirements.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The displayed image disappears later

If the sheet uses a URL from CellImage.getContentUrl(), that URL may expire after a short period. Store the original capture in Drive or other durable storage and use an appropriate stable reference with permissions that match the sheet audience.

The script stops partway through the list

Long runs can run into Apps Script execution limits, provider timeouts, or rate limits. Process fewer rows per run, write status as each row finishes, and resume from the first unfinished row. Add a bounded retry for temporary errors; do not blindly repeat every completed request.

Rank #4
Sale
The Google Workspace Bible: [14 in 1] The Ultimate All-in-One Guide from Beginner to Advanced | Including Gmail, Drive, Docs, Sheets, and Every Other App from the Suite
  • The Google Workspace Bible: [14 in 1] The Ultimate All in One Guide from Beginner to Advanced Including Gmail, Drive, Docs, Sheets, and Every Other App from the Suite
  • ABIS BOOK
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo is a screenshot API and MCP server; Apps Script can call its GET endpoint and insert the returned bytes. Use the ScreenshotNeo documentation for request options and response details. This complete Apps Script example uses one request per populated URL and places each response as an image over the grid:

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('Screenshots')
    .addItem('Capture URLs', 'captureUrls')
    .addToUi();
}

function captureUrls() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const firstDataRow = 2;
  const lastRow = sheet.getLastRow();
  if (lastRow < firstDataRow) return;

  const urls = sheet.getRange(firstDataRow, 1,
    lastRow - firstDataRow + 1, 1).getValues();
  const key = PropertiesService.getScriptProperties()
    .getProperty('SCREENSHOTNEO_ACCESS_KEY');
  if (!key) throw new Error('Set SCREENSHOTNEO_ACCESS_KEY in script properties.');

  urls.forEach((row, i) => {
    const r = firstDataRow + i;
    const url = String(row[0] || '').trim();
    if (!url) return;
    try {
      const response = UrlFetchApp.fetch(
        'https://api.screenshotneo.com/v1/shot?' +
        'access_key=' + encodeURIComponent(key) +
        '&url=' + encodeURIComponent(url),
        { muteHttpExceptions: true, followRedirects: true }
      );
      if (response.getResponseCode() < 200 || response.getResponseCode() >= 300) {
        throw new Error('HTTP ' + response.getResponseCode());
      }
      const blob = response.getBlob();
      sheet.getImages().forEach(image => {
        if (image.getAnchorCell().getRow() === r &&
            image.getAnchorCell().getColumn() === 2) image.remove();
      });
      sheet.insertImage(blob, 2, r);
      sheet.getRange(r, 3).setValue('Captured');
    } catch (err) {
      sheet.getRange(r, 3).setValue('Error: ' + (err.message || err));
    }
  });
}

In Apps Script, open Project Settings > Script Properties and add SCREENSHOTNEO_ACCESS_KEY with your API key. The script makes an individual call for each nonblank row; keep list size and execution limits in mind, and chunk a long list rather than assuming one run will finish it. ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The Free plan includes 1,000 screenshots monthly with no card; paid plans start at $5 for 3,000. Sign up for ScreenshotNeo’s free plan.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

FAQ

Can I capture screenshots with a Google Sheets formula alone?

No. A formula can display or reference an image, but rendering a website requires a browser-based renderer or screenshot service. Apps Script can send the request and manage the output.

Can Sheets put the screenshot inside the same cell as the URL?

Yes, use a cell-image method when you want an in-cell presentation. The script example uses insertImage(blob, column, row), which places an image over the grid instead.

Can I capture a private or logged-in page?

That depends on the screenshot service’s support for authentication, cookies, and request headers, and on whether the service can access the page. Do not expose session credentials in sheet cells or publicly shared script code.

Can I make screenshots run automatically?

Yes. A trigger can invoke the capture function, but scheduled runs still need to respect Apps Script execution constraints and the renderer’s quotas. Test with a small list before scheduling repeated captures.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.