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.

By Archit Tamrakar · · 7 min read

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

  1. 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.)
  2. In the app settings, click Incoming Webhooks.
  3. Turn on Activate Incoming Webhooks.
  4. Click Add New Webhook to Workspace.
  5. Pick the channel and click Authorize.
  6. 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

  1. Open your Google Sheet.
  2. Click Extensions > Apps Script. Verify this step: the menu may differ in your version of Sheets.
  3. Delete the sample code and paste the script below.
  4. Replace the placeholder with your webhook URL, and change Sheet1 if your tab has another name.
  5. Click Save, then choose sendNewRows in 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

  1. In the Apps Script editor, click Triggers on the left.
  2. Click Add Trigger at the bottom right.
  3. Choose sendNewRows as the function.
  4. 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.
  5. 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.

  1. In Zapier, create a new Zap.
  2. Choose Google Sheets as the trigger app and New or Updated Spreadsheet Row as the event.
  3. Connect your Google account, then pick the spreadsheet and worksheet.
  4. Choose Slack as the action app and Send Channel Message as the event.
  5. Connect your Slack account, pick the channel, and build the message text from the sheet columns.
  6. 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.

MethodCostDifficultyLimitsBest for
Apps Script + webhookNo extra feeMedium (paste and run)Google quotas, about 1 message per second per channelCustom messages, filtering by column values
ZapierFree plan, as of 13 October 2026Easy100 tasks a month, 15-minute polling, no Filters on FreePeople 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.

ErrorWhat it meansFix
invalid_payloadThe request body is malformedUse JSON.stringify and contentType: 'application/json'
no_textThe text field is missingMake sure your payload has a text key
no_serviceThe webhook is disabled, removed or invalidCreate a new webhook and update the URL
channel_is_archivedThe channel was archivedUnarchive it or create a webhook for another channel
posting_to_general_channel_deniedPosting to #general is restrictedUse another channel or ask an admin
HTTP 429You exceeded the rate limitWait 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_prohibited error 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

  1. Sending messages using incoming webhooks, Slack (2026-10-13)
  2. Rate limits, Slack (2026-10-13)
  3. Quotas for Google Services, Google for Developers (2026-09-03)
  4. Installable Triggers, Google for Developers (2026-09-03)
  5. UrlFetchApp, Google for Developers (2026-05-15)
  6. Google Sheets and Slack integrations, Zapier (2026-10-13)
  7. Zapier pricing, Zapier (2026-10-13)