diff --git a/bookwyrm/templates/403.html b/bookwyrm/templates/403.html
new file mode 100644
index 000000000..b7927da7e
--- /dev/null
+++ b/bookwyrm/templates/403.html
@@ -0,0 +1,16 @@
+{% extends 'layout.html' %}
+{% load i18n %}
+{% load utilities %}
+
+{% block title %}{% trans "Oh no!" %}{% endblock %}
+
+{% block content %}
+
+
{% trans "Permission Denied" %}
+ {% blocktrans trimmed with level=request.user|get_user_permission %}
+
You do not have permission to view this page. Your user permission level is {{ level }}
.
+
If you think you should have access to this page, please speak to your BookWyrm server administrator.
+ {% endblocktrans %}
+
+{% endblock %}
+
diff --git a/bookwyrm/templatetags/utilities.py b/bookwyrm/templatetags/utilities.py
index 42e67990f..99575d85f 100644
--- a/bookwyrm/templatetags/utilities.py
+++ b/bookwyrm/templatetags/utilities.py
@@ -125,3 +125,10 @@ def id_to_username(user_id):
value = f"{name}@{domain}"
return value
+
+
+@register.filter(name="get_user_permission")
+def get_user_permission(user):
+ """given a user, return their permission level"""
+
+ return user.groups.first() if user.groups.first() else "User"
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py
index 8541f4fb6..2cab2aaa9 100644
--- a/bookwyrm/urls.py
+++ b/bookwyrm/urls.py
@@ -792,3 +792,6 @@ urlpatterns.extend(staticfiles_urlpatterns())
# pylint: disable=invalid-name
handler500 = "bookwyrm.views.server_error"
+
+# pylint: disable=invalid-name
+handler403 = "bookwyrm.views.permission_required"
diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py
index 2d2e97f52..5af42f02b 100644
--- a/bookwyrm/views/__init__.py
+++ b/bookwyrm/views/__init__.py
@@ -167,3 +167,4 @@ from .annual_summary import (
summary_revoke_key,
)
from .server_error import server_error
+from .permission_required import permission_required
diff --git a/bookwyrm/views/permission_required.py b/bookwyrm/views/permission_required.py
new file mode 100644
index 000000000..8e12c38ef
--- /dev/null
+++ b/bookwyrm/views/permission_required.py
@@ -0,0 +1,8 @@
+"""custom 403 handler to enable context processors"""
+from django.template.response import TemplateResponse
+
+
+def permission_required(request, exception): # pylint: disable=unused-argument
+ """permission denied page"""
+
+ return TemplateResponse(request, "403.html")