Claude API Google Sheets Automation Script Guide
Why connect Claude to Google Sheets
If you're searching for a "claude api google sheets automation script," you're probably trying to do one of three things: classify or tag rows of data, summarize long text columns, or generate new content (descriptions, replies, translations) directly inside a spreadsheet without copy-pasting into a chat window. All three are solvable with a small script that calls the Claude API from Google Apps Script or from an external Python job that reads and writes to Sheets via the Google Sheets API.
This guide covers both approaches: a native Apps Script function you can trigger from a menu or a custom formula, and a Python script for batch jobs that run outside the Sheets environment (better for large datasets, scheduled runs, or anything you don't want timing out inside Google's execution limits).
Option 1: Google Apps Script with a custom function
Apps Script runs inside your spreadsheet and can call any HTTPS API with UrlFetchApp. This is the fastest way to get a working =CLAUDE() formula for your cells.
Open Extensions → Apps Script from your sheet and add:
function callClaude(prompt) {
const url = "https://api.subtoapi.app/v1/messages";
const payload = {
model: "claude-sonnet-4",
max_tokens: 300,
messages: [{ role: "user", content: prompt }]
};
const options = {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + PropertiesService.getScriptProperties().getProperty("SUBTOAPI_KEY")
},
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
return data.content[0].text;
}
function CLAUDE(prompt) {
return callClaude(prompt);
}
Store your key in Project Settings → Script Properties instead of hardcoding it. Once saved, you can use =CLAUDE(A2) in any cell to send that cell's content to Claude and return the response. This works well for row-by-row tasks like sentiment tagging, lead scoring, or rewriting product descriptions.
A few practical notes:
- Apps Script custom functions have a 30-second execution limit per cell, so keep
max_tokensmodest for formulas that run across many rows at once. - Sheets recalculates custom functions when the sheet opens or inputs change, which can burn through API calls fast. For high-volume sheets, trigger the script manually from a menu item instead of using it as a live formula.
- If you need streaming responses or tool use for more complex automations, those aren't practical inside a single-cell formula — better suited to the batch script below.
Option 2: A menu-triggered batch script for whole columns
For processing hundreds of rows at once, loop through a range instead of calling the API per-formula recalculation:
function processColumn() {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getRange("A2:A200");
const values = range.getValues();
const output = [];
for (let i = 0; i < values.length; i++) {
const text = values[i][0];
if (!text) {
output.push([""]);
continue;
}
output.push([callClaude("Summarize in one sentence: " + text)]);
Utilities.sleep(300); // basic rate limiting
}
sheet.getRange(2, 2, output.length, 1).setValues(output);
}
function addMenu() {
SpreadsheetApp.getUi()
.createMenu("Claude Tools")
.addItem("Summarize Column A", "processColumn")
.addToMenu();
}
Add addMenu() as a trigger on onOpen and you get a one-click batch job that writes results into column B, with a small delay between calls to avoid hitting rate limits.
Option 3: Python script with gspread for scheduled jobs
If you want this running as a cron job, a GitHub Action, or a Lambda function rather than inside Apps Script's sandbox, use gspread to read/write the sheet and a standard HTTP call for the API.
import gspread
import requests
import os
import time
gc = gspread.service_account(filename="credentials.json")
sheet = gc.open("Customer Feedback").sheet1
rows = sheet.get_all_values()
headers = requests.utils.default_headers()
API_KEY = os.environ["SUBTOAPI_KEY"]
for i, row in enumerate(rows[1:], start=2):
text = row[0]
if not text:
continue
response = requests.post(
"https://api.subtoapi.app/v1/messages",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "claude-sonnet-4",
"max_tokens": 200,
"messages": [{"role": "user", "content": f"Classify sentiment (positive/neutral/negative): {text}"}]
},
)
result = response.json()["content"][0]["text"]
sheet.update_cell(i, 2, result)
time.sleep(0.5)
This approach handles larger datasets more reliably since it isn't bound by Apps Script quotas, and it's easier to add retry logic, logging, or move the job to a scheduler.
Why go through SubToAPI instead of the raw Claude API
Scripts like these work with any Claude-compatible endpoint, but if your Claude access is through a subscription rather than a direct API account, you don't have a standard API key to put in Authorization: Bearer. SubToAPI turns your existing Claude access into an HTTPS API with its own sub_live_... keys, so the exact code above works without modification — just generate a key after signing up and swap it into SUBTOAPI_KEY.
It also gives you usage metadata per key, which is useful when a Sheets automation is running unattended: you can see exactly how many requests and tokens a scheduled job burned through without digging into spreadsheet logs. Check the docs and quickstart for the request format, or the messages reference for parameters like max_tokens and model.
Choosing between formulas and batch scripts
Use a custom =CLAUDE() formula when you want quick, ad hoc processing on a handful of cells and don't mind Sheets' recalculation behavior. Use a menu-triggered or external batch script when you're processing dozens or hundreds of rows, need rate limiting, or want the job to run on a schedule outside the browser. For anything involving streaming output or tool calls — like having Claude query external data mid-response — a server-side script is the only practical option; see streaming and tools for how those work.
questions
Can I call the Claude API directly from a Google Sheets formula? Yes, using Apps Script's UrlFetchApp inside a custom function, which you can then call like any other formula, e.g. =CLAUDE(A2). Keep requests small since custom functions have execution time limits.
How do I avoid hitting rate limits when processing many rows? Add a short delay (Utilities.sleep() in Apps Script or time.sleep() in Python) between API calls, and batch larger jobs through a menu-triggered script or external cron job rather than a live recalculating formula.
Do I need a Claude API key, or does my Claude subscription work? A subscription alone doesn't give you a standard API key. SubToAPI generates one from your existing Claude access at /signup so you can use the same request format shown above; see /pricing for plan details.