The basics
What is an ICS file?
An ICS file is a calendar in a text file. It uses the iCalendar format, which every mainstream calendar app can read and write, so it is how calendar data moves between Google Calendar, Outlook, Apple Calendar and everything else.
You meet ICS files in two forms. As a file: the "Add to calendar" download on a ticket or booking page, an invitation attached to an email, or a calendar exported from an app. And as a link: public holiday calendars, school terms, sports fixtures and shift rotas are often published as an .ics address that calendar apps subscribe to and check again from time to time.
Three things an ICS file is not:
- Not a live connection by itself. A downloaded file is a snapshot. Only a subscription to the file's web address picks up later changes.
- Not a contact card. Contacts use the related vCard format (
.vcf). The two look alike inside, with the sameBEGIN:andEND:lines. - Not an app's own database. Google, Outlook and Apple store calendars their own way and use iCalendar to exchange them, so app-specific features (colours, some reminders, attachments) may not survive the trip.
Anatomy
What's inside an ICS file
An ICS file is a series of content lines, each a property name, optional parameters after semicolons, a colon and a value: NAME;PARAM=x:value. BEGIN and END lines wrap them into components, like an event inside a calendar. Here is a small but complete file, part by part.
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp//Planner 1.0//EN
METHOD:PUBLISH
BEGIN:VEVENT
UID:workshop-20261119@example.com
DTSTAMP:20261027T090000Z
SEQUENCE:0
DTSTART:20261119T133000Z
DTEND:20261119T150000Z
SUMMARY:Planning workshop
LOCATION:Room 2\, Sample Building\, Utrecht
DESCRIPTION:Bring a laptop.\nCoffee from 14:15\; the planning session start
s at 14:30 sharp.
BEGIN:VALARM
ACTION:DISPLAY
DESCRIPTION:Planning workshop
TRIGGER:-PT30M
END:VALARM
END:VEVENT
END:VCALENDAR- 1
BEGIN:VCALENDAR … END:VCALENDARThe calendar object
Wraps everything. One file usually holds one calendar object, which can contain any number of events, to-dos and time zone definitions.
- 2
VERSION:2.0The version
Required, and always
2.0for iCalendar. Version1.0was vCalendar, the older format in.vcsfiles. - 3
PRODID:-//Example Corp//Planner 1.0//ENThe product identifier
Required. Names the program that wrote the file, which helps when debugging an import. Its format is a convention, not something apps check.
- 4
METHOD:PUBLISHThe method
Optional.
PUBLISHmeans "here are some events", with no reply expected. Invitations useREQUESTinstead, and the receiving app offers to accept or decline. - 5
UID:workshop-20261119@example.comThe unique identifier
Required, and must stay the same for the life of the event. Apps use it to recognise an update to an event they already have, instead of adding a copy.
- 6
DTSTAMP:20261027T090000ZThe timestamp
Required: when this file's version of the event was created. Always in UTC.
- 7
SEQUENCE:0The revision number
Starts at 0 and goes up each time the organiser makes a significant change, such as a new time. The highest number wins.
- 8
DTSTART:20261119T133000ZStart and end
Dates are written
YYYYMMDDTHHMMSS. TheZmeans UTC, so this is 14:30 in Amsterdam and 08:30 in New York. Without theZand without a time zone, the time would float: 13:30 wherever the reader is. - 9
LOCATION:Room 2\, Sample Building…Escaped text
In text values, commas, semicolons and backslashes are escaped with a backslash, and a line break is written
\n. - 10
DESCRIPTION:… session start s at 14:30 sharp.A folded line
This line is longer than 75 octets, so it is split, and the continuation starts with a single space. A reader removes the line break and that space, so the value reads
startsagain. A fold can fall anywhere, even inside a word. - 11
BEGIN:VALARM … END:VALARMAn alarm
A reminder inside the event.
TRIGGER:-PT30Mmeans 30 minutes before the start;ACTION:DISPLAYshows a message.
Using it
Importing vs subscribing: the difference that matters
Importing copies the events in the file into one of your calendars, once. Later changes to the file never reach you, and you can edit the copies. Subscribing adds the file's web address as a separate, read-only calendar, which your app downloads again on its own schedule. When the publisher replaces the file at that address, subscribers see the change after their app's next check.
| App | Import a file | Subscribe to a link | How often a subscription updates |
|---|---|---|---|
| Google Calendar | Settings, Import & export, on a computer | Other calendars, +, From URL, on a computer (not in the phone apps) | Not documented, and not quick: allow many hours |
| Outlook.com and Outlook on the web | Add calendar, Upload from file | Add calendar, Subscribe from web | Microsoft says about every 3 hours for personal accounts, every 6 for work and school, and sometimes more than 24 |
| Classic Outlook for Windows | File, Open & Export, Import/Export, Import an iCalendar (.ics) or vCalendar file (.vcs) | Add Calendar, From Internet | Not documented |
| Apple Calendar on a Mac | File, Import | File, New Calendar Subscription | You choose, in the Auto-refresh menu |
| Apple Calendar on iPhone and iPad | Open the file, then add the events | Calendars, Add Calendar, Add Subscription Calendar | Not documented |
A webcal:// link is an ordinary web address with the scheme swapped, as in webcal://example.com/team.ics. Clicking it opens the calendar app the device has registered for webcal, which offers to subscribe instead of downloading the file. That app is often not the one people use (a Google Calendar user on a Mac may get Apple Calendar), so publish the plain https:// address too, for pasting into a From URL box.
Publishing a calendar people subscribe to
Keep the address and every event's UID the same, and replace the file in place. A new address means everyone has to subscribe again; a new UID turns an edited event into a new one. The optional REFRESH-INTERVAL property from RFC 7986 (and the older, unofficial X-PUBLISHED-TTL) suggests how often apps should check, but apps decide for themselves.
Under the hood
Components, properties and the rules of the text
| Component | What it holds |
|---|---|
VEVENT | An event: a meeting, a booking, an all-day holiday. By far the most common. |
VTODO | A to-do with a due date, priority and progress. Many calendar apps skip these on import. |
VJOURNAL | A dated note. Rarely supported. |
VFREEBUSY | Busy and free time, without details. Used for scheduling and in .ifb files. |
VTIMEZONE | The rules of a time zone that events in the file refer to. |
VALARM | A reminder, inside an event or to-do. |
Every event needs a UID and a DTSTAMP, and a DTSTART unless the file is a scheduling message with a METHOD. The calendar itself needs VERSION and PRODID. Everything else is optional.
| METHOD | Meaning |
|---|---|
PUBLISH | Here are some events. No replies. Right for downloads and subscriptions. |
REQUEST | An invitation, or an update to one. The app offers accept, decline or tentative. |
REPLY | An attendee's answer, sent back to the organiser. |
CANCEL | The organiser cancels the event, or one occurrence of it. |
The text itself has three rules that hand-written and home-made files often break:
- Lines end with CRLF (a carriage return and a line feed), as in email. Many apps accept plain line feeds; strict parsers don't.
- Long lines are folded. A line should be at most 75 octets (bytes, not characters), and a longer one continues on the next line after one space. RFC 5545 calls a fold in the middle of a multi-byte UTF-8 character improper and asks readers to repair it, but it's safer to fold between characters.
- Text values are escaped:
\,for a comma,\;for a semicolon,\\for a backslash, and\nfor a line break.
Times
Time zones: why events show up at the wrong time
Most wrong-time problems come from the way a time is written. iCalendar has three forms, plus dates for all-day events:
| Written as | Means | Use it for |
|---|---|---|
DTSTART:20261119T133000Z | UTC, marked by the Z. The same instant everywhere. | Online meetings and anything machine-generated. |
DTSTART;TZID=Europe/Amsterdam:20261119T143000 | Local time in a named zone, defined by a VTIMEZONE in the file. | Events tied to a place, and recurring events that must follow summer time. |
DTSTART:20261119T143000 | Floating: 14:30 wherever the reader is, moving with them. | Rarely right. "Take medicine at 08:00" is the classic case. |
DTSTART;VALUE=DATE:20261202 | A whole day, no time. | All-day and multi-day events. |
- Every
TZIDneeds aVTIMEZONE. RFC 5545 requires the file to define each time zone it names. Many apps recognise names likeEurope/Amsterdamwithout one, but not all do, and Outlook writes Windows names such asW. Europe Standard Time, which only the included definition explains. - Floating times look right to the author and wrong to everyone in another time zone. A generator that drops the
Zor theTZIDproduces them by accident. - An end date is not included. An all-day event from 2 to 4 December has
DTEND;VALUE=DATE:20261205. Writing20261204makes it end a day early. - Recurring events should use a
TZID. A weekly 10:00 meeting written in UTC moves by an hour for local attendees when summer time starts or ends.
Repeats
Recurring events: RRULE, EXDATE and exceptions
A repeating event is stored once, with an RRULE that describes the pattern. The calendar app works out the dates. DTSTART is always the first occurrence.
| RRULE | Means |
|---|---|
FREQ=WEEKLY;BYDAY=TU;COUNT=10 | Every Tuesday, 10 times. |
FREQ=DAILY;INTERVAL=2 | Every other day, for ever. |
FREQ=MONTHLY;BYDAY=-1FR | The last Friday of every month. |
FREQ=MONTHLY;BYMONTHDAY=15 | The 15th of every month. |
FREQ=YEARLY | Every year on the start date: birthdays, anniversaries. |
FREQ=WEEKLY;UNTIL=20261231T235959Z | Weekly until the last second of 2026, UTC. UNTIL is inclusive. |
EXDATEremoves an occurrence, such as a meeting cancelled for a public holiday. Its time must match the occurrence exactly, time zone included.- A moved or edited occurrence is a second
VEVENTwith the sameUIDand aRECURRENCE-IDnaming the original date and time. UNTILmust be in UTC whenDTSTARThas a time zone or is in UTC. A localUNTILbreaks that rule, and apps then disagree about where the series ends, or reject it.RDATEadds extra dates that don't follow the pattern.
Changes
UID and SEQUENCE: how updates work, and where duplicates come from
An event's identity is its UID, not its title or time. When an app receives an event whose UID it already has, it treats it as a new version of that event. SEQUENCE says which version is newer: it starts at 0, and the organiser raises it for each significant change, such as a new time or place.
- Duplicates after a second import usually mean the file was generated with new UIDs, or the app imports without checking them. Keep UIDs stable and prefer a subscription for anything that changes.
- An updated invitation that changes nothing often has the same
SEQUENCEas the old one. Raise it with every real change. - Cancelling an invitation means sending
METHOD:CANCELwith the same UID. In a published calendar, setSTATUS:CANCELLEDon the event or remove it from the file.
A good UID is unique across the world and never reused: a random UUID, or an ID from your own system plus your domain, like booking-18422@example.com. It doesn't need to be an email address that works.
Troubleshooting
Common ICS problems, and how to fix them
| Problem | Usual cause | Fix |
|---|---|---|
| Events are hours off | Floating times, a missing VTIMEZONE, or local times marked with Z | Write UTC with Z, or a TZID plus its VTIMEZONE |
| All-day event one day short | DTEND set to the last day | Set DTEND to the day after |
| Every event appears twice | Imported twice with different UIDs, or imported and subscribed | Stable UIDs; delete the imported copy |
| Subscription never changes | The app hasn't checked yet, or the file moved to a new address | Wait for the refresh, or check the address in a browser |
| Import fails or skips events | A broken line, wrong line endings, a missing END:, or to-dos the app ignores | Run it through a parser such as Python's icalendar |
| Guests missing in Google Calendar | Google imports events without their guests or conference data | Send an invitation instead of importing |
Apps also differ in what they keep. Some ignore alarms in imported or subscribed calendars (Apple Calendar removes them unless you untick Remove alerts when subscribing), and support for to-dos, attachments and colours varies widely. Test with the apps your audience actually uses.
How to
How to open, edit and create an ICS file
- Open it: double-click it, and your default calendar app offers to add the events. On a phone, tap it in the email or browser; Google Calendar's own import only works on a computer.
- Read it: open it in any text editor. Each line is one property, so a quick look shows the times and time zones it really contains.
- Edit it: use a plain-text editor and keep the line endings as CRLF (VS Code shows CRLF or LF in its status bar). Raise
SEQUENCEand keepUIDunchanged if the event was already shared. - Create one: export it from a calendar app, or generate it with a library such as
icalendarfor Python orical-generatorfor Node.js rather than by string concatenation, which tends to get folding and escaping wrong. - From a spreadsheet: Google Calendar can import CSV directly. To turn CSV into ICS, a short script with an iCalendar library is the reliable route.
Security
Privacy and safety: what an ICS file can reveal
An ICS file is text and can't run code. The risks are in what it says and where it points:
- Attendee email addresses. Invitations carry the organiser and every attendee as
mailto:addresses, with names and replies. Forwarding or publishing one shares them all.sample-invite.icsbelow shows what's included. - Private calendar addresses. Many calendar services offer a private iCal link to a calendar. Anyone who has the link can read every event in it, with no sign-in, so treat it like a password and reset it if it leaks.
- Descriptions and notes often hold dial-in codes, door codes, home addresses or internal details nobody meant to publish.
- Calendar spam. Unknown invitations and subscriptions can add events with phishing links. Apple's advice is to subscribe only to calendars from sources you trust, and Apple Calendar can report a subscription as junk when you unsubscribe.
Before publishing a calendar file, open it in a text editor and read it: look for ATTENDEE, ORGANIZER, DESCRIPTION and X- lines carrying more than you intended.
Free downloads
Sample ICS files to download
Free sample iCalendar files for testing imports, subscriptions, time zones and recurrence. Each one parses with Python's icalendar library, uses CRLF line endings and folds every line at 75 octets.
Loading…What's inside sample-event.ics
iCalendar has no comment syntax, so this file can't explain itself. Open it in a text editor and look for these parts, from the top.
The header
VERSION:2.0and aPRODIDnaming this page, thenCALSCALE:GREGORIANandMETHOD:PUBLISH: an event to add, not an invitation.The VTIMEZONE block
Defines
Europe/Amsterdamas two yearly rules: CEST (UTC+2) from the last Sunday of March, CET (UTC+1) from the last Sunday of October.UID, DTSTAMP and SEQUENCE
A UID that will never change, when the file was made, and revision 0.
DTSTART and DTEND
14:30 to 16:00 Amsterdam time on 19 November 2026, written with
TZID. That is 13:30 UTC, so a calendar in New York should show 08:30 and one in Tokyo 22:30.Escaped and folded text
LOCATIONescapes its commas as\,;DESCRIPTIONhas\;and\n, and is long enough to fold three times. One fold falls just beforeÜnïcode, whose two-byte letters count double towards the 75-octet limit.GEO, URL and CATEGORIES
GEOputs latitude first, then longitude: the opposite order to GeoJSON.CATEGORIESholds a comma-separated list.The VALARM
A display reminder 30 minutes before the start (
TRIGGER:-PT30M). Whether it fires depends on the app and how the file was added.
All sample ICS files
Event with a time zone and an alarm
sample-event.ics · 1.3 KB (1,281 bytes)
One event at 14:30 Amsterdam time with a full
VTIMEZONE, escaped and folded text including non-ASCII letters, a location,GEO, a link and a 30-minute reminder.- Checking an app converts time zones correctly
- Testing an Add to calendar button
Weekly meeting with an exception
sample-recurring.ics · 1.4 KB (1,464 bytes)
Every Tuesday at 10:00 Amsterdam time, 10 times from 13 October 2026 (
RRULE), with 10 November cancelled (EXDATE) and 24 November moved to 14:00 (RECURRENCE-ID). It crosses the end of summer time on 25 October.- Testing recurrence expansion
- Checking events keep their local time across a clock change
All-day and multi-day events
sample-all-day.ics · 1.3 KB (1,341 bytes)
A one-day deadline with no
DTEND, a three-day conference (2 to 4 December), a holiday across the new year and a yearly all-day anniversary.- Catching off-by-one-day bugs with exclusive end dates
- Testing free and busy (`TRANSP`)
Calendar of 52 events for subscriptions
sample-subscription.ics · 17.5 KB (17,928 bytes)
A year of weekly fictional events with a calendar name,
REFRESH-INTERVALandX-PUBLISHED-TTL, two time zones, UTC and all-day events, and one cancelled event (#11).- Testing subscribe-by-URL in calendar apps
- Measuring how long subscriptions take to update
To-dos (VTODO)
sample-todo.ics · 1.5 KB (1,581 bytes)
Four to-dos: one due at a set time with a reminder, one half done, a sub-task linked with
RELATED-TO, and one completed.- Checking whether an app imports to-dos
- Task app import tests
Meeting invitation (METHOD:REQUEST)
sample-invite.ics · 956 bytes
An invitation in UTC with an organiser and two attendees at the reserved
example.comandexample.orgdomains, asking for replies.- Testing how mail and calendar apps handle invitations
- Seeing what personal data an invitation carries
Ways to test with them
- Time zones: import
sample-event.icswith your device set to another time zone. It should show the equivalent of 13:30 UTC; if it shows 14:30 local time, the app ignored the time zone. - Clock changes:
sample-recurring.icsshould give nine meetings, all at 10:00 Amsterdam time on both sides of 25 October, with none on 10 November and the 24 November one at 14:00. - Subscriptions: put
sample-subscription.icsonline, subscribe to its address, then replace the file with an edited copy and time how long each app takes to show the change. - Exclusive end dates: the conference in
sample-all-day.icsmust cover exactly 2, 3 and 4 December.
Free to use for testing, teaching and demos, commercially or not, with no attribution needed. A link back to this page is always appreciated.
Put it online
Have an ICS file? Give it a link.
Drop an ICS file on 99helpers and it gets its own web address. Opening the link downloads the file so the visitor's calendar app can add the events, and calendar apps can subscribe to the address instead.
Questions
ICS files, frequently asked
What is an ICS file?
A calendar file in the iCalendar format. It holds events, and sometimes to-dos and reminders, as plain text that any calendar app can import.
How do I open an ICS file?
Double-click or tap it, and your calendar app offers to add the events. To see what's inside without adding anything, open it in a text editor.
How do I add an ICS file to Google Calendar?
On a computer, open Settings, choose Import & export, select the file and pick a calendar. To follow a calendar published at a web address instead, use Other calendars, +, From URL.
What's the difference between importing and subscribing?
Importing copies the events once, and later changes don't reach you. Subscribing adds the file's web address as a read-only calendar that your app downloads again from time to time.
Why are my events at the wrong time after importing?
The file probably uses floating times (no Z and no TZID), names a time zone without defining it, or marks local times as UTC. Open it in a text editor and check the DTSTART lines.
Why doesn't my subscribed calendar update?
Calendar apps check subscriptions on their own schedule. Outlook can take more than 24 hours and Google doesn't publish its interval. Also check that the file is still at the same address.
What's the difference between ICS and VCS?
.vcs is vCalendar 1.0, the older format iCalendar replaced. .ics is iCalendar 2.0. They look similar, and Outlook can still import both.
Is it safe to open an ICS file?
It can't run code, but it can add events with links in them, and an invitation file reveals every attendee's email address. Only add calendars and invitations from people you trust.
Related formats
Other file types explained
Keep going
Related
Sources
- RFC 5545: Internet Calendaring and Scheduling Core Object Specification (iCalendar)
- RFC 5546: iCalendar Transport-Independent Interoperability Protocol (iTIP)
- RFC 7986: New Properties for iCalendar
- Google Calendar Help: Import events to Google Calendar
- Microsoft Support: Import or subscribe to a calendar in Outlook.com or Outlook on the web
- Apple Support: Subscribe to calendars on Mac
Last reviewed 27 October 2026.