How to Capture Bulk Screenshots with Airtable

Airtable can be an incredibly useful tool for creating a repository of web pages, whether from your own website or those of competitors. In this blog post, we will explore how to capture screenshots using Airtable, along with some advanced options for more complex workflows.

Basic Screenshot Capture in Airtable

To start, go to the webpage you want to capture. For example, navigate to tesla.com. Copy the URL, then go back to Airtable.

  1. Open Airtable: Navigate to your Airtable base.
  2. Attachment Field: Go to the attachment field and click the plus icon.
  3. Enter URL: Click on "Links" and enter the URL (including https:// and www).
  4. Upload: Click the link icon and then click "Upload". Airtable will automatically capture a screenshot of the webpage.

However, the built-in screenshot functionality in Airtable may not always capture the webpage as you need. In such cases, or if you want to integrate screenshots into a larger automated workflow, you can use other tools and APIs.

Advanced Screenshot Capture with APIs

For this more advanced workflow, we will use the "Get Screenshot" API from Rasterwise. This API integrates with Zapier, allowing for a more comprehensive workflow.

Tools Needed

  1. Airtable: Including the scripting app.
  2. Get Screenshot API: From Rasterwise, available at getscreenshotapi.com.

Setting Up the Airtable Table

  1. Create a Table: Name it "Single Screenshot".
  2. Primary Field: Use a formula field to extract the domain name from the screenshot URL.
  3. Status Column: Customize with options like "Screenshots Taken" and "Take Screenshots".
  4. URL Field: Enter the URL you want to capture (e.g., tesla.com).
  5. Attachment Field: Name it "Screenshot" to store the screenshot.
  6. Date Field: Capture the date the screenshot was taken.
  7. Button Field: Set up to run a script when clicked.

Writing the Script

Install the Airtable scripting app and write a script to automate the screenshot capture. Here are the key variables you will use with sample scripts for one or multiple screenshots:

  1. Table Name: Update with your table’s name.
  2. API Key: Enter your API key from Get Screenshot.
  3. API URL: Customize parameters like image format, height, and width.

Single Screenshot

// NOTE: This is based off of other scripts. Do not remember original sources.

const table = base.getTable("Single Screenshot"); // EDIT HERE: Name table
// Prompt the user to pick a record 
// If this script is run from a button field, this will use the button's record instead.
const record = await input.recordAsync('Select a record to use', table);

const scraperApiKey = "INSERT API KEY HERE";

const requestScreenshot = async url => {
    const rasterwiseUrl = `https://api.rasterwise.com/v1/get-screenshot?apikey=${scraperApiKey}&url=${encodeURIComponent(url)}`;
    output.text(`Queueing ${rasterwiseUrl}`);
    const response = await fetch(rasterwiseUrl);
    if (response.status / 100 == 2) {
        const json = await response.json();
        if (json.status == "success")
            return json.screenshotImage;
        else
            output.text(`${url} failed due to\n${JSON.stringify(json, null, 2)}`);
    }
    else
        output.text(`${url} failed with HTTP/${response.status}`);
};

if (record) {
    output.text(`You selected this record: ${record.name}`);

    const promises = {};

    const screenshots = [ "Screenshot" ]; // USE CASE: Single Screenshot
    //const screenshots = [ "Homepage", "Products", "Twitter" ]; // USE CASE: Multiple Screenshots

    // Make all screenshot requests in parallel, collect the promises
    for (const name of screenshots) {
        const url = record.getCellValue(`${name} URL`);
        promises[name] = url ? requestScreenshot(url) : null;
    }

    const update = {};

    for (const name of screenshots) {
        const promise = promises[name];
        update[`Screenshot`] = promise ? [{ "url": await promise }] : null; // USE CASE: Single Screenshot
        //update[`${name} Screenshot`] = promise ? [{ "url": await promise }] : null; // USE CASE: Multiple Screenshots
    }


    output.text(`Updating record with:\n${JSON.stringify(update, null, 2)}`);

    update["Screenshot Date"] = new Date();

    await table.updateRecordAsync(record,{
            "Status":{name: "Screenshots Taken; INSERT NEXT ACTION"}
        });
    

    await table.updateRecordAsync(record, update);

    output.text("Screenshot requests have been queued");
} else {
    output.text("No such record");
}

Multiple Screenshots


// NOTE: This is based off of other scripts. Do not remember original sources.

const table = base.getTable("Multiple Screenshots"); // EDIT HERE: Name table
// Prompt the user to pick a record 
// If this script is run from a button field, this will use the button's record instead.
const record = await input.recordAsync('Select a record to use', table);

const scraperApiKey = "INSERT GETSCREENSHOT API KEY HERE";

const requestScreenshot = async url => {
    const rasterwiseUrl = `https://api.rasterwise.com/v1/get-screenshot?apikey=${scraperApiKey}&url=${encodeURIComponent(url)}`;
    output.text(`Queueing ${rasterwiseUrl}`);
    const response = await fetch(rasterwiseUrl);
    if (response.status / 100 == 2) {
        const json = await response.json();
        if (json.status == "success")
            return json.screenshotImage;
        else
            output.text(`${url} failed due to\n${JSON.stringify(json, null, 2)}`);
    }
    else
        output.text(`${url} failed with HTTP/${response.status}`);
};

if (record) {
    output.text(`You selected this record: ${record.name}`);

    const promises = {};

    //const screenshots = [ "Screenshot" ]; // USE CASE: Single Screenshot
    const screenshots = [ "Homepage", "Products", "Twitter" ]; // USE CASE: Multiple Screenshots

    // Make all screenshot requests in parallel, collect the promises
    for (const name of screenshots) {
        const url = record.getCellValue(`${name} URL`);
        promises[name] = url ? requestScreenshot(url) : null;
    }

    const update = {};

    for (const name of screenshots) {
        const promise = promises[name];
        //update[`Screenshot`] = promise ? [{ "url": await promise }] : null; // USE CASE: Single Screenshot
        update[`${name} Screenshot`] = promise ? [{ "url": await promise }] : null; // USE CASE: Multiple Screenshots
    }


    output.text(`Updating record with:\n${JSON.stringify(update, null, 2)}`);

    update["Screenshot Date"] = new Date();

    await table.updateRecordAsync(record,{
            "Status":{name: "Screenshots Taken; INSERT NEXT ACTION"}
        });
    

    await table.updateRecordAsync(record, update);

    output.text("Screenshot requests have been queued");
} else {
    output.text("No such record");
}

Running the Script

Once the script is set up:

  1. Generate Screenshot: Click the button to run the script.
  2. Observe: Watch as the status and screenshot fields populate.

Capturing Multiple Screenshots

For capturing multiple screenshots, set up a new table "Multiple Screenshots" with similar fields but more URLs and attachment fields. Modify the script to handle multiple URLs:

// Update script for multiple screenshots
let urls = ["homepage_url", "products_url", "twitter_url"];

Run the script to capture multiple screenshots in one go.

Conclusion

This post provides a basic and advanced guide to capturing screenshots with Airtable. Whether you need a simple solution or a more complex workflow, these methods can help you efficiently archive web pages.


Video Reference

If you wish to watch a video tutorial, the following is the video referenced for this guide. Thanks to https://www.iheartnocode.com/ for this contribution: