diff --git a/js/src/main/scala/cs214/webapp/client/Pages.scala b/js/src/main/scala/cs214/webapp/client/Pages.scala
index 30bf5d16f0830c55169fc24f5dbd46ce4779ede9..78617787a08d98384ae05c4e08d65215502b94ce 100644
--- a/js/src/main/scala/cs214/webapp/client/Pages.scala
+++ b/js/src/main/scala/cs214/webapp/client/Pages.scala
@@ -269,9 +269,16 @@ case class AppPage(appId: AppId, uiId: UIId, instanceId: InstanceId, userId: Use
       frag(header(id := "banner"), tag("section")(id := "app"))
     Requests.instanceInfo(instanceId).map: appInfo =>
       val hostName = dom.window.location.hostname
+      val protocol = if dom.window.location.protocol.startsWith("https") then "wss" else "ws"
+      val port = {
+          val p = dom.window.location.port
+          if p.length == 0 then (if protocol == "wss" then "443" else "80") else p
+      }
       val endpoint = appInfo.wsEndpoint
-        .replace("{{hostName}}", hostName)
-        .replace("{{userId}}", URLEncoder.encode(userId, "UTF-8"))
+          .replace("{{protocol}}", protocol)
+          .replace("{{hostName}}", hostName)
+          .replace("{{port}}", port)
+          .replace("{{userId}}", URLEncoder.encode(userId, "UTF-8"))
       IpBanner(appInfo.shareUrl).renderInto(target.querySelector("#banner"))
       app.init(instanceId, userId, endpoint, target.querySelector("#app"))
 
diff --git a/jvm/src/main/scala/cs214/webapp/server/web/WebServerRoutes.scala b/jvm/src/main/scala/cs214/webapp/server/web/WebServerRoutes.scala
index e42a9ac8fe71f6e3ad1a646d89774bc12078f95a..de0b74946fbcae4ff5fa502a573372a51402a4b6 100644
--- a/jvm/src/main/scala/cs214/webapp/server/web/WebServerRoutes.scala
+++ b/jvm/src/main/scala/cs214/webapp/server/web/WebServerRoutes.scala
@@ -54,7 +54,7 @@ private[server] final case class WebServerRoutes()(using cc: castor.Context, log
       if WebServer.apps.contains(instanceId) then
         val app = WebServer.apps(instanceId).instance
         val shareUrl = f"http://$hostAddress:${Config.HTTP_PORT}${Endpoints.Api.root}/${app.appInfo.id}/$instanceId/"
-        val wsEndpoint = f"ws://{{hostName}}:${Config.HTTP_PORT}${Endpoints.WebSocket}/$instanceId/{{userId}}"
+        val wsEndpoint = f"{{protocol}}://{{hostName}}:{{port}}${Endpoints.WebSocket}/$instanceId/{{userId}}"
         val response = InstanceInfoResponse(instanceId, app.registeredUsers, wsEndpoint, shareUrl)
         InstanceInfoResponse.Wire.encode(response)
       else