Google Sheets can show any image from a URL with =IMAGE(), but it can't take a screenshot of a website. A 25-line Apps Script custom function fixes that: put URLs in column A, type =IMAGE(SHOTMINT(A2)) next to them, and each cell shows a live screenshot of that page. A second function saves the screenshots as PNG files in Google Drive. No add-on to install, and nothing to run on your side.
SHOTMINT(url) doesn't fetch anything itself. It builds a signed screenshot URL: an image link that carries an HMAC signature made with your API key, but not the key itself. Sheets loads that link like any other image, and Shotmint renders the page. Your key never appears in the sheet, so you can share it safely. Nobody can change the signed link to capture other pages on your credits.
Cost: 1 credit per new screenshot. The same URL and size requested again within 24 hours comes from cache and costs nothing, so recalculating or reopening the sheet the same day doesn't burn credits. A failed render (dead page, timeout) is refunded.
Get a key with 100 free renders at /pricing (no signup). In your sheet, open Extensions → Apps Script, replace the contents of Code.gs with the code below and click Save. Then go to Project Settings (gear icon) → Script Properties → Add script property, name it SHOTMINT_KEY and paste your key. Script properties are visible to the script's editors only, not to people who can just view or comment on the sheet.
/**
* Returns a signed Shotmint screenshot URL for use in =IMAGE().
* Example: =IMAGE(SHOTMINT(A2)) or =IMAGE(SHOTMINT(A2, 390, 844, TRUE))
* @param {string} url Page to capture.
* @param {number} width Viewport width in px (default 1280).
* @param {number} height Viewport height in px (default 800).
* @param {boolean} mobile Emulate a phone (default FALSE).
* @customfunction
*/
function SHOTMINT(url, width, height, mobile) {
if (!url) return '';
var key = PropertiesService.getScriptProperties().getProperty('SHOTMINT_KEY');
if (!key) throw new Error('Set the SHOTMINT_KEY script property first');
var fields = ['url', 'width', 'height', 'full_page', 'mobile', 'device_scale_factor',
'block_ads', 'dark_mode', 'delay', 'wait_until', 'hide_selectors'];
url = String(url).trim();
if (url.toLowerCase().indexOf('http') !== 0) url = 'https://' + url;
var p = { url: url, width: String(width || 1280), height: String(height || 800), block_ads: 'true' };
if (mobile) p.mobile = 'true';
var canon = fields.map(function (f) { return p[f] || ''; }).join('\n');
var bytes = Utilities.computeHmacSha256Signature('shot\n' + canon, key);
var sig = bytes.map(function (b) { return ('0' + (b & 255).toString(16)).slice(-2); }).join('').slice(0, 32);
var kid = Utilities.base64EncodeWebSafe(Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, key)).slice(0, 12);
var qs = fields.filter(function (f) { return p[f]; })
.map(function (f) { return f + '=' + encodeURIComponent(p[f]); }).join('&');
return 'https://shotmint.creasework.com/s/' + kid + '.png?' + qs + '&sig=' + sig;
}
/** Adds a Shotmint menu to the sheet. */
function onOpen() {
SpreadsheetApp.getUi().createMenu('Shotmint')
.addItem('Save screenshots to Drive', 'saveScreenshotsToDrive')
.addToUi();
}
/** URLs in column A (row 1 = header) -> PNGs in a Drive folder, links in column B. */
function saveScreenshotsToDrive() {
var sheet = SpreadsheetApp.getActiveSheet();
var last = sheet.getLastRow();
if (last < 2) return;
var urls = sheet.getRange(2, 1, last - 1, 1).getValues();
var folder = DriveApp.createFolder('Shotmint screenshots ' + new Date().toISOString().slice(0, 10));
for (var i = 0; i < urls.length; i++) {
var url = String(urls[i][0]).trim();
if (!url) continue;
var res = UrlFetchApp.fetch(SHOTMINT(url), { muteHttpExceptions: true });
var cell = sheet.getRange(i + 2, 2);
if (res.getResponseCode() !== 200) {
cell.setValue('Error ' + res.getResponseCode() + ': ' + res.getContentText().slice(0, 200));
continue;
}
var name = url.replace('https://', '').replace('http://', '').split('/').join('_') + '.png';
cell.setValue(folder.createFile(res.getBlob().setName(name)).getUrl());
}
}
| Formula | Result |
|---|---|
=IMAGE(SHOTMINT(A2)) | Desktop screenshot, 1280×800, fitted to the cell |
=IMAGE(SHOTMINT(A2, 390, 844, TRUE)) | Mobile view, 390×844 (iPhone-sized) |
=IMAGE(SHOTMINT(A2, 1440, 900), 4, 180, 288) | Wide desktop view at a fixed 288×180 px in the cell |
=SHOTMINT(A2) | Just the image URL, to paste into a doc, a CMS or an email |
Make rows taller (right-click the row number → Resize row, e.g. 180) so the thumbnails are readable. Fill the formula down the column and every row gets its own screenshot. The URL column can be plain domains: example.com becomes https://example.com. The function also turns on block_ads to drop common ads and cookie banners; to change any other option (full page, dark mode, a delay before the capture), edit the p object in the script and use field names from the signed URL docs.
After saving the script, reload the sheet. A Shotmint menu appears: Save screenshots to Drive reads every URL in column A (row 1 is the header), saves each one as a PNG in a new dated Drive folder, and writes the file link (or the error message) in column B. The first run asks you to authorize Drive and external requests. Use this when you need files, e.g. to archive competitor homepages, attach screenshots to a client report, or keep a record of how pages looked on a given day.
Apps Script itself only runs inside Google, so we ran the exact code above in Node.js with stand-ins for the Google services it uses: Utilities, PropertiesService, UrlFetchApp, SpreadsheetApp and DriveApp. The signed URLs it built returned real screenshots from the live API (1280×800 desktop, 390×844 mobile, with a bare domain upgraded to https). The Drive function saved the PNGs and wrote the error text for an unreachable host in column B. The calls to Google's services are standard Apps Script APIs, but we couldn't run them against Google here.
For other no-code tools, see n8n, Make and Zapier. For a script that captures a URL list from your own machine, see bulk website screenshots.
No signup, no card. Get a key in one click, then buy credits only if you need more (from €5 for 2,000, never expire).
Get a free API key Full API reference