.ICS iCalendar
.ics

iCalendar

An ICS file is plain-text calendar data per RFC 5545 (IETF, 1998) — every calendar app from Google to Apple to Outlook reads it, but each interprets recurrence rules and time zones slightly differently.

File structure
BEGIN:VCALENDAR
VEVENT
RRULE
VTIMEZONE
MetadataText
Not convertible

ICS conversion is not yet available in FileDex. For now, use the CLI commands in the Developer Door to convert between calendar formats with python-icalendar or grep.

Common questions

How do I open an .ics file?

Double-click the file to open it in your default calendar app — Google Calendar (web), Apple Calendar (Mac/iOS), Microsoft Outlook (Windows/Mac), or Mozilla Thunderbird. ICS is plain text, so any text editor (Notepad, TextEdit, VS Code) shows the raw structure if you want to inspect it directly.

How do I add an .ics file to Google Calendar?

Open Google Calendar in your browser. Click the gear icon → Settings → Import & Export → Import. Select the .ics file and choose which calendar to add the events to. You can also drag the .ics file directly onto the Google Calendar interface. For recurring subscriptions, use 'From URL' under Other calendars.

What is the difference between ICS and CalDAV?

ICS is the file format that stores calendar events as plain text per RFC 5545. CalDAV (RFC 4791) is the HTTP-based sync protocol that calendar apps use to keep events synchronized with a server. CalDAV is not an alternative to ICS — CalDAV uses ICS as its data payload. The format is the message; the protocol is the post office.

Why does my ICS event show the wrong time after import?

ICS times can be expressed three ways: with a Z suffix (UTC, unambiguous), with a TZID parameter (local time in a named timezone), or with no timezone (floating time interpreted in the viewer's local timezone). When the source uses a TZID the destination calendar doesn't recognize, or when DST rules differ between source and destination, events shift hours.

How do I subscribe to a calendar feed instead of downloading a file?

Use a `webcal://` URL or paste an HTTPS URL ending in .ics into your calendar app's 'Add calendar by URL' option. Google Calendar: Other calendars → From URL. Apple Calendar: File → New Calendar Subscription. Outlook: Add calendar → Subscribe from web. The feed refreshes on the interval set by the server's REFRESH-INTERVAL property, so holiday calendars, sports schedules, and subscription events update automatically without re-downloading.

What makes .ICS special

26 years of one format
vCalendar 1.0 in 1996, still text/calendar today
The Internet Mail Consortium published vCalendar 1.0 in 1996. RFC 2445 standardized it as iCalendar at the IETF in 1998. RFC 5545 obsoleted RFC 2445 in 2009. The .ics file syntax has not changed since.
RRULE: 7 free parameters
One line encodes a year of meetings
FREQ × BYDAY × BYMONTHDAY × BYSETPOS × INTERVAL × COUNT × UNTIL combinations express 'last Friday of every month' or 'every Mon/Wed/Fri until 2027.' The combinatoric expansion is why ical.js and python-icalendar are each thousands of lines of recurrence logic.
Ten years, one parameter ignored
RSCALE added in 2015. Most calendar apps still drop it.
RFC 7529 lets recurring events reference Hebrew, Chinese, Islamic, Ethiopic, or Indian calendars. Apple Calendar has basic support; Google, Outlook, and most CalDAV servers silently discard the parameter on import — forcing every culture with a non-Gregorian calendar onto manual workarounds.
Lebanon ran in two time zones
March 2023 split-DST broke .ics scheduling for 4 days
When the Lebanese government postponed DST for Ramadan and Christian leaders refused, Lebanon spent 26-29 March 2023 in 'Christian Time' and 'Muslim Time' simultaneously. Aviation, telecoms, and hospitals all broke. ICS timezone parsers were one of the casualties.

Click any 'Add to Calendar' button on the web. The download is a small text file beginning BEGIN:VCALENDAR — bytes that every calendar app in the world knows how to read, and every calendar app in the world reads slightly differently. That divergence is the iCalendar story.

Continue reading — full technical deep dive

Every Calendar App Reads ICS. None Agree On What Happens Next. Why?

The iCalendar format is universal. Apple Calendar, Google Calendar, Microsoft Outlook, Mozilla Thunderbird, and every CalDAV server speak text/calendar natively. Drop a .ics file into any of them and it imports without conversion.

What is not settled is what the calendar app does next.

A VCALENDAR container holds one or more components: VEVENT for meetings, VTODO for tasks, VJOURNAL for journal entries, VFREEBUSY for availability lookups, VTIMEZONE for timezone definitions, and VALARM for reminders nested inside events. Every component is delimited by BEGIN:NAME and END:NAME markers. The required PRODID line — PRODID:-//Google Inc//Google Calendar 70.9054//EN — fingerprints the application that produced the file.

Take the same .ics file and import it into Google, Apple, and Outlook. The event arrives in all three. Reminders may arrive in two of them. Attendee status may be parsed in one. iTIP scheduling verbs (METHOD:REQUEST, METHOD:REPLY, METHOD:CANCEL per RFC 5546) are interpreted differently by each implementation. The format is universal; the behavior is local. This is the canonical iCalendar problem: every app reads ICS, none agree on edge cases. Simple events expose the gap. Recurring events widen it.

One Line Encodes a Year of Meetings. Why Is RRULE the Hardest Sentence in the Spec?

RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20271231T235959Z is one line. It also encodes a date set that calendar apps must compute correctly across decades, time zones, and exception lists.

The recurrence rule grammar gives you seven free parameters. FREQ chooses the base frequency (SECONDLY through YEARLY). INTERVAL multiplies the gap. COUNT or UNTIL bounds the series. BYDAY, BYMONTHDAY, BYMONTH, BYYEARDAY, BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND, and BYSETPOS narrow the set. Combining them produces 'every other Tuesday in months with 31 days' or 'the last weekday of each quarter' — patterns that look reasonable in English and look like dense math in RRULE syntax.

EXDATE removes specific instances. RECURRENCE-ID overrides a single instance with a different DTSTART. RDATE adds one-off occurrences that don't match the main rule.

The combinatoric expansion is why ICS parsing libraries are not small. ical.js and python-icalendar each ship thousands of lines just to expand recurrence sets correctly, and corner cases — BYDAY=FR;BYMONTHDAY=13 for Friday-the-13th, daylight-saving boundaries inside an INTERVAL=3 monthly rule, leap-day annual events on February 29 — still produce calendar bug reports decades after RFC 5545. Once the date set is computed correctly, the time zone still has to resolve — and that is where spec mechanics collide with politics.

A 9 AM Beirut Meeting Landed at Two Different UTC Moments in 2023. How?

A meeting at 9 AM in Beirut on 26 March 2023 happened at two different UTC instants depending on which faction of the Lebanese government you trusted.

ICS gives an event three ways to express a time. Add a Z suffix — DTSTART:20260415T060000Z — and the time is unambiguous UTC. Reference a TZID — DTSTART;TZID=Europe/Paris:20260415T090000 — and the time is local to that named timezone, which the parser must look up either in an embedded VTIMEZONE block or in the Olson database. Skip both and you have a 'floating time' — interpreted in whatever local timezone the viewer happens to be in.

Most cross-region scheduling complications are timezone definition disputes, not ICS spec failures. Countries that don't observe DST — Japan (UTC+09:00), India (UTC+05:30), most of Africa — are the easy case. Egypt reintroduced DST on 28 April 2023 after a decade of suspension — every Egypt-tagged ICS event from before that date may now decode wrong if the parser used a stale Olson database. Lebanon's March 2023 chaos was worse: the prime minister postponed DST to keep mornings shorter during Ramadan, Christian leaders rejected the decision, and for ~4 days Lebanon ran in two simultaneous time zones — 'Christian Time' (UTC+03:00) and 'Muslim Time' (UTC+02:00). Aviation systems, telecoms, and hospital scheduling all broke. iCalendar's flexibility — three valid ways to write a time — became the problem. Time zones are a tooling problem. Which days count as which is the deeper one.

RFC 7529 Added Non-Gregorian Recurrence in 2015. Why Does Every App Still Ignore It?

Chinese New Year moves every year by lunar calculation. Passover shifts through March and April by the Hebrew calendar. Diwali lands on a different Gregorian date each fall. Ramadan rotates backward eleven days annually through the Hijri calendar. None of these can be expressed as a simple RRULE.

ICS hardcodes the Gregorian calendar in DTSTART. RFC 7529 (2015) added the RSCALE parameter so recurring events could reference non-Gregorian calendars — Hebrew, Chinese, Islamic-Civil, Ethiopic, Indian. Ten years later, most calendar apps still ignore the parameter. Apple Calendar has basic RSCALE support. Google Calendar lacks server-side handling. Outlook, Thunderbird, and most CalDAV servers drop RSCALE silently on import.

The practical consequence: a Jewish community calendar needs a manually-maintained annual EXDATE list for Passover. A Chinese business calendar maintains two parallel subscription feeds — one for Western holidays, one for lunar ones computed offline. An Islamic prayer-time calendar publishes as a static yearly .ics file rather than a recurring rule, because no cross-app recurring rule can express 'five prayers whose times shift with sunrise' reliably.

Every non-Gregorian recurrence across every culture still comes down to Gregorian DTSTART plus externally-computed display at render time. Twenty-six years of iCalendar evolution, ten years after the spec added the fix, and the ecosystem still does not support it. The format met the technical challenge. The implementations never caught up.

.ICS compared to alternatives

.ICS compared to alternative formats
Formats Criteria Winner
.ICS vs .VCARD (VCF)
Domain
ICS handles calendar/scheduling data — events, tasks, recurrence, time zones. VCF handles contact data — names, addresses, phone numbers. Both descend from the IMC's PIM-format work in the late 1990s and share line-folding, content-line, and parameter syntax. They are siblings, not competitors.
Draw
.ICS vs .CALDAV
File vs protocol
ICS is a file format. CalDAV (RFC 4791) is an HTTP/WebDAV-based sync protocol that uses ICS as its native data payload. They are not alternatives — CalDAV requires ICS. Servers like Radicale, Baikal, and Nextcloud store every event as a .ics file inside a calendar collection.
Draw
.ICS vs .GOOGLE CALENDAR API
Cross-vendor portability
ICS is an open IETF standard (RFC 5545) — every calendar app reads it. Google Calendar API is a proprietary REST/JSON interface useful only with Google's calendar service. Even Google Calendar exports as ICS for cross-app portability. JMAP CalendarEvent (RFC 8984) is the modern open-standard JSON alternative, but ICS still wins for vendor neutrality.
ICS wins

Technical reference

MIME Type
text/calendar
Developer
IETF
Year Introduced
1998
Open Standard
Yes — View specification

Binary Structure

ICS is plain UTF-8 text with no binary structure or magic bytes. A valid file begins with the literal text `BEGIN:VCALENDAR` (PRONOM fmt/388 signature) followed by `VERSION:2.0` and a `PRODID` identifying the producing application. Components nest via `BEGIN:NAME` / `END:NAME` markers — VEVENT for events, VTODO for tasks, VJOURNAL for notes, VTIMEZONE for timezone definitions, VALARM for reminders nested inside events. Every line terminates with CRLF; lines longer than 75 octets are folded onto the next line beginning with a single space (a legacy constraint inherited from RFC 822 email). Properties carry optional parameters via `;NAME=VALUE` between the property name and the colon (e.g., `DTSTART;TZID=Europe/Paris:20260417T123000`). Text values escape commas (`\,`), semicolons (`\;`), and newlines (`\n`).

OffsetLengthFieldExampleDescription
Line 1 15 bytes BEGIN marker BEGIN:VCALENDAR Required first line — also serves as content-based identification (PRONOM fmt/388 signature)
Line 2 11 bytes VERSION VERSION:2.0 iCalendar specification version — always 2.0 for RFC 5545 (1.0 was pre-standard vCalendar)
Line 3 variable PRODID PRODID:-//Apple Inc.//macOS 14.5//EN Required product identifier of the application that created the file — fingerprints exporters in calendar diff tools
Last line 13 bytes END marker END:VCALENDAR Required last line — closes the VCALENDAR container
1996Internet Mail Consortium publishes vCalendar 1.0 — first widely-adopted text-based calendar format1998RFC 2445 standardizes iCalendar at the IETF — published years before any consumer iCal app existed2002Apple ships iCal app with Mac OS X 10.2 (Jaguar) — popularizes the .ics file extension among consumers2007RFC 4791 defines CalDAV — WebDAV-based sync protocol that uses ICS as native data payload2009RFC 5545 obsoletes RFC 2445; RFC 5546 published the same year defining iTIP scheduling2011RFC 6321 defines xCal — an XML representation of iCalendar data for services that prefer XML over the native text format2012RFC 6638 defines CalDAV Scheduling Extensions — shifts automatic scheduling from the client to the server via inbox/outbox collections2014RFC 7265 defines jCal — a JSON representation of iCalendar data, easier to consume in modern web applications2015RFC 7529 defines RSCALE for non-Gregorian recurrence (Islamic-civil, Hebrew, Chinese, Hindu)2016RFC 7986 adds calendar publish/subscribe properties — NAME, REFRESH-INTERVAL, COLOR, IMAGE, CONFERENCE — enabling richer subscription feeds2023Lebanon DST chaos — government postpones DST for Ramadan, Christian leaders refuse, Lebanon runs in two simultaneous time zones for 4 days (March 26-29)2023Egypt reintroduces DST after a decade — first observance 28 April, ends 26 October
Count VEVENT components in an ICS file other
grep -c '^BEGIN:VEVENT' events.ics

ICS is plain text, so a single grep counts events without any ICS-aware library. Useful for sanity-checking a calendar export before import.

Extract event summaries (titles) other
grep '^SUMMARY:' events.ics | sed 's/^SUMMARY://'

Extracts the SUMMARY (title) of each event. Combined with grep -A for DTSTART, this gives a quick TSV-like overview of any calendar.

Parse and walk events with python-icalendar other
python3 -c "from icalendar import Calendar; cal=Calendar.from_ical(open('events.ics','rb').read()); [print(e.get('SUMMARY'), e.get('DTSTART').dt) for e in cal.walk('VEVENT')]"

Resolves RRULE recurrence on demand and handles VTIMEZONE blocks correctly. python-icalendar is the reference Python library — pip install icalendar.

ICS conversion is not yet available in FileDex. For now, use the CLI commands in the Developer Door to convert between calendar formats with python-icalendar or grep.

MEDIUM

Attack Vectors

  • Mailto: ATTENDEE auto-reply data leak
  • Oversized RRULE memory exhaustion
  • URL-property phishing
  • VTIMEZONE injection

Mitigation: Open ICS only in trusted calendar apps. Before accepting invites from unknown senders, inspect the .ics in a text editor — suspicious ATTENDEE rows and phishing URLs are visible in plain text. For server-side imports, cap RRULE expansion and disable auto-replies. Treat calendar attachments like any executable. FileDex does not parse ICS — this page is static, no upload.

Apple's calendar app shipped with macOS and iOS. The iCal app released with Mac OS X 10.2 in August 2002 popularized the .ics extension and gave the format its informal name — but RFC 2445 (1998) predates Apple's iCal by four years
Google Calendar service
Google's web-based calendar service — most-used consumer calendar worldwide. Imports and exports ICS files; supports 'From URL' subscriptions for recurring calendar feeds
Microsoft's calendar and email client, dominant in enterprise. Full ICS import/export and iTIP scheduling support across Windows, Mac, web, iOS, and Android
Open-source desktop email and calendar client with native ICS support. Uses ical.js as its parser library; runs on Windows, macOS, Linux
ical.js library
JavaScript library for parsing and generating iCalendar data. Used by Mozilla Thunderbird, ~1.5K GitHub stars, active maintenance
Python library for parsing and generating iCalendar files. The reference Python implementation, ~2.5K GitHub stars
Radicale tool
Lightweight open-source CalDAV server in Python. Stores events as .ics files in per-calendar collections — minimal config, suitable for self-hosting
khal tool
Command-line calendar manager that reads and writes ICS via vdirsyncer. CLI alternative to Outlook or Calendar.app for terminal users