No-code tools
Every endpoint is a single HTTP request, so Shotlane works in any tool with an HTTP step: Google Sheets, Zapier, Make, n8n, Airtable and others. Copy a recipe below.
Most no-code tools handle links better than files. Add response_type=json and use the url field of the response: a hosted link that stays valid for 24 hours. To keep the image, have the next step download it or upload it to your own storage with the storage_* parameters.
Google Sheets
Show a live screenshot in a cell with =IMAGE(SHOTLANE(A2)). In your sheet, open Extensions → Apps Script, paste this, fill in your two keys from the dashboard, and save:
// Shotlane for Google Sheets: =IMAGE(SHOTLANE(A2)) shows a live screenshot of the URL in A2.
// Extensions → Apps Script → paste this file → set your keys below → Save. No API call happens here:
// the function only builds a signed image URL, and Sheets loads it. Each URL is cached for 24 hours,
// so a sheet costs 1 credit per URL per day however often it recalculates.
const SHOTLANE_PUBLIC_KEY = "pub_..."; // dashboard → Public key
const SHOTLANE_SECRET_KEY = "sl_..."; // dashboard → Secret API key (stays in this script, not in the sheet)
/**
* A signed Shotlane screenshot URL for use with IMAGE().
* @param {string} url The page to capture.
* @param {string} options Optional extra parameters, e.g. "device=iphone&full_page=true".
* @customfunction
*/
function SHOTLANE(url, options) {
if (!url) return "";
const params = { url: String(url), format: "png", width: "1280", height: "800", hide_cookie_banners: "true" };
String(options || "").split("&").filter(String).forEach(function (pair) {
const i = pair.indexOf("=");
params[decodeURIComponent(pair.slice(0, i))] = decodeURIComponent(pair.slice(i + 1));
});
const enc = function (s) { // the same encoding as Python's urlencode
return encodeURIComponent(s).replace(/%20/g, "+").replace(/[!'()*]/g, function (c) { return "%" + c.charCodeAt(0).toString(16).toUpperCase(); });
};
const query = Object.keys(params).sort().map(function (k) { return enc(k) + "=" + enc(params[k]); }).join("&");
const path = "/v1/screenshot";
const sig = Utilities.computeHmacSha256Signature(path + "?" + query, SHOTLANE_SECRET_KEY)
.map(function (b) { return ("0" + (b & 0xff).toString(16)).slice(-2); }).join("");
return "https://shotlane.dev" + path + "?" + query + "&key=" + SHOTLANE_PUBLIC_KEY + "&signature=" + sig;
}
Also as a file: shotlane.gs.
Then in the sheet: =IMAGE(SHOTLANE(A2)), or with options =IMAGE(SHOTLANE(A2, "device=iphone&full_page=true")). The function builds a signed URL and makes no request itself; your secret key stays in the script, not in the sheet. Signed URLs are cached for 24 hours, so a sheet costs one credit per URL per day however often it recalculates.
Zapier
- Add an action step: Webhooks by Zapier → GET.
- URL:
https://shotlane.dev/v1/screenshot - Query string params:
url(map it from your trigger),response_type=json, plus any options such asfull_page=true. - Headers:
X-API-Key= your API key. - Use the step's
urloutput in later steps (Slack, email, Google Drive "upload file from URL"…).
The same works for PDFs (/v1/pdf), Markdown (/v1/markdown, the text is the response), page checks (/v1/check) and videos (/v1/animate).
Make
- Add the HTTP → Make a request module.
- URL
https://shotlane.dev/v1/screenshot, method GET, a headerX-API-Keywith your key. - Query string:
url,response_type=json, and options. Turn on Parse response. - Map
data.urlinto the next module. To pass the file itself instead, dropresponse_type: the response body is the image.
n8n
Use an HTTP Request node: method GET, URL https://shotlane.dev/v1/screenshot, authentication Generic Credential Type → Header Auth with name X-API-Key and your key as the value, and query parameters url and your options. Set Response Format to File to get the image as binary data, or add response_type=json for a link.
Airtable
In a Run a script automation (or the Scripting extension), fetch a screenshot for a record's URL and store it in an attachment field:
const { url, recordId } = input.config();
const r = await fetch("https://shotlane.dev/v1/screenshot?response_type=json&url=" + encodeURIComponent(url), {
headers: { "X-API-Key": "sl_your_key" },
});
const shot = await r.json();
if (!r.ok) throw new Error(shot.error);
const table = base.getTable("Sites");
await table.updateRecordAsync(recordId, { Screenshot: [{ url: shot.url }] });
Airtable copies the file from the link into its own storage, so the attachment stays after the link expires.
Anything else
Retool, Bubble, Pipedream, Power Automate, Clay and others: use their HTTP or API step with the same three things (the endpoint URL, the X-API-Key header, and your options as query parameters). The OpenAPI spec imports into tools that read it.