Skip to content

Convert

ICS to JSON

ICS to JSON

Beta

Drop a Google Calendar, Apple Calendar or Outlook .ics export and download structured JSON: one object per event with uid, summary, start, end, time zone, attendees, categories and the recurrence rule as text. Times stay exactly as the file states them, and nothing is uploaded.

Use via API
  • Free, no sign-up
  • REST + MCP
  • Updated
  • Reviewed by Olgun Ozoktas
ICS Input
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
JSON Output

One object per event will appear here..

Why Convert ICS to JSON in the Browser?

A calendar export looks like plain text and is not: lines longer than 75 characters are folded onto the next line, commas and newlines are escaped with backslashes, and a start time can be floating, in UTC with a trailing Z, or in a named zone through a TZID parameter. A script that splits on newlines and colons works on one file and breaks on the next. This page reads the format properly and hands you a JSON array with one object per event and the same field names every time, so the script can start at the interesting part. The conversion runs in your browser; the calendar file never leaves the tab.

Each VEVENT in the file becomes one object with a fixed set of keys: type, uid, summary, description, location, start, end, all_day, timezone, status, url, organizer, attendees, categories, rrule, exdate, recurrence_id, created, last_modified, sequence and alarms. The organizer and each attendee are written as Name

, categories and exception dates as arrays, sequence as a number, alarms as the count of VALARM blocks nested in the event. Folded lines are joined and escaped text is decoded before any of it is read.

Every date-time is written in wall-clock ISO-8601 form exactly as the file states it: YYYY-MM-DD for an all-day value, YYYY-MM-DDTHH:MM:SS for a timed one, with a trailing Z when the file said Z. The timezone field names the TZID the start was stated in, UTC for a Z stamp, or nothing for floating time. No time is converted between zones, because that would need the zone rules of the reader's calendar. The end is the exclusive iCalendar end, computed from DURATION when DTEND is absent, and set from the start when the event has neither.

The result also carries a calendar block with the name, PRODID, METHOD, the X-WR-TIMEZONE hint and the list of VTIMEZONE ids, plus counts: how many objects were returned, how many carry a recurrence rule, how many components were skipped and how many lines could not be read. To-dos and journal entries are skipped and counted unless you include them, in which case each carries its own type. Nothing is uploaded and no calendar URL is fetched.

How it compares

The same calendar family on this site has two shapes. ICS to CSV writes one row per event for a spreadsheet, with an inclusive end date and the fields a sheet wants. ICS to JSON writes one object per event for code, with the exclusive end the format defines, attendees and exception dates as arrays, and every key present on every object. Pick the CSV for people and the JSON for scripts; both read the same fields and neither converts a time zone.

Conversion Tips

  • Times are written as the file states them, in ISO-8601 wall-clock form, and the timezone field names the zone: the TZID, UTC for a trailing Z, or empty for floating time. Nothing is converted to your local zone.
  • The end is the iCalendar end, which is exclusive: a two-day all-day event on the 5th and 6th ends on the 7th. When the file gives a DURATION instead of DTEND, the end is computed from it.
  • A recurring event is one object. Its rule stays as RRULE text and its exception dates are listed under exdate; nothing is expanded into occurrences.
  • A modified occurrence of a recurring event is its own object with the series UID and a recurrence_id naming the occurrence it replaces.
  • Missing values are empty strings and empty arrays, never absent keys, so a script can read every field without checking for it first.

Frequently Asked Questions

Which fields does each event object have?

Every object has the same twenty-one keys: type, uid, summary, description, location, start, end, all_day, timezone, status, url, organizer, attendees, categories, rrule, exdate, recurrence_id, created, last_modified, sequence and alarms. Text fields are strings, attendees, categories and exdate are arrays, all_day is a boolean, sequence and alarms are numbers. A value the event does not carry is an empty string, an empty array or zero, never a missing key.

How are dates and times written?

In wall-clock ISO-8601 form, exactly as the file states them. An all-day value is YYYY-MM-DD. A timed value is YYYY-MM-DDTHH:MM:SS, with a trailing Z when the file stated UTC. The timezone field names the zone the start was stated in: a TZID such as Europe/Istanbul, UTC for a Z stamp, or empty for floating time. Nothing is converted to your local zone; do that in the script with the zone the field names.

Why does an all-day event end on the day after its last day?

Because that is how iCalendar defines the end: DTEND is exclusive, so a two-day offsite on the 5th and 6th is stored with an end of the 7th. This page keeps that definition, since code that handles calendar data expects it. The ICS to CSV tool on this site does the opposite for spreadsheet readers and writes the inclusive last day.

What happens to recurring events?

A recurring event is one object. Its rule stays as text in rrule, for example FREQ=WEEKLY;BYDAY=TU, and its exception dates are listed in exdate. Occurrences are never expanded, because a rule with no end has no last occurrence and a capped expansion would be a different tool. A modified occurrence that the calendar stored separately is its own object with the same uid and a recurrence_id. The recurring count under the output says how many rules the file holds.

Does the JSON include to-dos and journal entries?

Not by default. VTODO and VJOURNAL components are counted as skipped and named in the notes. Turn on Include to-dos and journal entries and each is returned as an object with its type set to VTODO or VJOURNAL. A to-do's end comes from its DUE property when it has no DTEND.

What if the event has a DURATION instead of an end time?

The end is computed by adding the duration to the start, in the start's own zone. An event with neither DTEND nor DURATION gets an end equal to its start when it is timed, and the next day when it is all-day, which is what the format prescribes. An end that lies before the start is reported in the notes and replaced the same way.

Are folded lines and escaped characters handled?

Yes. A line longer than 75 characters is stored across several lines, each continuation starting with a space; those are joined before reading. Backslash escapes for commas, semicolons, newlines and backslashes are decoded, so a description reads as the text the person typed. A comma inside a quoted parameter, such as CN="Doe, Jane", is kept as part of the name.

Is my calendar uploaded anywhere?

No. The file is parsed and converted in your browser, and no request carries the calendar text. You can confirm that in the browser's network panel while converting. The tool never fetches a calendar URL either.

Can I go from JSON back to an .ics file?

Not directly on this page. The nearest route on this site is the CSV to ICS tool: write the events as a CSV with Subject, Start Date, Start Time, End Date, End Time, All Day Event and Location columns, and that tool writes a calendar that Google Calendar, Apple Calendar and Outlook import. The JSON to CSV tool can produce that CSV from a flat array.

Can I convert calendars from a script?

Yes. The same code runs on the FindUtils API and MCP server as the ics_to_json tool. Send the .ics text as input, set include_todos when you want to-dos and journal entries too, and read the events array, the calendar block and the counts from the result.

Rate This Tool

0/1000

Get Weekly Tools

Suggest a Tool