← Back to Blog

How to sync iCloud Calendar to Google, Outlook, or anything else

A survey of calendar synchronization options - from SaaS services to self-hosted solutions to DIY with native Apple APIs.

If you've ever tried to keep your work calendar in sync with your personal one, you've encountered one of computing's most mundane yet persistent annoyances: calendar synchronization.

I've spent more time than I'd like to admit wrestling with this problem. My personal life runs on both iCloud (my family loves the iCloud Family calendar feature), but my work calendars live on Google Workspace. I needed to stop letting people down by accidentally scheduling work meetings over my kids doctors appointments.

What follows is a survey of the options I explored. We’ll walk through SaaS services, self-hosted tools, and finally the path I chose once I decided to solve the problem myself.


The Non-Solutions: What Apple Gives You Out of the Box

Before we explore actual solutions, let's acknowledge what Apple provides natively and why it only gets you halfway there.

Viewing Multiple Calendars on iOS

iOS and macOS can display events from multiple calendar accounts simultaneously. You can add your Google account, your Microsoft account, and your iCloud account to the same device, and the Calendar app will show events from all of them. This is genuinely useful for viewing your schedule.

But viewing isn't syncing. Events from your iCloud calendar don't appear on your Google calendar (or vice versa). Your colleagues looking at your Google calendar availability won't see that you have a dentist appointment on your iCloud calendar. This is the problem.

The Public Calendar URL Workaround

Apple does offer one escape hatch: you can make an iCloud calendar public and share its URL. This generates a webcal:// link that other services can subscribe to.

To do this:

  1. Open Calendar on iCloud.com
  2. Click the share icon next to a calendar
  3. Enable "Public Calendar"
  4. Copy the URL

You can then paste this URL into Google Calendar (Settings → Add calendar → From URL) or Outlook. The events will appear.

The catch? It's read-only and one-way. Changes you make in Google won't propagate back. Updates in iCloud can take hours to appear (Google refreshes subscribed calendars roughly every 12-24 hours). And you're making your calendar data available to anyone with the URL—there's no authentication.

For some use cases, this works. For anything requiring bidirectional sync or timely updates, it doesn't.


The SaaS Route: Let someone else handle it

The easiest solution is to pay someone else to solve the problem for you. Several services exist specifically to synchronize calendars across providers.

Here's some that I found:

  • SyncGene supports iCloud, Google Calendar, Outlook, Office 365, and various other CalDAV-compatible services. The setup process is straightforward: create an account, connect your calendar providers, select which calendars to sync, and configure the direction (one-way or two-way). SyncGene runs in the background and keeps things synchronized. Pricing: Free tier syncs manually. Automatic sync starts at roughly $10/month.
  • CalendarBridge takes a similar approach but emphasizes privacy features. They offer options to sync only free/busy information rather than full event details—useful when you want to block time on a work calendar without exposing personal appointment details. Pricing: Starts around $4/month for basic sync.
  • OneCal is a newer entrant targeting professionals who manage multiple calendars. Their marketing emphasizes "calendar blocking"—automatically creating blocking events on one calendar when you have events on another. Pricing: Free tier available, paid plans from $5/month.

The SaaS Problem

I'll acknowledge these services appear to work and solve a real problem. If your primary concern is convenience and you're comfortable with the privacy tradeoffs, I'm sure any of them will get the job done.

I'll admit I didn't actually try any of them, SaaS was a nonstarter for me. There's something unsatisfying about paying a monthly fee for what feels like basic plumbing. Let alone the data privacy concerns, as well as sharing credentials (or OAuth tokens) with these third parties. I already have a supercomputer in my pocket and it already has access to all my calendars.

And sadly, SaaS companies disappear every day and could leave you scrambling for another solution.


The Self-Hosted Route: CalDAV and Friends

For the technically inclined, there's another path: running your own calendar synchronization infrastructure. This approach uses CalDAV, the open standard that underlies most calendar systems.

CalDAV (Calendaring Extensions to WebDAV) is the protocol that calendar applications use to communicate with calendar servers. iCloud, Google Calendar, and most other calendar services support CalDAV (with varying degrees of enthusiasm).

If you can speak CalDAV to a given calendar service, then you can write software that reads from one and writes to another.

vdirsyncer

vdirsyncer is a command-line tool that synchronizes calendars (and contacts) between CalDAV servers. It's written in Python and has been around for years.

A typical configuration looks like this:

[pair my_calendars]
a = "icloud_calendar"
b = "google_calendar"
collections = ["from a", "from b"]
conflict_resolution = "a wins"

[storage icloud_calendar]
type = "caldav"
url = "https://caldav.icloud.com/"
username = "your_apple_id"
password.fetch = ["command", "security", "find-generic-password", "-s", "icloud", "-w"]

[storage google_calendar]
type = "google_calendar"
token_file = "~/.vdirsyncer/google_token"
client_id = "your_client_id"
client_secret = "your_client_secret"

Run vdirsyncer sync on a schedule (cron, launchd, systemd) and you’re off to the races.

The good: Full control, no monthly fees, all your data stays with you. The bad: You’re running infrastructure now. The ugly: Credential management becomes a hobby whether you want it or not.

Self-hosting works, but it’s a commitment.


The Apple Native Route: EventKit

Here's where things get interesting, and where I eventually landed.

Apple's iOS and macOS provide a framework called EventKit that gives applications direct access to calendar data on the device. This is the same framework that powers the built-in Calendar app.

What EventKit Can Do

EventKit provides programmatic access to:

  • All calendar accounts configured on the device (iCloud, Google, Exchange, CalDAV, etc.)
  • All events within those calendars
  • The ability to create, modify, and delete events
  • Reminder lists and individual reminders

The critical insight is that EventKit doesn't care which service originally provided the calendar. If the calendar is accessible on your iPhone or Mac, EventKit can read it and write to it. This means an app using EventKit can copy events from your iCloud calendar to your Google calendar—without any cloud service involvement.

A Quick Look at the Code

For those curious about what this looks like in practice, here's a simplified Swift example that fetches events from one calendar and copies them to another:

import EventKit

let eventStore = EKEventStore()

// Request calendar access (required since iOS 17)
eventStore.requestFullAccessToEvents { granted, error in
    guard granted else {
        print("Calendar access denied")
        return
    }

    // Find source and destination calendars
    let calendars = eventStore.calendars(for: .event)
    guard let sourceCalendar = calendars.first(where: { $0.title == "Personal" }),
          let destCalendar = calendars.first(where: { $0.title == "Work" }) else {
        print("Calendars not found")
        return
    }

    // Define date range
    let startDate = Date()
    let endDate = Calendar.current.date(byAdding: .month, value: 1, to: startDate)!

    // Fetch events from source calendar
    let predicate = eventStore.predicateForEvents(
        withStart: startDate,
        end: endDate,
        calendars: [sourceCalendar]
    )
    let events = eventStore.events(matching: predicate)

    // Copy each event to destination calendar
    for sourceEvent in events {
        let newEvent = EKEvent(eventStore: eventStore)
        newEvent.title = "Busy" // Optionally mask the title
        newEvent.startDate = sourceEvent.startDate
        newEvent.endDate = sourceEvent.endDate
        newEvent.calendar = destCalendar

        do {
            try eventStore.save(newEvent, span: .thisEvent)
        } catch {
            print("Failed to save event: \(error)")
        }
    }
}

This is obviously a grossly oversimplified example, production code needs to handle cases like recurring events, all-day events, event modifications, and deletions-- all in an idempotent fashion. But it illustrates the core concept: EventKit gives you direct access to calendar data across all configured accounts.

EventKit on macOS

EventKit works on macOS too, not just iOS. If you're comfortable building Swift command-line tools, you could write a sync utility that runs on your Mac. Projects like mcp-ical demonstrate this approach—it's a Python tool that uses PyObjC to access EventKit and exposes calendar data for automation.

The catch? You need a Mac, and it needs to be running for syncs to happen. That's fine if you have a Mac mini humming away somewhere.

This is why EventKit really shines on iOS. Your phone is always with you, always on, always connected. It's the natural place to run sync operations, if you can work within iOS's background execution constraints.

The Privacy and Cost Advantages

With EventKit, everything happens on-device. The sync logic runs locally. No calendar data leaves your phone (except when it syncs with the original providers, which it was doing anyway). There's no third-party account to create, no credentials to share. Your calendar data stays between you and the calendar providers you've already chosen to trust.

There's also no additional service to sign up for or pay monthly.

The Limitations

iOS Background Execution Limits: iOS is famously restrictive about what apps can do in the background. An EventKit-based sync app needs to work within these constraints, which limits how frequently it can run automatic syncs. Apple provides background app refresh, but you can't guarantee when or how often your app will wake up.

Complexity: Building a robust sync engine is genuinely hard. Conflict resolution, handling deleted events, managing recurring event exceptions, dealing with events that span time zones—these are non-trivial problems that require careful thought.

Why I Built Calendar Copilot

After surveying all these options, I realized what I actually wanted:

  1. On-device sync that doesn't send my calendar data through a third-party service
  2. Automatic background operation that keeps things synchronized without manual intervention
  3. Flexibility to sync specific calendars with specific transformations (like stripping event details to create availability blocks)

None of the existing solutions checked all these boxes. The SaaS services required trusting a third party. The self-hosted solutions required infrastructure I didn't want to maintain. EventKit provided the capabilities I needed, but no app I found used it in the way I wanted.

So I built one.

Calendar Copilot is the result of that effort. It uses EventKit to run sync operations entirely on your iPhone, iPad, or newer Mac (as an iPad app). You configure which calendars to sync, in which direction, and with what transformations. The app handles the rest, running in the background using iOS's available background execution mechanisms.

I decided to go oldschool on the pricing. I didn't want to deal with the complexity of some kind of subscription or "freemium" model, and I honestly don't think anyone else really wants to these days. So I put it out there for $1.99 - basically a 99 cent app in 2025 money. Pay once, have it forever. Easier for all parties involved, right?


Have questions about calendar sync or suggestions for this guide? Reach out at [email protected].