How to Send Slack Messages From Google Sheets (Free Apps Script Method and Zapier)
Send Slack messages from Google Sheets for free with a Slack webhook and Apps Script, or use Zapier. Copy-paste code, limits and fixes included.
Quick answer: Create a Slack incoming webhook, then paste a short Google Apps Script into your sheet that posts to it. Free? Yes. Time: about 15 minutes.
The webhook is a private web address. Your script sends a small block of text to it, and Slack replies with HTTP 200 and the word ok when the message lands in your channel. If you would rather not touch code, Method 2 below uses Zapier.
What do you need before you start?
You need three things: a Google account that can edit the sheet, a Slack workspace where you are allowed to add apps, and a channel for the messages.
- If your Slack admin has blocked app creation, the webhook step will fail. Ask the admin to create the webhook for you.
- For a private channel, Slack says you must first be in that channel before you can pick it.
- Lay out your sheet with one row per message. This guide uses columns A to D: Name (A), Detail (B), Status (C) and Sent (D, left empty).
How do you send Slack messages from Google Sheets with Apps Script? (Method 1: free)
You create a Slack webhook, copy its URL, and call it from Apps Script with UrlFetchApp.fetch. Every step below follows Slack's webhook guide unless noted.
Part A: create the webhook
- Go to api.slack.com/apps and create a new app, then pick a name and your workspace and click Create. (You can reuse an existing app instead.)
- In the app settings, click Incoming Webhooks.
- Turn on Activate Incoming Webhooks.
- Click Add New Webhook to Workspace.
- Pick the channel and click Authorize.
- Copy the new URL from Webhook URLs for Your Workspace. It looks like
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX.
Slack says the URL is specific to a single user and a single channel, and that you cannot override the channel, username or icon in the message. Treat the URL like a password.
Part B: add the script
- Open your Google Sheet.
- Click Extensions > Apps Script. Verify this step: the menu may differ in your version of Sheets.
- Delete the sample code and paste the script below.
- Replace the placeholder with your webhook URL, and change
Sheet1if your tab has another name. - Click Save, then choose
sendNewRowsin the function drop-down and click Run. Approve the permission prompt the first time.
// Posts one Slack message per row that has no timestamp in column D.
const WEBHOOK_URL = 'PASTE_YOUR_SLACK_WEBHOOK_URL_HERE'; // placeholder, never share the real one
const SHEET_NAME = 'Sheet1';
function sendNewRows() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
const rows = sheet.getDataRange().getValues();
for (let i = 1; i < rows.length; i++) { // row 0 is the header
const name = rows[i][0];
const detail = rows[i][1];
const status = rows[i][2];
const alreadySent = rows[i][3];
if (!name || alreadySent) continue;
const payload = {
text: '*' + name + '*\n' + detail + '\nStatus: ' + status
};
const response = UrlFetchApp.fetch(WEBHOOK_URL, {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload),
muteHttpExceptions: true
});
if (response.getResponseCode() === 200) {
sheet.getRange(i + 1, 4).setValue(new Date()); // mark as sent
} else {
Logger.log('Row ' + (i + 1) + ' failed: ' + response.getContentText());
}
Utilities.sleep(1100); // stay near Slack's one-message-per-second guidance
}
}
Google documents that fetch accepts method, contentType, payload and muteHttpExceptions as advanced parameters. With muteHttpExceptions set to true, a failed request returns a response instead of stopping the script, so you can log the error text. The *bold* wrapper around the name is Slack's own formatting: *text* is bold, and links use <https://example.com|Label>.
Part C: run it automatically
- In the Apps Script editor, click Triggers on the left.
- Click Add Trigger at the bottom right.
- Choose
sendNewRowsas the function. - Pick the event type. For a check every few minutes, choose a time-driven trigger. To react when someone edits the sheet, choose the edit event. Verify this step: the exact drop-down labels may differ.
- Click Save.
Use an installable trigger rather than a function named onEdit. Google lists "they can call services that require authorization" as an advantage of installable triggers, and a web request is such a service. Installable triggers run under the account of the person who created them.
Method 2: How do you connect Google Sheets to Slack with Zapier?
Build a two-step Zap: a Google Sheets trigger followed by a Slack action. Zapier lists New or Updated Spreadsheet Row as a Sheets trigger, described as "Triggers when a new row is added or modified in a spreadsheet", and Send Channel Message as a Slack action.
- In Zapier, create a new Zap.
- Choose Google Sheets as the trigger app and New or Updated Spreadsheet Row as the event.
- Connect your Google account, then pick the spreadsheet and worksheet.
- Choose Slack as the action app and Send Channel Message as the event.
- Connect your Slack account, pick the channel, and build the message text from the sheet columns.
- Test the Zap, then publish it.
The trade-off is speed and volume. As of 13 October 2026, Zapier's pricing page lists the Free plan with 100 tasks a month, two-step Zaps and a 15-minute polling time. Filters and Paths are paid features. If you only want a Slack message when a status column says "Urgent", the Free plan cannot filter, so your script is the better fit.
Which method should you choose?
Pick Apps Script if you want it free and are happy to paste code once. Pick Zapier if you want no code and can live with a 15-minute delay on the Free plan.
| Method | Cost | Difficulty | Limits | Best for |
|---|---|---|---|---|
| Apps Script + webhook | No extra fee | Medium (paste and run) | Google quotas, about 1 message per second per channel | Custom messages, filtering by column values |
| Zapier | Free plan, as of 13 October 2026 | Easy | 100 tasks a month, 15-minute polling, no Filters on Free | People who do not want to touch code |
If your data comes from a form instead of typed rows, see how to send Google Form responses to Slack.
What's free and what costs money?
The webhook and the script cost nothing extra, but both have published limits. All figures are as of the dates shown.
- Slack: Slack lists incoming webhooks at 1 per second, with short bursts above that allowed. Slack does not publish exact burst limits and recommends designing for one request per second.
- Apps Script URL Fetch: Google's quota page (last updated 3 September 2026) lists 20,000 calls a day for consumer accounts and 100,000 for Google Workspace accounts.
- Apps Script trigger runtime: 90 minutes a day on a consumer account and 6 hours on Workspace. Each execution can run 6 minutes, and you can have 20 triggers per user per script.
- Zapier Free: 100 tasks a month, as of 13 October 2026. Zapier says failed actions are not counted as tasks.
One message per row, sent one second apart, means a 300-row backlog takes about five and a half minutes, which fits inside a single 6-minute execution only barely. For bigger batches, send fewer, longer messages.
What can go wrong, and how do you fix it?
Most failures come from a bad payload, a revoked URL or the rate limit. Slack documents the error strings below.
| Error | What it means | Fix |
|---|---|---|
invalid_payload | The request body is malformed | Use JSON.stringify and contentType: 'application/json' |
no_text | The text field is missing | Make sure your payload has a text key |
no_service | The webhook is disabled, removed or invalid | Create a new webhook and update the URL |
channel_is_archived | The channel was archived | Unarchive it or create a webhook for another channel |
posting_to_general_channel_denied | Posting to #general is restricted | Use another channel or ask an admin |
| HTTP 429 | You exceeded the rate limit | Wait for the Retry-After seconds, then slow your loop |
Two more problems come up often. If nothing happens when you edit a cell, you probably used a plain onEdit function instead of an installable trigger. If the script asks for permission and then stops, run it once by hand from the editor so Google can show the consent screen. The script needs the script.external_request permission, which Google lists for UrlFetchApp.
Is this allowed?
Yes. Incoming webhooks are Slack's documented way to post messages from outside systems, and Apps Script's UrlFetchApp is Google's documented way to call them. Some limits still apply.
- Your Slack admin can restrict posting. The
action_prohibitederror means an admin has blocked this way of posting. - Do not put customer data in messages if the channel includes people who should not see it. Anything in the sheet row can end up in Slack.
- Do not share the webhook URL. Anyone who has it can post to your channel.
For email alerts from the same sheet, see how to send emails from Google Sheets automatically. For phone alerts, see Google Sheets alerts on WhatsApp.
What's still unclear?
Slack does not publish exact burst limits, so a fast loop may be throttled earlier or later than expected.
The weakest point of the script method is that the webhook URL sits inside the script. Anyone who can edit the sheet can read it. If many people edit your sheet, give edit access sparingly or create a separate sheet for the automation.
Last checked: 13 October 2026.
Frequently asked questions
Can Google Sheets send a message to Slack by itself?
Not with a built-in formula or menu item. Sheets needs a small script or an automation tool to make the request. The free route is a Slack incoming webhook URL plus a short Google Apps Script that posts to it. The no-code route is a tool such as Zapier, which watches the sheet and posts to a channel for you.
Is it free to send Slack messages from Google Sheets?
The Apps Script method has no extra fee. Incoming webhooks and Apps Script both work without a paid add-on, and Google publishes daily quotas for free Gmail accounts. Zapier has a Free plan with 100 tasks a month as of 13 October 2026. Check each vendor's current plan page, because limits change.
How do I send a message to a different Slack channel?
A webhook URL is tied to one channel, and Slack says you cannot override that channel in the message. To post to a second channel, create a second webhook with Add New Webhook to Workspace, pick the other channel, and store that URL in your script as a separate constant.
Why does my script say invalid_payload?
Slack returns invalid_payload when the request body is malformed, such as broken JSON. In Apps Script, wrap your object in JSON.stringify and set contentType to application/json. Without that, the object is sent as form fields and Slack cannot read it.
Can I send a Slack message every time someone edits a cell?
Yes, but use an installable trigger, not the plain onEdit function. Google says installable triggers can call services that require authorization, which a webhook request needs. Set one up under Triggers, Add Trigger, and choose the edit event.
Is the webhook URL safe to share?
No. Anyone with the URL can post to your channel. Slack says it searches for and revokes leaked secrets, so a URL pasted in a public place may stop working. Keep it out of public repositories and shared sheets that people outside your team can open.
Sources
- Sending messages using incoming webhooks, Slack (2026-10-13)
- Rate limits, Slack (2026-10-13)
- Quotas for Google Services, Google for Developers (2026-09-03)
- Installable Triggers, Google for Developers (2026-09-03)
- UrlFetchApp, Google for Developers (2026-05-15)
- Google Sheets and Slack integrations, Zapier (2026-10-13)
- Zapier pricing, Zapier (2026-10-13)