diff --git a/web/controller/inbound.go b/web/controller/inbound.go
index c22ce192..d572cc40 100644
--- a/web/controller/inbound.go
+++ b/web/controller/inbound.go
@@ -12,6 +12,10 @@ import (
 	"github.com/gin-gonic/gin"
 )
 
+type ClientOnlineIPsResponse struct {
+	Count int `json:"count"`
+}
+
 type InboundController struct {
 	inboundService service.InboundService
 	xrayService    service.XrayService
@@ -30,6 +34,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) {
 	g.POST("/add", a.addInbound)
 	g.POST("/del/:id", a.delInbound)
 	g.POST("/update/:id", a.updateInbound)
+	g.POST("/clientOnlineIps/:email", a.getClientOnlineIPs)
 	g.POST("/clientIps/:email", a.getClientIps)
 	g.POST("/clearClientIps/:email", a.clearClientIps)
 	g.POST("/addClient", a.addInboundClient)
@@ -146,6 +151,21 @@ func (a *InboundController) updateInbound(c *gin.Context) {
 	}
 }
 
+func (a *InboundController) getClientOnlineIPs(c *gin.Context) {
+	email := c.Param("email")
+
+	count, err := a.inboundService.GetClientOnlineIPs(email)
+	res := &ClientOnlineIPsResponse{
+		Count: count,
+	}
+	if err != nil {
+		jsonObj(c, res, err)
+		return
+	}
+
+	jsonObj(c, res, nil)
+}
+
 func (a *InboundController) getClientIps(c *gin.Context) {
 	email := c.Param("email")
 
diff --git a/web/controller/util.go b/web/controller/util.go
index 440de276..04084f41 100644
--- a/web/controller/util.go
+++ b/web/controller/util.go
@@ -46,8 +46,13 @@ func jsonMsgObj(c *gin.Context, msg string, obj interface{}, err error) {
 		}
 	} else {
 		m.Success = false
-		m.Msg = msg + " " + I18nWeb(c, "fail") + ": " + err.Error()
-		logger.Warning(msg+" "+I18nWeb(c, "fail")+": ", err)
+		if msg != "" {
+			m.Msg = msg + " " + I18nWeb(c, "fail") + ": " + err.Error()
+			logger.Warning(msg+" "+I18nWeb(c, "fail")+": ", err)
+		} else {
+			m.Msg = I18nWeb(c, "fail") + ": " + err.Error()
+			logger.Warning(I18nWeb(c, "fail")+": ", err)
+		}
 	}
 	c.JSON(http.StatusOK, m)
 }
diff --git a/web/service/inbound.go b/web/service/inbound.go
index 4f28af21..71c0f132 100644
--- a/web/service/inbound.go
+++ b/web/service/inbound.go
@@ -1855,6 +1855,18 @@ func (s *InboundService) SearchClientTraffic(query string) (traffic *xray.Client
 	return traffic, nil
 }
 
+func (s *InboundService) GetClientOnlineIPs(email string) (int, error) {
+	s.xrayApi.Init(p.GetAPIPort())
+	defer s.xrayApi.Close()
+
+	count, err := s.xrayApi.GetClientOnlineIPs(email)
+	if err != nil {
+		logger.Debug("Failed to fetch Xray Client Online IPs:", err)
+		return 0, err
+	}
+	return count, nil
+}
+
 func (s *InboundService) GetInboundClientIps(clientEmail string) (string, error) {
 	db := database.GetDB()
 	InboundClientIps := &model.InboundClientIps{}
diff --git a/web/service/server.go b/web/service/server.go
index 21ab66f5..4c9731f5 100644
--- a/web/service/server.go
+++ b/web/service/server.go
@@ -61,6 +61,7 @@ type Status struct {
 		State    ProcessState `json:"state"`
 		ErrorMsg string       `json:"errorMsg"`
 		Version  string       `json:"version"`
+		ApiPort  string       `json:"apiPort"`
 	} `json:"xray"`
 	Uptime   uint64    `json:"uptime"`
 	Loads    []float64 `json:"loads"`
@@ -239,6 +240,7 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status {
 		status.Xray.ErrorMsg = s.xrayService.GetXrayResult()
 	}
 	status.Xray.Version = s.xrayService.GetXrayVersion()
+	status.Xray.ApiPort = s.xrayService.GetXrayApiPort()
 	var rtm runtime.MemStats
 	runtime.ReadMemStats(&rtm)
 
diff --git a/web/service/xray.go b/web/service/xray.go
index d37c963a..5998b5f0 100644
--- a/web/service/xray.go
+++ b/web/service/xray.go
@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"errors"
 	"sync"
+	"strconv"
 
 	"x-ui/logger"
 	"x-ui/xray"
@@ -56,6 +57,13 @@ func (s *XrayService) GetXrayVersion() string {
 	return p.GetVersion()
 }
 
+func (s *XrayService) GetXrayApiPort() string {
+	if p == nil {
+		return "Unknown"
+	}
+	return strconv.Itoa(p.GetAPIPort())
+}
+
 func RemoveIndex(s []interface{}, index int) []interface{} {
 	return append(s[:index], s[index+1:]...)
 }
diff --git a/xray/api.go b/xray/api.go
index 727ab526..988e3b44 100644
--- a/xray/api.go
+++ b/xray/api.go
@@ -204,6 +204,35 @@ func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) {
 	return mapToSlice(tagTrafficMap), mapToSlice(emailTrafficMap), nil
 }
 
+func (x *XrayAPI) GetClientOnlineIPs(email string) (int, error) {
+	if x.grpcClient == nil {
+		return 0, common.NewError("xray api is not initialized")
+	}
+
+	statName := "user>>>" + email + ">>>online"
+
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
+	defer cancel()
+
+	if x.StatsServiceClient == nil {
+		return 0, common.NewError("xray StatusServiceClient is not initialized")
+	}
+
+	r := &statsService.GetStatsRequest{
+		Name:   statName,
+		Reset_: false,
+	}
+	resp, err := (*x.StatsServiceClient).GetStatsOnline(ctx, r)
+	if err != nil {
+		logger.Debug("Failed to query Xray statsonline:", err)
+		return 0, err
+	}
+
+	count := resp.GetStat().Value
+	
+	return int(count), nil
+}
+
 func processTraffic(matches []string, value int64, trafficMap map[string]*Traffic) {
 	isInbound := matches[1] == "inbound"
 	tag := matches[2]