How to Scrape Websites into Google Sheets & Airtable Automatically

Business analysts and founders who live in spreadsheets don't want to manage Python scripts or API keys manually. This guide shows three ways to wire up the Bolt Scraper Website API to your Google Sheet or Airtable base — from a one-click Apps Script button to a fully automated n8n pipeline that self-updates on a schedule.

Three Integration Approaches

Depending on your technical comfort level and automation needs, there are three ways to connect the Website Scraper API to your spreadsheet tool:

Method Difficulty Best For Auto-Updates?
Google Apps Script Low Google Sheets users who want a one-click button Manual trigger or timed
Make.com (Zapier) Very Low — no code Sheets and Airtable users who prefer drag-and-drop Yes — on webhook event
n8n workflow Low-Medium Teams wanting full control and self-hosted automation Yes — fully automated

Method 1 — Google Sheets with Apps Script

This approach adds a custom menu button to your Google Sheet. Click it, and it reads all URLs from column A, submits them to the API, then polls until the job completes and writes the enriched data back into columns B onwards — all within the sheet.

Sheet structure required:

A: Website URL  |  B: Email 1  |  C: Phone 1  |  D: LinkedIn  |  E: Instagram  |  F: Facebook  |  G: Company Name
BoltScraper.gs — Google Apps Script (Tools → Script Editor)
const API_KEY  = 'bs_YOUR_API_KEY';
const BASE_URL = 'https://boltscraper.com/api/v1/website';

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('🔍 Bolt Scraper')
    .addItem('Enrich Selected URLs', 'enrichUrls')
    .addToUi();
}

function enrichUrls() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const lastRow = sheet.getLastRow();
  const urls = sheet.getRange(2, 1, lastRow - 1).getValues()
    .flat().filter(u => u);

  if (!urls.length) { return Browser.msgBox('No URLs found in column A'); }

  // 1. Submit job
  const jobRes = UrlFetchApp.fetch(`${BASE_URL}/jobs`, {
    method: 'post',
    contentType: 'application/json',
    headers: { Authorization: `Bearer ${API_KEY}` },
    payload: JSON.stringify({ job_name: 'Sheets Enrichment', urls })
  });
  const { job_id } = JSON.parse(jobRes.getContentText());

  // 2. Poll until complete (max 10 min)
  let status = 'scraping';
  let tries = 0;
  while (status !== 'COMPLETED' && tries < 40) {
    Utilities.sleep(15000);
    const poll = JSON.parse(UrlFetchApp.fetch(`${BASE_URL}/jobs/${job_id}`, {
      headers: { Authorization: `Bearer ${API_KEY}` }
    }).getContentText());
    status = poll.job.status;
    tries++;
  }

  // 3. Fetch results and write back to sheet
  const results = JSON.parse(UrlFetchApp.fetch(
    `${BASE_URL}/jobs/${job_id}/results?pageSize=10000`,
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  ).getContentText()).results;

  const resultMap = {};
  results.forEach(r => { resultMap[r.url.replace(/\/$/, '')] = r; });

  for (let i = 2; i <= lastRow; i++) {
    const url = sheet.getRange(i, 1).getValue().replace(/\/$/, '');
    const r = resultMap[url] || resultMap['https://' + url];
    if (r) {
      sheet.getRange(i, 2, 1, 6).setValues([[
        r.email_1, r.phone_1, r.linkedin_url,
        r.instagram_url, r.facebook_url, r.page_title
      ]]);
    }
  }
  Browser.msgBox(`✅ Enrichment complete — ${results.length} URLs processed`);
}
Apps Script Execution Limit

Google Apps Script has a 6-minute execution limit on free accounts. For lists larger than ~300 URLs (which can take longer to enrich), use the Make.com or n8n webhook approach instead — those are async and have no timeout.

Method 2 — Make.com (No-Code, Fully Automated)

Make.com (formerly Integromat) is the easiest way to get a fully automated, self-updating pipeline. The scenario below fires every time a new row is added to your sheet and automatically writes enrichment data back when the job completes.

1
Trigger: Google Sheets — Watch New Rows

Watches for new rows added to column A. Set the watch interval to every 15 minutes.

2
HTTP: POST to /api/v1/website/jobs

Pass the new URL(s) as the urls array. Include Authorization: Bearer YOUR_KEY header.

3
Webhooks: Custom Webhook (Listen)

Add a Make.com Webhook module. Copy the webhook URL and register it in your Bolt Scraper dashboard. This module receives the website_job.completed payload automatically.

4
HTTP: GET download_csv_url

Use the download_csv_url from the webhook payload in an HTTP GET module. Parse the CSV response.

5
Google Sheets / Airtable: Update Row

Map email_1, phone_1, linkedin_url, instagram_url to the corresponding columns. The sheet updates itself — no human action required.

Method 3 — Airtable with n8n (Self-Hosted Automation)

For teams using Airtable as their lead CRM, n8n provides a more powerful and customisable integration. The n8n workflow listens for the Bolt Scraper webhook, fetches the results, and creates or updates Airtable records automatically.

n8n Workflow — Bolt Scraper → Airtable (key nodes)
// Node 1: Webhook Trigger
{
  "type": "n8n-nodes-base.webhook",
  "parameters": {
    "httpMethod": "POST",
    "path": "bolt-website"
  }
}

// Node 2: Filter — only process completed jobs
{
  "type": "n8n-nodes-base.if",
  "parameters": {
    "conditions": {
      "string": [{ "value1": "={{ $json.event }}", "value2": "website_job.completed" }]
    }
  }
}

// Node 3: HTTP Request — fetch full results CSV
{
  "type": "n8n-nodes-base.httpRequest",
  "parameters": {
    "method": "GET",
    "url": "={{ $json.download_csv_url }}",
    "responseFormat": "text"
  }
}

// Node 4: Airtable — Create/Upsert Records
{
  "type": "n8n-nodes-base.airtable",
  "parameters": {
    "operation": "upsert",
    "table": "Leads",
    "matchField": "Website",
    "fields": {
      "Website":   "={{ $item.url }}",
      "Email":     "={{ $item.email_1 }}",
      "Phone":     "={{ $item.phone_1 }}",
      "LinkedIn":  "={{ $item.linkedin_url }}",
      "Instagram": "={{ $item.instagram_url }}",
      "Facebook":  "={{ $item.facebook_url }}",
      "Company":   "={{ $item.page_title }}"
    }
  }
}

The upsert operation on the Website field ensures existing Airtable records are updated (not duplicated) when re-enriched weeks later — making this the foundation for a self-maintaining, always-fresh lead base.

Build Your Self-Updating Lead Base Today

Add a list of company URLs to your Google Sheet or Airtable. Click a button — or let it run automatically — and watch Email, Phone, LinkedIn, and Instagram columns populate themselves.

No Credit Card Required Free Credits Included Apps Script, n8n & Make.com Ready

Instant cloud setup • CSV & JSON export • Test live website scraper for free & view docs

Frequently Asked Questions

Yes. The Apps Script runs entirely within Google's infrastructure and works on both free Gmail accounts and Google Workspace (G Suite) accounts. Workspace accounts have an extended execution limit of up to 30 minutes, making it suitable for larger URL lists.

Yes. The n8n upsert approach matches on the Website field, so existing records are updated with fresh enrichment data rather than duplicated. This is ideal for monthly re-enrichment cycles where you want to refresh stale contact data in place.

For lists larger than 300 URLs, use the Make.com or n8n webhook approach. Alternatively, in Apps Script you can store the job_id in Script Properties and run a separate time-based trigger every minute to check job status and write results without a single long execution.

Yes. Zapier's "Webhooks by Zapier" trigger step catches the website_job.completed payload in exactly the same way as Make.com's custom webhook module. You then use a Zapier HTTP action to fetch the CSV and a Google Sheets or Airtable action to write the enriched columns.