diff --git a/aleksis/core/feeds.py b/aleksis/core/feeds.py
index 0ba3aed4d5796c612a27c64ac99bed4484a89090..546d7afa6e96bf740ff48b2598ebd8ff1a8c24a9 100644
--- a/aleksis/core/feeds.py
+++ b/aleksis/core/feeds.py
@@ -2,10 +2,14 @@ from typing import Any
 
 from django.conf import settings
 from django.core.handlers.wsgi import WSGIRequest
+from django.utils.formats import date_format
 from django.utils.functional import classproperty
+from django.utils.translation import gettext_lazy as _
+from django_ical.utils import build_rrule_from_text
 from django_ical.views import ICalFeed
 
-from aleksis.core.util.core_helpers import get_site_preferences
+from aleksis.core import models
+from aleksis.core.util.core_helpers import get_site_preferences, queryset_rules_filter
 
 
 class PersonalICalFeedBase(ICalFeed):
@@ -36,3 +40,40 @@ class PersonalICalFeedBase(ICalFeed):
     @classproperty
     def subclass_choices(cls):
         return [(subclass.__name__, f"{subclass.title} – {subclass.description}") for subclass in cls.subclasses_list]
+
+
+class BirthdayFeed(PersonalICalFeedBase):
+    """
+    Birthday calendar feed
+    """
+    title = _("Birthday Calendar")
+    description = _("A Calendar of Birthdays")
+    file_name = "birthdays.ics"
+
+    def items(self):
+        from aleksis.core.models import Person
+
+        return queryset_rules_filter(
+            obj=self.person.user,
+            perm="core.view_personal_details_rule",
+            queryset=Person.objects.filter(date_of_birth__isnull=False),
+        )
+
+    def item_title(self, item: "models.Person"):
+        return _("%(first_name)s %(last_name)s's birthday") % {
+            "first_name": item.first_name,
+            "last_name": item.last_name,
+        }
+
+    def item_description(self, item: "models.Person"):
+        return _("%(first_name)s %(last_name)s was born on %(birthday)s") % {
+            "first_name": item.first_name,
+            "last_name": item.last_name,
+            "birthday": date_format(item.date_of_birth),
+        }
+
+    def item_start_datetime(self, item):
+        return item.date_of_birth
+
+    def item_rrule(self, item):
+        return build_rrule_from_text("FREQ=YEARLY")