diff --git a/docs/content/doc/advanced/migrations.en-us.md b/docs/content/doc/advanced/migrations.en-us.md
index 7db9cad81..2511f7af8 100644
--- a/docs/content/doc/advanced/migrations.en-us.md
+++ b/docs/content/doc/advanced/migrations.en-us.md
@@ -34,6 +34,7 @@ create a Downloader.
 ```Go
 type Downloader interface {
 	GetRepoInfo() (*Repository, error)
+	GetTopics() ([]string, error)
 	GetMilestones() ([]*Milestone, error)
 	GetReleases() ([]*Release, error)
 	GetLabels() ([]*Label, error)
diff --git a/modules/migrations/base/downloader.go b/modules/migrations/base/downloader.go
index f28d0b61e..ab5ca6dec 100644
--- a/modules/migrations/base/downloader.go
+++ b/modules/migrations/base/downloader.go
@@ -8,6 +8,7 @@ package base
 // Downloader downloads the site repo informations
 type Downloader interface {
 	GetRepoInfo() (*Repository, error)
+	GetTopics() ([]string, error)
 	GetMilestones() ([]*Milestone, error)
 	GetReleases() ([]*Release, error)
 	GetLabels() ([]*Label, error)
diff --git a/modules/migrations/base/uploader.go b/modules/migrations/base/uploader.go
index 8c1d64922..a3a9c9fac 100644
--- a/modules/migrations/base/uploader.go
+++ b/modules/migrations/base/uploader.go
@@ -9,6 +9,7 @@ package base
 type Uploader interface {
 	MaxBatchInsertSize(tp string) int
 	CreateRepo(repo *Repository, opts MigrateOptions) error
+	CreateTopics(topic ...string) error
 	CreateMilestones(milestones ...*Milestone) error
 	CreateReleases(releases ...*Release) error
 	CreateLabels(labels ...*Label) error
diff --git a/modules/migrations/git.go b/modules/migrations/git.go
index 335d44ec9..75d05976c 100644
--- a/modules/migrations/git.go
+++ b/modules/migrations/git.go
@@ -38,6 +38,11 @@ func (g *PlainGitDownloader) GetRepoInfo() (*base.Repository, error) {
 	}, nil
 }
 
+// GetTopics returns empty list for plain git repo
+func (g *PlainGitDownloader) GetTopics() ([]string, error) {
+	return []string{}, nil
+}
+
 // GetMilestones returns milestones
 func (g *PlainGitDownloader) GetMilestones() ([]*base.Milestone, error) {
 	return nil, ErrNotSupported
diff --git a/modules/migrations/gitea.go b/modules/migrations/gitea.go
index 45f324516..08244e5ab 100644
--- a/modules/migrations/gitea.go
+++ b/modules/migrations/gitea.go
@@ -97,6 +97,11 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
 	return err
 }
 
+// CreateTopics creates topics
+func (g *GiteaLocalUploader) CreateTopics(topics ...string) error {
+	return models.SaveTopics(g.repo.ID, topics...)
+}
+
 // CreateMilestones creates milestones
 func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) error {
 	var mss = make([]*models.Milestone, 0, len(milestones))
diff --git a/modules/migrations/github.go b/modules/migrations/github.go
index 93ba10854..c5f29cabb 100644
--- a/modules/migrations/github.go
+++ b/modules/migrations/github.go
@@ -118,6 +118,12 @@ func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) {
 	}, nil
 }
 
+// GetTopics return github topics
+func (g *GithubDownloaderV3) GetTopics() ([]string, error) {
+	r, _, err := g.client.Repositories.Get(g.ctx, g.repoOwner, g.repoName)
+	return r.Topics, err
+}
+
 // GetMilestones returns milestones
 func (g *GithubDownloaderV3) GetMilestones() ([]*base.Milestone, error) {
 	var perPage = 100
diff --git a/modules/migrations/github_test.go b/modules/migrations/github_test.go
index 54845ab42..62fce6bbc 100644
--- a/modules/migrations/github_test.go
+++ b/modules/migrations/github_test.go
@@ -71,6 +71,10 @@ func TestGitHubDownloadRepo(t *testing.T) {
 		OriginalURL: "https://github.com/go-gitea/gitea",
 	}, repo)
 
+	topics, err := downloader.GetTopics()
+	assert.NoError(t, err)
+	assert.Contains(t, topics, "gitea")
+
 	milestones, err := downloader.GetMilestones()
 	assert.NoError(t, err)
 	// before this tool release, we have 39 milestones on github.com/go-gitea/gitea
diff --git a/modules/migrations/migrate.go b/modules/migrations/migrate.go
index a86614c31..27782cb94 100644
--- a/modules/migrations/migrate.go
+++ b/modules/migrations/migrate.go
@@ -82,6 +82,17 @@ func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts
 		return err
 	}
 
+	log.Trace("migrating topics")
+	topics, err := downloader.GetTopics()
+	if err != nil {
+		return err
+	}
+	if len(topics) > 0 {
+		if err := uploader.CreateTopics(topics...); err != nil {
+			return err
+		}
+	}
+
 	if opts.Milestones {
 		log.Trace("migrating milestones")
 		milestones, err := downloader.GetMilestones()