Send Discord Webhooks from Google Sheets (Apps Script)
Send Discord notifications from Google Sheets using Apps Script. Trigger on edits and form submissions, post rich embeds, and avoid rate limits — with copy-paste code.
🇷🇺 Also available in Русский
Why Connect Google Sheets to Discord?
Google Sheets is where a lot of teams collect data: form responses, sign-ups, orders, inventory, bug reports. Apps Script lets you push that data to a Discord channel the moment a row changes or a form is submitted — turning a spreadsheet into a live notification feed with no server and no paid tools.
This guide uses Google Apps Script and its built-in UrlFetchApp to send Discord webhooks, with triggers for both edits and form submissions, plus rich embeds.
Step 1: Get a Discord Webhook URL
In Discord: Server Settings → Integrations → Webhooks → New Webhook, choose a channel, and click Copy Webhook URL. New to webhooks? Read the setup guide first.
Step 2: Open the Apps Script Editor
In your spreadsheet, go to Extensions → Apps Script. Delete any placeholder code and paste the function below. Store the webhook URL in Script Properties so it isn’t hardcoded in shared scripts:
- In the editor sidebar: Project Settings → Script Properties → Add script property.
- Name it
DISCORD_WEBHOOK_URLand paste your URL as the value.
function getWebhookUrl() {
return PropertiesService.getScriptProperties().getProperty('DISCORD_WEBHOOK_URL');
}
function sendToDiscord(payload) {
const options = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload),
muteHttpExceptions: true,
};
const response = UrlFetchApp.fetch(getWebhookUrl(), options);
const code = response.getResponseCode();
if (code >= 400) {
Logger.log('Discord error ' + code + ': ' + response.getContentText());
}
}
muteHttpExceptions: true lets you read Discord’s error body instead of the script throwing — useful for debugging a 400 or 429.
Step 3: Send a Test Message
Add a quick test function, select it in the toolbar dropdown, and click Run. The first run asks you to authorize the script — approve it.
function testWebhook() {
sendToDiscord({ content: 'Hello from Google Sheets!' });
}
A message in your Discord channel confirms the connection works.
Step 4: Notify on Every Edit
To fire a Discord message whenever someone edits the sheet, use an installable onEdit trigger. (A simple onEdit can’t reliably call external URLs, so an installable trigger is required for UrlFetchApp.)
function onEditNotify(e) {
const sheet = e.range.getSheet();
const row = e.range.getRow();
const editedCell = e.range.getA1Notation();
const newValue = e.value || '(cleared)';
sendToDiscord({
embeds: [
{
title: 'Sheet Updated',
color: 5793266,
fields: [
{ name: 'Sheet', value: sheet.getName(), inline: true },
{ name: 'Cell', value: editedCell, inline: true },
{ name: 'New Value', value: String(newValue), inline: false },
],
footer: { text: 'Row ' + row },
},
],
});
}
Register the trigger once:
- In the editor: Triggers (clock icon) → Add Trigger.
- Function:
onEditNotify. Event source: From spreadsheet. Event type: On edit. - Save (authorize if prompted).
Now every edit posts a color-coded embed. Design the layout visually in the Discord Webhook Builder and copy the field structure into your script.
Step 5: Notify on Google Form Submissions
If your sheet is linked to a Google Form, post each response automatically. Use an On form submit trigger pointed at this function:
function onFormSubmitNotify(e) {
const values = e.values; // array of answers in column order
const headers = e.range.getSheet().getRange(1, 1, 1, values.length).getValues()[0];
const fields = headers.map((header, i) => ({
name: String(header || 'Field ' + (i + 1)),
value: String(values[i] || '—'),
inline: false,
}));
sendToDiscord({
embeds: [
{
title: 'New Form Submission',
color: 5763719,
fields: fields.slice(0, 25), // Discord allows max 25 fields
},
],
});
}
Register it under Triggers → Add Trigger → Event type: On form submit. Each submission now arrives in Discord as a tidy embed with every answer as a field. The slice(0, 25) guard respects Discord’s field limit.
Step 6: Send Scheduled Summaries
A time-driven trigger can post a daily or weekly digest — for example, a row count or sum. Create a function and schedule it under Triggers → Add Trigger → Time-driven:
function dailySummary() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
const rows = sheet.getLastRow() - 1; // minus header
sendToDiscord({
embeds: [
{
title: 'Daily Summary',
description: 'Total records: **' + rows + '**',
color: 16753920,
},
],
});
}
Avoiding Rate Limits
A Discord webhook accepts about 30 requests per minute. If you bulk-import hundreds of rows and trigger a send per row, you’ll hit 429. To stay safe:
- Batch many rows into a single message rather than one webhook per row.
- Add
Utilities.sleep(1200)between sends in a loop to space them out. - For large dumps, summarize (“42 new rows added”) instead of posting each one.
Troubleshooting
| Problem | Cause & Fix |
|---|---|
Authorization required | Run the function once manually and approve the OAuth prompt. |
| Nothing posts on edit | You used a simple trigger — switch to an installable onEdit trigger. |
400 in the logs | Invalid embed (e.g. empty field value or hex color). See the error guide. |
429 during import | You’re sending too fast — batch rows or add Utilities.sleep. |
| Works once, then stops | Webhook may have been deleted/regenerated — paste a fresh URL into Script Properties. |
Next Steps
Your spreadsheet now talks to Discord in real time. Build and preview your embed layout in the free Discord Webhook Builder, then paste the JSON structure into your Apps Script. For more automation ideas, see webhook notifications and automation workflows.
Related Articles
- Discord Webhook Setup — Complete Guide in 2 Minutes — Create your webhook URL
- Complete Guide to Discord Embed Formatting — Design rich embeds
- Discord Embed Limits Cheat Sheet — Stay within field and character limits
- Discord Webhook Errors: 400, 401, 403, 404, 429 — Fix a failing send
Try it in our tool
Open Discord Webhook Builder