diff --git a/public-legacy/manage/users/user.php b/public-legacy/manage/users/user.php
index 23cea501..38f7a441 100644
--- a/public-legacy/manage/users/user.php
+++ b/public-legacy/manage/users/user.php
@@ -21,6 +21,7 @@ $canManagePerms = perms_check_user(MSZ_PERMS_USER, $currentUserId, MSZ_PERM_USER
 $canManageNotes = perms_check_user(MSZ_PERMS_USER, $currentUserId, MSZ_PERM_USER_MANAGE_NOTES);
 $canManageWarnings = perms_check_user(MSZ_PERMS_USER, $currentUserId, MSZ_PERM_USER_MANAGE_WARNINGS);
 $canManageBans = perms_check_user(MSZ_PERMS_USER, $currentUserId, MSZ_PERM_USER_MANAGE_BANS);
+$canImpersonate = perms_check_user(MSZ_PERMS_USER, $currentUserId, MSZ_PERM_USER_IMPERSONATE);
 $hasAccess = $canManageUsers || $canManageNotes || $canManageWarnings || $canManageBans;
 
 if(!$hasAccess) {
@@ -44,15 +45,24 @@ $permissions = $canEditPerms ? manage_perms_list(perms_get_user_raw($userId)) :
 
 if(CSRF::validateRequest() && $canEdit) {
     if(!empty($_POST['impersonate_user'])) {
-        if(!$currentUser->isSuper()) {
+        if(!$canImpersonate) {
             $notices[] = 'You must be a super user to do this.';
         } elseif(!is_string($_POST['impersonate_user']) || $_POST['impersonate_user'] !== 'meow') {
             $notices[] = 'You didn\'t say the magic word.';
         } else {
-            $authToken->setImpersonatedUserId($userInfo->getId());
-            $authToken->applyCookie();
-            url_redirect('index');
-            return;
+            $allowToImpersonate = $currentUser->isSuper();
+
+            if(!$allowToImpersonate) {
+                $allowImpersonateUsers = $msz->getConfig()->getArray(sprintf('impersonate.allow.u%s', $currentUser->getId()));
+                $allowToImpersonate = in_array((string)$userInfo->getId(), $allowImpersonateUsers, true);
+            }
+
+            if($allowToImpersonate) {
+                $authToken->setImpersonatedUserId($userInfo->getId());
+                $authToken->applyCookie();
+                url_redirect('index');
+                return;
+            } else $notices[] = 'You aren\'t allowed to impersonate this user.';
         }
     }
 
@@ -207,5 +217,6 @@ Template::render('manage.users.user', [
     'can_manage_notes' => $canManageNotes,
     'can_manage_warnings' => $canManageWarnings,
     'can_manage_bans' => $canManageBans,
+    'can_impersonate' => $canImpersonate,
     'permissions' => $permissions ?? [],
 ]);
diff --git a/public/index.php b/public/index.php
index 7a0dc78f..020e7658 100644
--- a/public/index.php
+++ b/public/index.php
@@ -112,19 +112,33 @@ if($authToken->isValid()) {
                 if($sessionInfo->shouldBumpExpires())
                     $authToken->applyCookie($sessionInfo->getExpiresTime());
 
-                // only allow impersonation when super user
-                if($authToken->hasImpersonatedUserId() && $userInfo->isSuper()) {
-                    $userInfoReal = $userInfo;
+                if($authToken->hasImpersonatedUserId()) {
+                    $allowToImpersonate = $userInfo->isSuper();
+                    $impersonatedUserId = $authToken->getImpersonatedUserId();
 
-                    try {
-                        $userInfo = User::byId($authToken->getImpersonatedUserId());
-                    } catch(RuntimeException $ex) {
-                        $userInfo = $userInfoReal;
+                    if(!$allowToImpersonate) {
+                        $allowImpersonateUsers = $cfg->getArray(sprintf('impersonate.allow.u%s', $userInfo->getId()));
+                        $allowToImpersonate = in_array((string)$impersonatedUserId, $allowImpersonateUsers, true);
+                    }
+
+                    $removeImpersonationData = !$allowToImpersonate;
+                    if($allowToImpersonate) {
+                        $userInfoReal = $userInfo;
+
+                        try {
+                            $userInfo = User::byId($impersonatedUserId);
+                        } catch(RuntimeException $ex) {
+                            $userInfo = $userInfoReal;
+                            $removeImpersonationData = true;
+                        }
+
+                        $userInfo->setCurrent();
+                    }
+
+                    if($removeImpersonationData) {
                         $authToken->removeImpersonatedUserId();
                         $authToken->applyCookie();
                     }
-
-                    $userInfo->setCurrent();
                 }
             }
         }
diff --git a/src/manage.php b/src/manage.php
index a2e13400..63632f7a 100644
--- a/src/manage.php
+++ b/src/manage.php
@@ -211,6 +211,11 @@ function manage_perms_list(array $rawPerms): array {
                     'title' => 'Can manage user bans.',
                     'perm' => MSZ_PERM_USER_MANAGE_BANS,
                 ],
+                [
+                    'section' => 'impersonate',
+                    'title' => 'Can impersonate select users.',
+                    'perm' => MSZ_PERM_USER_IMPERSONATE,
+                ],
             ],
         ],
         [
diff --git a/src/perms.php b/src/perms.php
index e5ab6de6..53881317 100644
--- a/src/perms.php
+++ b/src/perms.php
@@ -23,6 +23,7 @@ define('MSZ_PERM_USER_MANAGE_WARNINGS',     0x01000000);
 //define('MSZ_PERM_USER_MANAGE_BLACKLISTS', 0x02000000); // Replaced with MSZ_PERM_GENERAL_MANAGE_BLACKLIST
 define('MSZ_PERM_USER_MANAGE_NOTES',        0x04000000);
 define('MSZ_PERM_USER_MANAGE_BANS',         0x08000000);
+define('MSZ_PERM_USER_IMPERSONATE',         0x10000000);
 
 define('MSZ_PERMS_CHANGELOG', 'changelog');
 define('MSZ_PERM_CHANGELOG_MANAGE_CHANGES',   0x00000001);
diff --git a/templates/manage/users/user.twig b/templates/manage/users/user.twig
index ced3b819..a0ecb41d 100644
--- a/templates/manage/users/user.twig
+++ b/templates/manage/users/user.twig
@@ -164,7 +164,9 @@
                     <button class="input__button manage__user__button">Send</button>
                 </div>
             </form>
+        {% endif %}
 
+        {% if can_impersonate %}
             <form method="post" action="{{ url('manage-user', {'user': user_info.id}) }}" class="container manage__user__container">
                 {{ container_title('Impersonate ' ~ user_info.username ~ ' (' ~ user_info.id ~ ')') }}