Skip to content

Convert

ICS Diff

ICS Diff

Beta

Compare two .ics exports of the same calendar and see which events were added, removed or changed, matched by UID, with the before and after value of every changed field. Download the report and the added or removed events as calendars of their own. On this page, both files are read in your browser and nothing is uploaded.

Use via API
  • Free, no sign-up
  • REST + MCP
  • Updated
  • Reviewed by Olgun Ozoktas

Matched by UID + RECURRENCE-ID

Before (A)

Drop or choose a .ics fileOne calendar export

After (B)

Drop or choose a .ics fileOne calendar export

Differences

Drop the before and after calendars to compare them.

How to Compare Two ICS Files

  1. Export the calendar twice

    before and after the change, or from the two apps you want to compare. In Google Calendar, Settings > Import & export > Export; Apple Calendar: File > Export; Outlook: File > Save Calendar.
  2. Drop the older export on Before (A) and the newer one on After (B)

  3. Read the counts and the table

    Each changed event lists the fields that differ, with the old value and the new one.
  4. Download the JSON report for a record, and added.ics or removed.ics to import or restore just those events

Common Use Cases

Migrations

check that a move from one calendar service to another kept every event and every time.

Sync problems

see which events a sync changed, dropped or duplicated.

Shared calendars

find what someone else edited between two exports.

Restores

take removed.ics from the comparison and import it to bring deleted events back.

Generated calendars

check what a script or a feed changed before you publish it.

Why Compare Two Calendar Exports?

After a migration, a sync conflict or a re-export, the question is always the same: what actually changed? Opening two .ics files in a text editor does not answer it, because long lines are folded at 75 characters, properties come in any order, and every export rewrites stamps such as DTSTAMP. Two calendar apps side by side do not answer it either once there are more than a handful of events. This page matches the events of both files by their UID, the identifier calendar apps use for the same purpose, and lists exactly which were added, which were removed, and which fields of the rest changed.

The comparison reads both files into their components and matches entries by UID together with RECURRENCE-ID, the same identity a calendar app uses when it imports a file and the same key Merge ICS dedupes on. An entry only in After is added, an entry only in Before is removed, and an entry in both is compared field by field. Entries without a UID are listed apart and never matched; when one UID appears more than once in a file, the copies are paired in file order and a note says so.

A field is a property name such as SUMMARY, DTSTART, LOCATION or ATTENDEE, or a sub-component such as VALARM. A field counts as changed when the set of its values differs, so property order, line folding and the order of parameters are not changes. For a repeated field such as ATTENDEE or CATEGORIES, only the values that differ are shown: one new attendee shows as that one attendee, not the whole list. Values are shown with their parameters and with text escapes removed. DTSTAMP, LAST-MODIFIED and SEQUENCE are left out by default because calendar apps rewrite them on every export.

Times are compared as written and never converted between zones, and recurrence rules are compared as text, not expanded: a changed RRULE shows as a change to the RRULE field. The added and removed entries can be downloaded as calendars of their own, with the header of their source file and the VTIMEZONE blocks they use. The JSON report holds every difference with its fields.

How it compares

A line-by-line text diff of two .ics files reports every refolded line, every reordered property and every new DTSTAMP, and buries the one meeting that moved. Comparing two calendar apps by eye works for a week of events, not a year. This page compares the files the way a calendar app reads them, event by event and field by field, and leaves out the stamps that change on every export.

Comparison Tips

  • Put the older file on Before (A). Added means only in After, removed means only in Before.
  • A modified occurrence of a recurring meeting has the series UID plus a RECURRENCE-ID, so it is compared as its own entry, never against the series.
  • An event without a UID cannot be matched safely, so it is listed apart instead of being guessed.
  • Turn off the DTSTAMP, LAST-MODIFIED and SEQUENCE option to see every stamp a calendar app rewrote.
  • Times are compared as written: the same meeting stated in UTC in one file and in Europe/Istanbul in the other shows as a DTSTART change.

Frequently Asked Questions

How does ICS Diff match events between the two files?

By UID together with RECURRENCE-ID. The UID is the identifier a calendar app gives each event and keeps when the event is edited, so the same event has the same UID in both exports even when its title, time or place changed. A modified occurrence of a recurring event shares the series UID and adds a RECURRENCE-ID, so it is matched as its own entry. Events are never matched by title or position.

What counts as a changed event?

An event that is in both files and differs in at least one field: a property such as SUMMARY, DTSTART, DTEND, LOCATION, DESCRIPTION, RRULE, STATUS or ATTENDEE, or an alarm (VALARM). Each changed event lists the fields with their before and after values. Property order, line folding and parameter order are not changes, and DTSTAMP, LAST-MODIFIED and SEQUENCE are ignored by default.

Why are DTSTAMP, LAST-MODIFIED and SEQUENCE ignored?

Because calendar apps rewrite them without anyone editing the event. DTSTAMP is usually the moment the file was exported, so it differs on every event between two exports, and LAST-MODIFIED and SEQUENCE move with sync activity. Counting them would mark almost every event as changed. Turn the option off to compare them too.

What happens to events without a UID?

They are listed under the table by side, with their title and start, and are not counted as added, removed or changed. Matching them by title or time would be a guess that can pair two different events, so the page does not try.

How are recurring events compared?

A recurring series is one entry, compared by its fields like any other, so a changed rule shows as a change to RRULE and a new exception date as a change to EXDATE. Each modified occurrence is a separate entry with its own RECURRENCE-ID. The rules are not expanded into occurrences; to compare the actual dates, run both files through ICS Expand RRULE with the same date range first.

Are time zones converted before comparing?

No. Times are compared as written, with their TZID or trailing Z. The same meeting written as 06:30 UTC in one file and as 09:30 Europe/Istanbul in the other shows as a DTSTART change, which is what changed in the file. The page does not decide that the two are the same instant.

What are added.ics and removed.ics?

They are the added and the removed events as calendars of their own, each a complete VCALENDAR with the header of its source file and the VTIMEZONE blocks its events use. Import removed.ics to bring deleted events back, or added.ics to copy just the new events into another calendar. Changed events stay in the report; no merged calendar is written.

What is in the JSON report?

The two file names, the match key, the ignored fields, the four counts, and one entry per difference with change (added, removed or changed), type, uid, recurrence_id, summary, start and, for a changed event, each field with its before and after values. Entries without a UID and any notes are included too. The table on the page shows up to 300 rows; the report holds every one.

Is my calendar uploaded?

Not on this page. Both files are read with the browser's File API and compared in the tab, and the page makes no request with the calendar text, which you can confirm in the browser's network panel. The REST API and MCP tool are a separate path: a call sends the input you include to FindUtils over HTTPS, where it is processed and the result returned. FindUtils does not store that input, and logs the request without its content.

Can I compare calendars from a script?

Yes. The same code runs on the FindUtils REST API and MCP server as the ics_diff tool. Send the two .ics texts as before and after, optionally with ignore_metadata and include_todos, and read the counts, the differences with their fields, the entries without a UID, and added_ics and removed_ics from the result.

Rate This Tool

0/1000

Get Weekly Tools

Suggest a Tool