Pick the right method
Which method is quickest depends on how the events got there, and how many of them you want to remove.
| Situation | Best method |
|---|---|
| A handful of events | Delete them in Google Calendar |
| A repeating event you no longer need | Open one occurrence and delete the whole series |
| Everything in a secondary calendar, or a bad import into a calendar made for it | Delete that calendar |
| Many events by date range or by a word in the title, on any calendar | The preview-and-delete script |
| A list of events in a sheet that you want removed, with a preview | CalendarRows |
Google Calendar itself has no way to select several one-off events and delete them together, and its help page describes deleting events one at a time. A Chrome extension called Event Multiselect for Google Calendar adds that. We haven’t tested it, and like any extension it asks for permission to see and edit your calendar, so read what it asks for. The methods in this guide don’t need an extension.
Whatever you choose, work out first which calendar the events are on and how you can describe them: a date range, a word in the title, or a list. Deleting is the one thing in this guide you can’t fully rely on being able to undo, so every method below includes a way to look before you delete.
After a bad import: delete the calendar
The most common reason for bulk deleting is an import that went wrong: a CSV or .ics file with the wrong dates, or one that was imported twice. If those events went into a calendar that you made just for the import, there is nothing to select:
- In Google Calendar on a computer, find the calendar in the left list under My calendars, hover over it, click the three dots, and choose Settings and sharing.
- Scroll to the bottom to Remove calendar and choose Delete. Read the warning: it deletes the calendar and all its events for everyone who has it.
This is also why we suggest importing into a new calendar the first time: if the result looks wrong, deleting the calendar is a one-minute cleanup. Google doesn’t let you delete your primary calendar this way, and the same menu has an Unsubscribe choice for calendars that aren’t yours, which only removes them from your list. If the events were imported into your main calendar, use the script below instead.
Our import guide covers how to bring a spreadsheet in so that it is easy to check and undo.
Delete by date range or keyword with a script
This script works in two steps, on purpose. previewDeletes lists the events that match your date range and keyword in a tab and deletes nothing. You then type yes next to the ones to remove and run deleteMarkedEvents. Open your spreadsheet, choose Extensions → Apps Script, paste this in, change the settings at the top, and save.
// Step 1: previewDeletes() lists matching events in a tab named "Delete preview" and deletes nothing.
// Step 2: change "no" to "yes" in the Delete? column for the events to remove, then run deleteMarkedEvents().
const DEL_CALENDAR_ID = 'primary'; // use a test calendar's ID while you try this
const DEL_FROM = '2026-11-01'; // first day to include (YYYY-MM-DD)
const DEL_TO = '2026-12-01'; // day to stop before (YYYY-MM-DD)
const DEL_SEARCH = ''; // optional: only events whose text contains this, e.g. 'Old offsite'
const DEL_TAB_NAME = 'Delete preview';
const DEL_SKIP_REPEATING = true; // leave occurrences of repeating events alone (delete those in Calendar)
function previewDeletes() {
const ss = SpreadsheetApp.getActive();
const sheet = ss.getSheetByName(DEL_TAB_NAME) || ss.insertSheet(DEL_TAB_NAME);
const found = findEvents_();
const rows = found.events.map(function (e) {
return ['no', e.getTitle(), e.getStartTime(), e.getEndTime(), e.isAllDayEvent(), e.getLocation(), e.getDescription(), e.getId()];
});
sheet.clearContents();
sheet.getRange(1, 1, 1, 8).setValues([['Delete?', 'Title', 'Start', 'End', 'All day', 'Location', 'Description', 'Event ID']]);
if (rows.length) sheet.getRange(2, 1, rows.length, 8).setValues(rows);
sheet.getRange(1, 10).setValue(rows.length + ' events listed, ' + found.skipped + ' repeating skipped. Nothing deleted yet.');
}
function deleteMarkedEvents() {
const ss = SpreadsheetApp.getActive();
const sheet = ss.getSheetByName(DEL_TAB_NAME);
if (!sheet || sheet.getLastRow() < 2) throw new Error('Run previewDeletes first.');
const rows = sheet.getRange(2, 1, sheet.getLastRow() - 1, 8).getValues();
const marked = {};
rows.forEach(function (r) {
if (String(r[0]).trim().toLowerCase() === 'yes') marked[key_(r[7], r[2])] = true;
});
let deleted = 0, failed = 0, lastError = '';
// Look the events up again with the same settings, and delete only the ones that were marked.
findEvents_().events.forEach(function (e) {
if (!marked[key_(e.getId(), e.getStartTime())]) return;
try {
e.deleteEvent();
deleted++;
Utilities.sleep(250); // a short pause keeps Google from rate-limiting a long run
} catch (err) {
failed++;
lastError = String(err.message || err);
}
});
sheet.getRange(1, 10).setValue('Deleted ' + deleted + ' of ' + Object.keys(marked).length + ' marked events on ' + new Date().toString() +
(failed ? '. ' + failed + ' failed (' + lastError + '). Run deleteMarkedEvents again.' : ''));
}
function findEvents_() {
const cal = DEL_CALENDAR_ID === 'primary' ? CalendarApp.getDefaultCalendar() : CalendarApp.getCalendarById(DEL_CALENDAR_ID);
if (!cal) throw new Error('Calendar not found. Check DEL_CALENDAR_ID.');
const from = parseDayDel_(DEL_FROM), to = parseDayDel_(DEL_TO);
if (!from || !to || to <= from) throw new Error('Check DEL_FROM and DEL_TO: use YYYY-MM-DD and put the end after the start.');
const all = cal.getEvents(from, to, DEL_SEARCH ? { search: DEL_SEARCH } : {});
let skipped = 0;
const events = all.filter(function (e) {
if (DEL_SKIP_REPEATING && e.isRecurringEvent()) { skipped++; return false; }
return true;
});
return { events: events, skipped: skipped };
}
function key_(id, start) { return String(id) + '|' + new Date(start).getTime(); }
function parseDayDel_(s) {
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(s).trim());
return m ? new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3])) : null;
}
The settings:
DEL_CALENDAR_ID:'primary'is your main calendar. For another calendar, copy its Calendar ID from Settings and sharing → Integrate calendar. While you are trying the script, use a test calendar.DEL_FROMandDEL_TO: the range asYYYY-MM-DD. The end day is not included, so an end of2026-12-01covers all of November.DEL_SEARCH: leave empty to list everything in the range, or put a word to keep only events whose text matches it.DEL_SKIP_REPEATING:trueleaves occurrences of repeating events alone. See repeating events.
What makes it safer than a one-line loop that deletes everything it finds:
- Nothing is deleted at the preview step. The tab shows the title, start, end, location, description and ID of every match, with
noin the first column. - Only rows marked
yesare deleted. Anything else, including blank cells and typos, is kept. - It looks the events up again at delete time and matches each one on its ID and start time. An event added after the preview, even with the same title, is not deleted, and running the delete step twice does nothing the second time.
- It paces itself and reports failures. It pauses a quarter of a second between deletions so Google is less likely to rate-limit a long run, and the note in column J says how many deletions failed and why, so you can run the delete step again.
- The preview tab is a record. If you made a mistake, the title, time, location and description are right there for you to recreate the event.
We tested the logic with stand-ins for the Calendar and Sheets services. The tests cover the preview deleting nothing, marking with yes in any capitalisation, nothing marked meaning nothing deleted, a repeating event being skipped, an event outside the range being left alone, a new event with the same title being left alone, the search setting, a deletion that fails part-way, and running the delete step twice. Stand-ins are not Google itself, so try it on a test calendar with a few throwaway events before you point it at a real one.
Run it safely
- Make a test calendar in Google Calendar, add three events to it, put its ID in
DEL_CALENDAR_IDand set a range that covers them. - Choose
previewDeletesin the function menu and click Run. Google asks you to authorise the script; the warning that the app isn’t verified is normal for a script you pasted yourself (Advanced, then Go to your project). - Open the Delete preview tab. The note in column J says how many events were listed and how many repeating ones were skipped.
- Change
notoyesin column A for one event, then rundeleteMarkedEvents. Check that exactly that event disappeared. - When that works, set the real calendar and range, run the preview again and read the list properly. Sort it by title and start time and look for anything that shouldn’t be there. Mark the rest
yes, which is quick if you typeyesin the first cell and drag it down. - Run
deleteMarkedEvents. The note in column J says how many were deleted.
If you change the range or the search text after the preview, run the preview again. The delete step uses the settings at the time it runs, and it will skip rows that no longer match.
Repeating events
A repeating event is many events that share one series. A script that works on single events is a poor fit for them, which is why the preview leaves them out by default and reports how many it skipped. To delete a series, open one occurrence in Google Calendar, click the trash icon, and choose All events. Choose This event to remove only that occurrence, or This and following events to end the series from a date.
If you set DEL_SKIP_REPEATING to false, every occurrence in your range gets its own row, and marking a row deletes that occurrence only. For a weekly meeting that ran for a year, that is up to 52 rows, so it is usually easier to end the series in Calendar.
Undoing a deletion
In the Google Calendar web app, an event you delete stays in that calendar’s Trash for 30 days, according to Google’s help page. You open it from the settings menu, and anyone with “Make changes to events” access to the calendar can restore events from it. We couldn’t confirm that events removed by a script are always listed there too, so don’t count on it. Instead:
- Keep the preview tab until you are sure. Duplicate it (right-click the tab, then Duplicate) before you delete, and rename the copy.
- Export a backup first. In Google Calendar, Settings → Import & export → Export downloads your calendars as .ics files you can re-import if something goes wrong.
- Test on a throwaway calendar first, and look in Trash afterwards. That shows you how it behaves for your account.
- Remember that guests lose the event too. Google’s help page says that deleting an event you created takes it off the calendars of everyone invited. If that is not what you want, remove the guests first or check the notification settings. A bulk delete of events with guests is a bulk cancellation.
Without a script: CalendarRows
CalendarRows is our add-on for Google Sheets and Google Calendar. It deletes events in a different way from the script: through rows in a sheet. Each row points to an event by its ID, and a row with delete in the Action column removes that event. You see the numbers before anything happens.
- Install CalendarRows from the Google Workspace Marketplace (the button below), then choose Extensions → CalendarRows → Open CalendarRows.
- On the From Calendar tab, pick the calendar and the date range and import. The events arrive in a new tab with their IDs. The free plan imports up to 100 events at a time.
- In the sheet, delete the rows of events you want to keep, so only the events to remove are left. Add a column headed Action and type
deletein each remaining row. - On the To Calendar tab, pick that sheet, map the Action column and click Preview. It shows how many events will be created, updated, deleted or left unchanged, and lists any problems. Nothing changes yet.
- Click Send to Calendar. Each row gets a status, so you can see what was deleted.
The honest comparison: the script is free, has no daily limit other than Google’s, and can select by keyword inside the script. CalendarRows is a better fit when you want to look at the events in a sheet, sort and filter them yourself, and see a count before you commit, with no code. The free plan allows 50 event changes a day, so a large cleanup needs Pro ($9/month or $59/year) or several days. CalendarRows works from the rows you give it, so it only deletes events that are in your sheet.
Common problems
“Run previewDeletes first”. The preview tab doesn’t exist or is empty. Run previewDeletes, then mark rows, then run deleteMarkedEvents.
The preview is empty. No events match. Check the dates, the calendar ID and the search word. Remember that repeating events are skipped by default, and that the note in column J says how many were.
Deleted 0 of 5 marked events. The events no longer match the settings. The range or search changed after the preview, or they were already deleted. Run the preview again.
“Calendar not found”. The Calendar ID is wrong or your account can’t see that calendar.
An error saying you don’t have permission. You can read the calendar but not change its events. Ask the owner to give you “Make changes to events” access, or ask them to run it.
The note says some deletions failed. Google probably rate-limited the run, or you don’t have permission for those events. Wait a few minutes and run deleteMarkedEvents again: events that are already gone are skipped.
It stops partway with a time-out. Google ends scripts after about six minutes. Run deleteMarkedEvents again; events that are already gone are skipped, and the rest are deleted. For very large cleanups, use a smaller date range.
Guests got cancellation emails. Deleting an event that has guests can send them a cancellation, and as far as we know a script is treated no differently. Next time, remove the guests first or delete only events without guests.
Frequently asked questions
Can I delete multiple events at once in Google Calendar?
Not with a select-many option for ordinary events, as far as we could find when we wrote this. You can delete a whole secondary calendar in one step, or use a script or an add-on to delete a list of events. For repeating events, Google Calendar lets you delete the whole series from one event.
How do I delete all events in a Google Calendar?
If it is a secondary calendar, open its settings and choose Delete calendar, which removes the calendar and every event in it. You can’t delete your primary calendar that way. For the primary calendar, use a script like the one in this guide with a wide date range, and check the preview first.
How do I undo a bulk import of events?
If you imported into a calendar made for the import, delete that calendar. If you imported into your main calendar, list the imported events by date range or keyword with the script in this guide, check the list, then delete them. Next time import into a new calendar first.
Can I get deleted Google Calendar events back?
Google Calendar keeps an event you delete in that calendar’s Trash for 30 days, where you can restore it from the Settings menu. We could not confirm that events removed by a script always land there, so treat the preview tab in this guide as your record, and try it on a test calendar first.
Does the script delete every occurrence of a repeating event?
No. By default it leaves repeating events alone and tells you how many it skipped. Delete a repeating series in Google Calendar by opening one occurrence and choosing the whole series. Setting DEL_SKIP_REPEATING to false lists each occurrence separately, and deleting a marked one removes that occurrence.
Will the script delete events on other people’s calendars?
It can only delete events your account is allowed to delete. On a calendar you can only read, the delete step will fail. On a shared calendar where you can edit events, it can delete events other people created, so check the preview carefully.
Is there a limit on how many events I can delete?
Google limits how long a script can run (about six minutes per run) and how much work it can do per day. A few hundred events is fine. For thousands, run it on smaller date ranges, one after another.
Related
- How to import a spreadsheet into Google Calendar
- How to export Google Calendar to Google Sheets
- How to sync Google Sheets with Google Calendar
- Repeating events from Google Sheets to Google Calendar
- CalendarRows documentation
- All guides
Disclosure: we make CalendarRows, the Google Sheets add-on mentioned in this guide. The script here works without it, and we say where the add-on is the better fit.
Google Sheets, Google Calendar and Google Workspace are trademarks of Google LLC. CalendarRows and Cellbrook are not affiliated with or endorsed by Google.