diff --git a/app/finders/repositories/changelog_tag_finder.rb b/app/finders/repositories/changelog_tag_finder.rb
index 7dd7404730f779245079f9e213bb248cbb22a3d3..d90ac6cc98fa39d7481f8320a297e04f3d471ed7 100644
--- a/app/finders/repositories/changelog_tag_finder.rb
+++ b/app/finders/repositories/changelog_tag_finder.rb
@@ -33,40 +33,16 @@ def initialize(project, regex: Gitlab::Changelog::Config::DEFAULT_TAG_REGEX)
 
     def execute(new_version)
       tags = {}
-      versions = [new_version]
-
-      begin
-        regex = Gitlab::UntrustedRegexp.new(@regex)
-      rescue RegexpError => e
-        # The error messages produced by default are not very helpful, so we
-        # raise a better one here. We raise the specific error here so its
-        # message is displayed in the API (where we catch this specific
-        # error).
-        raise(
-          Gitlab::Changelog::Error,
-          "The regular expression to use for finding the previous tag for a version is invalid: #{e.message}"
-        )
-      end
-
-      @project.repository.tags.each do |tag|
-        matches = regex.match(tag.name)
-
-        next unless matches
 
-        # When using this class for generating changelog data for a range of
-        # commits, we want to compare against the tag of the last _stable_
-        # release; not some random RC that came after that.
-        next if matches[:pre]
+      requested_version = extract_version(new_version)
+      return unless requested_version
 
-        major = matches[:major]
-        minor = matches[:minor]
-        patch = matches[:patch]
-        build = matches[:meta]
+      versions = [requested_version]
 
-        next unless major && minor && patch
+      @project.repository.tags.each do |tag|
+        version = extract_version(tag.name)
 
-        version = "#{major}.#{minor}.#{patch}"
-        version += "+#{build}" if build
+        next unless version
 
         tags[version] = tag
         versions << version
@@ -74,9 +50,47 @@ def execute(new_version)
 
       VersionSorter.sort!(versions)
 
-      index = versions.index(new_version)
+      index = versions.index(requested_version)
 
       tags[versions[index - 1]] if index&.positive?
     end
+
+    private
+
+    def version_matcher
+      @version_matcher ||= Gitlab::UntrustedRegexp.new(@regex)
+    rescue RegexpError => e
+      # The error messages produced by default are not very helpful, so we
+      # raise a better one here. We raise the specific error here so its
+      # message is displayed in the API (where we catch this specific
+      # error).
+      raise(
+        Gitlab::Changelog::Error,
+        "The regular expression to use for finding the previous tag for a version is invalid: #{e.message}"
+      )
+    end
+
+    def extract_version(string)
+      matches = version_matcher.match(string)
+
+      return unless matches
+
+      # When using this class for generating changelog data for a range of
+      # commits, we want to compare against the tag of the last _stable_
+      # release; not some random RC that came after that.
+      return if matches[:pre]
+
+      major = matches[:major]
+      minor = matches[:minor]
+      patch = matches[:patch]
+      build = matches[:meta]
+
+      return unless major && minor && patch
+
+      version = "#{major}.#{minor}.#{patch}"
+      version += "+#{build}" if build
+
+      version
+    end
   end
 end
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 638e3e57cf64aff73cf9fb523e7b919701b012b4..ced0e313df8d276d52d1c3bf85866b36c4f7f792 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -366,6 +366,9 @@ If the `version` attribute is `2.1.0`, GitLab uses tag `v2.0.0`. And when the
 version is `1.1.1`, or `1.2.0`, GitLab uses tag v1.1.0. The tag `v1.0.0-pre1` is
 never used, because pre-release tags are ignored.
 
+The `version` attribute can start with `v`. For example: `v1.0.0`.
+The response is the same as for `version` value `1.0.0`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/437616) in GitLab 16.9.
+
 If `from` is unspecified and no tag to use is found, the API produces an error.
 To solve such an error, you must explicitly specify a value for the `from`
 attribute.
diff --git a/spec/finders/repositories/changelog_tag_finder_spec.rb b/spec/finders/repositories/changelog_tag_finder_spec.rb
index cd79beb3e9ee4239eed8c46ccadda645c4a4ebd2..73e302efd27d6fb0164f1d85e26fb7f965097e8c 100644
--- a/spec/finders/repositories/changelog_tag_finder_spec.rb
+++ b/spec/finders/repositories/changelog_tag_finder_spec.rb
@@ -2,7 +2,7 @@
 
 require 'spec_helper'
 
-RSpec.describe Repositories::ChangelogTagFinder do
+RSpec.describe Repositories::ChangelogTagFinder, feature_category: :source_code_management do
   let(:project) { build_stubbed(:project) }
   let(:finder) { described_class.new(project) }
 
@@ -35,6 +35,10 @@
         expect(finder.execute('1.0.0')).to eq(tag4)
         expect(finder.execute('0.9.0')).to eq(tag6)
         expect(finder.execute('0.6.0')).to eq(tag7)
+
+        # with v at the beginning
+        expect(finder.execute('v2.1.0')).to eq(tag3)
+        expect(finder.execute('wrong_version')).to eq(nil)
       end
     end