diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index fde828aee6f..d7cc5f3de33 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -1397,15 +1397,23 @@ class UsersController < ApplicationController
 
   def bookmarks
     user = fetch_user_from_params
-    bookmarks = BookmarkQuery.new(user, params).list_all
 
-    if bookmarks.empty?
-      render json: {
-        bookmarks: [],
-        no_results_help: I18n.t("user_activity.no_bookmarks.self")
-      }
-    else
-      render_serialized(bookmarks, UserBookmarkSerializer, root: 'bookmarks')
+    respond_to do |format|
+      format.json do
+        bookmarks = BookmarkQuery.new(user, params).list_all
+
+        if bookmarks.empty?
+          render json: {
+            bookmarks: [],
+            no_results_help: I18n.t("user_activity.no_bookmarks.self")
+          }
+        else
+          render_serialized(bookmarks, UserBookmarkSerializer, root: 'bookmarks')
+        end
+      end
+      format.ics do
+        @bookmark_reminders = Bookmark.where(user_id: user.id).where.not(reminder_at: nil).joins(:topic)
+      end
     end
   end
 
diff --git a/app/views/users/bookmarks.ics.erb b/app/views/users/bookmarks.ics.erb
new file mode 100644
index 00000000000..da77b9d792f
--- /dev/null
+++ b/app/views/users/bookmarks.ics.erb
@@ -0,0 +1,14 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Discourse//<%= Discourse.current_hostname %>//<%= Discourse.full_version %>//EN
+<% @bookmark_reminders.each do |bookmark| %>
+BEGIN:VEVENT
+UID:bookmark_reminder_#<%= bookmark.id %>@<%= Discourse.current_hostname %>
+DTSTAMP:<%= bookmark.updated_at.strftime("%Y%m%dT%H%M%SZ") %>
+DTSTART:<%= bookmark.reminder_at.strftime("%Y%m%dT%H%M%SZ") %>
+DTEND:<%= (bookmark.reminder_at + 1.hour).strftime("%Y%m%dT%H%M%SZ") %>
+SUMMARY:<%= bookmark.name.presence || bookmark.topic.title %>
+URL:<%= Discourse.base_url %>/t/-/<%= bookmark.topic_id %>
+END:VEVENT
+<% end %>
+END:VCALENDAR
diff --git a/config/routes.rb b/config/routes.rb
index 7f7a457af3f..7cde4b038e1 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -469,7 +469,7 @@ Discourse::Application.routes.draw do
     get "#{root_path}/:username/activity" => "users#show", constraints: { username: RouteFormat.username }
     get "#{root_path}/:username/activity/:filter" => "users#show", constraints: { username: RouteFormat.username }
     get "#{root_path}/:username/badges" => "users#badges", constraints: { username: RouteFormat.username }
-    get "#{root_path}/:username/bookmarks" => "users#bookmarks", constraints: { username: RouteFormat.username }
+    get "#{root_path}/:username/bookmarks" => "users#bookmarks", constraints: { username: RouteFormat.username, format: /(json|ics)/ }
     get "#{root_path}/:username/notifications" => "users#show", constraints: { username: RouteFormat.username }
     get "#{root_path}/:username/notifications/:filter" => "users#show", constraints: { username: RouteFormat.username }
     delete "#{root_path}/:username" => "users#destroy", constraints: { username: RouteFormat.username }