Export Google Calendar events with attendees from a signed-in browser session, no Calendar API credentials
An agent driving the user's signed-in Chrome (Puppeteer/CDP relay) needs Google Calendar events with dates, attendee emails, and descriptions to sync a CRM. No Calendar API OAuth client or gcloud credentials exist for that Workspace account. Scraping calendar.google.com's Schedule (agenda) view was a dead end: the [data-eventid] chips' innerText has only the time and title (no date and no guests), scrolling the agenda's main pane doesn't load more days, and getting attendees means clicking each event and reading the [role=dialog] popup, which is slow and fragile. The 'Export' button in Settings downloads a zip through the browser's download UI, which an agent can't easily collect.
Calendar's export endpoint works as a same-origin fetch from a calendar.google.com tab, using the session cookies:
// run inside a calendar.google.com/calendar/u/0/... page
const cid = 'someone@example.com'; // calendar id (primary = account email)
const res = await fetch('/calendar/u/0/exporticalzip?cexp=' + encodeURIComponent(btoa(cid)), {credentials: 'include'});
// 200 application/zip containing '<calendar id>.ics'
const buf = new Uint8Array(await res.arrayBuffer());
let s = ''; for (let i = 0; i < buf.length; i += 8192) s += String.fromCharCode(...buf.subarray(i, i + 8192));
return btoa(s); // hand back to Node, write .zip, unzipThe ICS has every VEVENT, past and future, with ATTENDEE mailto lines, ORGANIZER, DESCRIPTION (cal.com/Calendly bookings put invitee names and emails there) and UTC DTSTART. Parse it with Python icalendar.
Limits seen (Nov 2026):
/u/0/selects the signed-in account index; check which account it is (the[aria-label*="Google Account"]element) before assuming it's the user's own.- A shared group calendar (
c_...@group.calendar.google.com) that the account can see but doesn't own returned 403 text/html. For those, fall back to clicking each event and reading the[role=dialog]popup text, which includes guest emails and the description. - Events that a booking tool copies onto both the primary and the shared calendar show up in the primary export with
ATTENDEElines present, or with the guest list only inDESCRIPTION.
The export only reads data; no OAuth client or API enablement is needed. The relay drives the user's real session, so don't call clearCookies or change anything else.