diff --git a/LICENSE.txt b/LICENSE.txt
index e562a0b4c..fb055807b 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -63,6 +63,7 @@ Zughy:
   textures/base/pack/settings_btn.png
   textures/base/pack/settings_info.png
   textures/base/pack/settings_reset.png
+  textures/base/pack/server_view_clients.png
 
 appgurueu:
   textures/base/pack/server_incompatible.png
diff --git a/builtin/mainmenu/dlg_clients_list.lua b/builtin/mainmenu/dlg_clients_list.lua
new file mode 100644
index 000000000..2ea021c5e
--- /dev/null
+++ b/builtin/mainmenu/dlg_clients_list.lua
@@ -0,0 +1,49 @@
+-- Luanti
+-- Copyright (C) 2024 siliconsniffer
+-- SPDX-License-Identifier: LGPL-2.1-or-later
+
+
+local function clients_list_formspec(dialogdata)
+	local TOUCH_GUI = core.settings:get_bool("touch_gui")
+	local clients_list = dialogdata.server.clients_list
+	local servername   = dialogdata.server.name
+
+	local function fmt_formspec_list(clients_list)
+		local escaped = {}
+		for i, str in ipairs(clients_list) do
+			escaped[i] = core.formspec_escape(str)
+		end
+		return table.concat(escaped, ",")
+	end
+
+	local formspec = {
+		"formspec_version[8]",
+		"size[6,9.5]",
+		TOUCH_GUI and "padding[0.01,0.01]" or "",
+		"hypertext[0,0;6,1.5;;<global margin=5 halign=center valign=middle>",
+			fgettext("This is the list of clients connected to\n$1",
+				"<b>" .. core.hypertext_escape(servername) .. "</b>") .. "]",
+		"textlist[0.5,1.5;5,6.8;;" .. fmt_formspec_list(clients_list) .. "]",
+		"button[1.5,8.5;3,0.8;quit;OK]"
+	}
+	return table.concat(formspec, "")
+end
+
+
+local function clients_list_buttonhandler(this, fields)
+	if fields.quit then
+        this:delete()
+		return true
+	end
+	return false
+end
+
+
+function create_clientslist_dialog(server)
+	local retval = dialog_create("dlg_clients_list",
+		clients_list_formspec,
+		clients_list_buttonhandler,
+		nil)
+	retval.data.server = server
+	return retval
+end
diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua
index 41519b2ee..4e1c201cd 100644
--- a/builtin/mainmenu/init.lua
+++ b/builtin/mainmenu/init.lua
@@ -55,6 +55,7 @@ dofile(menupath .. DIR_DELIM .. "dlg_register.lua")
 dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
 dofile(menupath .. DIR_DELIM .. "dlg_version_info.lua")
 dofile(menupath .. DIR_DELIM .. "dlg_reinstall_mtg.lua")
+dofile(menupath .. DIR_DELIM .. "dlg_clients_list.lua")
 
 local tabs = {
 	content  = dofile(menupath .. DIR_DELIM .. "tab_content.lua"),
diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua
index a73b863ce..558e2aff2 100644
--- a/builtin/mainmenu/tab_online.lua
+++ b/builtin/mainmenu/tab_online.lua
@@ -108,16 +108,38 @@ local function get_formspec(tabview, name, tabdata)
 	end
 
 	if tabdata.selected then
-		if gamedata.fav then
-			retval = retval .. "tooltip[btn_delete_favorite;" .. fgettext("Remove favorite") .. "]"
-			retval = retval .. "style[btn_delete_favorite;padding=6]"
-			retval = retval .. "image_button[5,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir ..
-				"server_favorite_delete.png") .. ";btn_delete_favorite;]"
-		end
 		if gamedata.serverdescription then
 			retval = retval .. "textarea[0.25,1.85;5.25,2.7;;;" ..
 				core.formspec_escape(gamedata.serverdescription) .. "]"
 		end
+
+		local server = tabdata.lookup[tabdata.selected]
+
+		local clients_list = server and server.clients_list
+		local can_view_clients_list = clients_list and #clients_list > 0
+		if can_view_clients_list then
+			table.sort(clients_list, function(a, b)
+				return a:lower() < b:lower()
+			end)
+			local max_clients = 5
+			if #clients_list > max_clients then
+				retval = retval .. "tooltip[btn_view_clients;" ..
+						fgettext("Clients:\n$1", table.concat(clients_list, "\n", 1, max_clients)) .. "\n..." .. "]"
+			else
+				retval = retval .. "tooltip[btn_view_clients;" ..
+						fgettext("Clients:\n$1", table.concat(clients_list, "\n")) .. "]"
+			end
+			retval = retval .. "style[btn_view_clients;padding=6]"
+			retval = retval .. "image_button[5,1.3;0.5,0.5;" .. core.formspec_escape(defaulttexturedir ..
+				"server_view_clients.png") .. ";btn_view_clients;]"
+		end
+
+		if gamedata.fav then
+			retval = retval .. "tooltip[btn_delete_favorite;" .. fgettext("Remove favorite") .. "]"
+			retval = retval .. "style[btn_delete_favorite;padding=6]"
+			retval = retval .. "image_button[" .. (can_view_clients_list and "4.5" or "5") .. ",1.3;0.5,0.5;" ..
+				core.formspec_escape(defaulttexturedir .. "server_favorite_delete.png") .. ";btn_delete_favorite;]"
+		end
 	end
 
 	retval = retval .. "container_end[]"
@@ -315,6 +337,14 @@ local function main_button_handler(tabview, fields, name, tabdata)
 		return true
 	end
 
+	if fields.btn_view_clients then
+		local dlg = create_clientslist_dialog(tabdata.lookup[tabdata.selected])
+		dlg:set_parent(tabview)
+		tabview:hide()
+		dlg:show()
+		return true
+	end
+
 	if fields.btn_mp_clear then
 		tabdata.search_for = ""
 		menudata.search_result = nil
diff --git a/textures/base/pack/server_view_clients.png b/textures/base/pack/server_view_clients.png
new file mode 100644
index 000000000..87b569f93
Binary files /dev/null and b/textures/base/pack/server_view_clients.png differ