diff --git a/models/repo/fork.go b/models/repo/fork.go
index 07cd31c269..632e91c2bb 100644
--- a/models/repo/fork.go
+++ b/models/repo/fork.go
@@ -7,6 +7,7 @@ import (
 	"context"
 
 	"code.gitea.io/gitea/models/db"
+	"code.gitea.io/gitea/models/unit"
 	user_model "code.gitea.io/gitea/models/user"
 
 	"xorm.io/builder"
@@ -54,9 +55,9 @@ func GetUserFork(ctx context.Context, repoID, userID int64) (*Repository, error)
 	return &forkedRepo, nil
 }
 
-// GetForks returns all the forks of the repository
-func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions) ([]*Repository, error) {
-	sess := db.GetEngine(ctx)
+// GetForks returns all the forks of the repository that are visible to the user.
+func GetForks(ctx context.Context, repo *Repository, user *user_model.User, listOptions db.ListOptions) ([]*Repository, int64, error) {
+	sess := db.GetEngine(ctx).Where(AccessibleRepositoryCondition(user, unit.TypeInvalid))
 
 	var forks []*Repository
 	if listOptions.Page == 0 {
@@ -66,7 +67,8 @@ func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions)
 		sess = db.SetSessionPagination(sess, &listOptions)
 	}
 
-	return forks, sess.Find(&forks, &Repository{ForkID: repo.ID})
+	count, err := sess.FindAndCount(&forks, &Repository{ForkID: repo.ID})
+	return forks, count, err
 }
 
 // IncrementRepoForkNum increment repository fork number
diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go
index 212cc7a93b..41bac96ce4 100644
--- a/routers/api/v1/repo/fork.go
+++ b/routers/api/v1/repo/fork.go
@@ -55,7 +55,7 @@ func ListForks(ctx *context.APIContext) {
 	//   "404":
 	//     "$ref": "#/responses/notFound"
 
-	forks, err := repo_model.GetForks(ctx, ctx.Repo.Repository, utils.GetListOptions(ctx))
+	forks, total, err := repo_model.GetForks(ctx, ctx.Repo.Repository, ctx.Doer, utils.GetListOptions(ctx))
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "GetForks", err)
 		return
@@ -70,7 +70,7 @@ func ListForks(ctx *context.APIContext) {
 		apiForks[i] = convert.ToRepo(ctx, fork, permission)
 	}
 
-	ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumForks))
+	ctx.SetTotalCountHeader(total)
 	ctx.JSON(http.StatusOK, apiForks)
 }
 
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index e98cd46c4e..48a84bf432 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -1221,11 +1221,8 @@ func Forks(ctx *context.Context) {
 		page = 1
 	}
 
-	pager := context.NewPagination(ctx.Repo.Repository.NumForks, setting.MaxForksPerPage, page, 5)
-	ctx.Data["Page"] = pager
-
-	forks, err := repo_model.GetForks(ctx, ctx.Repo.Repository, db.ListOptions{
-		Page:     pager.Paginater.Current(),
+	forks, total, err := repo_model.GetForks(ctx, ctx.Repo.Repository, ctx.Doer, db.ListOptions{
+		Page:     page,
 		PageSize: setting.MaxForksPerPage,
 	})
 	if err != nil {
@@ -1233,6 +1230,9 @@ func Forks(ctx *context.Context) {
 		return
 	}
 
+	pager := context.NewPagination(int(total), setting.MaxForksPerPage, page, 5)
+	ctx.Data["Page"] = pager
+
 	for _, fork := range forks {
 		if err = fork.LoadOwner(ctx); err != nil {
 			ctx.ServerError("LoadOwner", err)
diff --git a/tests/integration/api_fork_test.go b/tests/integration/api_fork_test.go
index b80b4c6645..15b60f8344 100644
--- a/tests/integration/api_fork_test.go
+++ b/tests/integration/api_fork_test.go
@@ -18,6 +18,8 @@ import (
 	"code.gitea.io/gitea/modules/test"
 	"code.gitea.io/gitea/routers"
 	"code.gitea.io/gitea/tests"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func TestAPIForkAsAdminIgnoringLimits(t *testing.T) {
@@ -108,3 +110,44 @@ func TestAPIDisabledForkRepo(t *testing.T) {
 		})
 	})
 }
+
+func TestAPIForkListPrivateRepo(t *testing.T) {
+	defer tests.PrepareTestEnv(t)()
+
+	session := loginUser(t, "user5")
+	token := getTokenForLoggedInUser(t, session,
+		auth_model.AccessTokenScopeWriteRepository,
+		auth_model.AccessTokenScopeWriteOrganization)
+	org23 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23, Visibility: api.VisibleTypePrivate})
+
+	req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{
+		Organization: &org23.Name,
+	}).AddTokenAuth(token)
+	MakeRequest(t, req, http.StatusAccepted)
+
+	t.Run("Anomynous", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+
+		req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks")
+		resp := MakeRequest(t, req, http.StatusOK)
+
+		var forks []*api.Repository
+		DecodeJSON(t, resp, &forks)
+
+		assert.Empty(t, forks)
+		assert.EqualValues(t, "0", resp.Header().Get("X-Total-Count"))
+	})
+
+	t.Run("Logged in", func(t *testing.T) {
+		defer tests.PrintCurrentTest(t)()
+
+		req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks").AddTokenAuth(token)
+		resp := MakeRequest(t, req, http.StatusOK)
+
+		var forks []*api.Repository
+		DecodeJSON(t, resp, &forks)
+
+		assert.Len(t, forks, 1)
+		assert.EqualValues(t, "1", resp.Header().Get("X-Total-Count"))
+	})
+}
diff --git a/tests/integration/repo_fork_test.go b/tests/integration/repo_fork_test.go
index e58e9fe201..c6984a12fb 100644
--- a/tests/integration/repo_fork_test.go
+++ b/tests/integration/repo_fork_test.go
@@ -17,6 +17,7 @@ import (
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/test"
 	"code.gitea.io/gitea/routers"
 	repo_service "code.gitea.io/gitea/services/repository"
@@ -238,3 +239,34 @@ func TestRepoForkToOrg(t *testing.T) {
 		})
 	})
 }
+
+func TestForkListPrivateRepo(t *testing.T) {
+	forkItemSelector := ".tw-flex.tw-items-center.tw-py-2"
+
+	onGiteaRun(t, func(t *testing.T, u *url.URL) {
+		session := loginUser(t, "user5")
+		org23 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 23, Visibility: structs.VisibleTypePrivate})
+
+		testRepoFork(t, session, "user2", "repo1", org23.Name, "repo1")
+
+		t.Run("Anomynous", func(t *testing.T) {
+			defer tests.PrintCurrentTest(t)()
+
+			req := NewRequest(t, "GET", "/user2/repo1/forks")
+			resp := MakeRequest(t, req, http.StatusOK)
+			htmlDoc := NewHTMLParser(t, resp.Body)
+
+			htmlDoc.AssertElement(t, forkItemSelector, false)
+		})
+
+		t.Run("Logged in", func(t *testing.T) {
+			defer tests.PrintCurrentTest(t)()
+
+			req := NewRequest(t, "GET", "/user2/repo1/forks")
+			resp := session.MakeRequest(t, req, http.StatusOK)
+			htmlDoc := NewHTMLParser(t, resp.Body)
+
+			htmlDoc.AssertElement(t, forkItemSelector, true)
+		})
+	})
+}