// Forms · Apps Script

Clear all responses from a form in Google Forms.

How to delete all form responses in Google Forms using Apps Script, including clearing the linked spreadsheet so your reset is actually complete.

I need to wipe all collected responses from a Google Form before re-running a survey or event registration, and I want it done in one script rather than clicking through the UI every time.

The script

copy · paste · trigger
clearFormResponses.gs
Apps Script
// clearFormResponses.gs
// Deletes all responses from the Form store AND the linked Sheet.
// Run from the Apps Script editor bound to the Form, or as a standalone
// script by supplying the form ID in FORM_ID.

function clearAllResponses() {
  var form = FormApp.getActiveForm();

  // Wipe the Form's own response store
  form.deleteAllResponses();

  // Also clear the linked spreadsheet, if one exists
  var destId = form.getDestinationId();
  if (destId) {
    var ss = SpreadsheetApp.openById(destId);
    var sheet = ss.getSheets()[0];
    var lastRow = sheet.getLastRow();
    if (lastRow > 1) {
      sheet.deleteRows(2, lastRow - 1);
    }
  }
}

Need a variant? Gnaw writes a custom version from one sentence — fields, triggers, edge cases handled.

Walkthrough

Why deleteAllResponses isn't the whole job

Google Forms stores responses in two separate places when you have a linked spreadsheet: the Form's own internal response store, and the destination Sheet. The Forms UI button labeled "Delete all responses" hits both. The Apps Script method `deleteAllResponses()` hits only the first one.

The first time I hit this, I was resetting a registration form between event runs. The form showed zero responses, the summary charts were blank, but the spreadsheet still had 47 rows of old data. New responses came in starting at row 48. Downstream formulas expecting a clean slate broke silently.

So a real reset is two operations: call `form.deleteAllResponses()` to clear the Form store, then locate the linked spreadsheet via `form.getDestinationId()` and remove the data rows from the sheet yourself.

What the script actually does, line by line

The script calls `FormApp.getActiveForm()`, which works when the script is bound to the form (opened via Extensions > Apps Script from inside the form). If you're running it standalone, replace that line with `FormApp.openById('YOUR_FORM_ID')` and paste the form's ID from its URL.

`form.getDestinationId()` returns the spreadsheet ID if a response destination is linked, or `null` if the form collects responses only internally. The null check means the script is safe to run on forms with no linked sheet.

`sheet.getSheets()[0]` grabs the first sheet tab, which is always where Forms writes responses. The header row is row 1, so `deleteRows(2, lastRow - 1)` removes every row from row 2 down to the last populated row without touching the column headers. Deleting the header row would break the Forms-to-sheet sync and force you to re-link the destination.

The `lastRow > 1` guard prevents a crash on an already-empty sheet, where `deleteRows(2, 0)` would throw a range error.

Permissions and where to paste this

The script needs two OAuth scopes: `https://www.googleapis.com/auth/forms` and `https://www.googleapis.com/auth/spreadsheets`. Apps Script will prompt for both on first run. If you see an "authorization required" screen, click through it -- it's just Google confirming your own script can touch your own files.

Paste the code into the Apps Script editor bound to your form. Save, then click Run. The first run will ask for permission; subsequent runs (including time-driven triggers) will not. I keep a copy of this in a utils file in every form-heavy project because the need comes up constantly during testing cycles.

If you want this to run on a schedule (for example, wiping a daily feedback form at midnight), add a time-driven trigger from the Triggers panel: clock icon on the left sidebar, set it to "Time-driven > Day timer > Midnight to 1am." The script handles an empty sheet gracefully, so a trigger firing before any responses arrive causes no harm.

Want a custom version?

Describe your sheet and the rule you want. Gnaw writes the Apps Script — fields, triggers, edge cases — in one shot.

FAQ

4 questions
Does deleteAllResponses also delete the linked spreadsheet rows?
No. It clears only the Form's internal response store. The spreadsheet rows stay intact until you delete them separately, which is what the sheet.deleteRows() call in this script handles.
Will this delete my spreadsheet header row?
No. The script calls deleteRows(2, lastRow - 1), which starts at row 2 and leaves row 1 (the header) untouched. The Forms-to-sheet link depends on those headers matching the question titles exactly, so you never want to remove them.
Can I run this on a form I don't own, only edit?
Only if you have edit access to both the form and the linked spreadsheet. The OAuth grant runs as you, so the script can only touch files your Google account is authorized to modify.
What happens if the form has no linked spreadsheet?
getDestinationId() returns null, the if block is skipped, and only the Form store is cleared. The script exits cleanly without touching any spreadsheet.