diff --git a/doc/user/project/repository/code_suggestions/repository_xray.md b/doc/user/project/repository/code_suggestions/repository_xray.md
index e1894a273b468927d122d20897789f54c3af612c..54d58cece0ac17c7096475ee2fb903b91cd54ff3 100644
--- a/doc/user/project/repository/code_suggestions/repository_xray.md
+++ b/doc/user/project/repository/code_suggestions/repository_xray.md
@@ -47,6 +47,7 @@ The Repository X-Ray searches a maximum of two directory levels from the reposit
 | Java       | Gradle          | `build.gradle`       | 17.4 or later  |
 | Java       | Maven           | `pom.xml`            | 17.4 or later  |
 | Kotlin     | Gradle          | `build.gradle.kts`   | 17.5 or later  |
+| Python     | Pip             | `requirements.txt`   | 17.5 or later  |
 | Ruby       | RubyGems        | `Gemfile.lock`       | 17.4 or later  |
 
 ## Enable Repository X-Ray in your CI pipeline (deprecated)
diff --git a/ee/lib/ai/context/dependencies/config_files/constants.rb b/ee/lib/ai/context/dependencies/config_files/constants.rb
index 06db8164c7cd7ddaca6a2727427e636258fefba1..bd70a8a008c808195a9c04c5030128eb408c4b6d 100644
--- a/ee/lib/ai/context/dependencies/config_files/constants.rb
+++ b/ee/lib/ai/context/dependencies/config_files/constants.rb
@@ -23,6 +23,7 @@ module Constants
             ConfigFiles::JavaGradle,
             ConfigFiles::JavaMaven,
             ConfigFiles::KotlinGradle,
+            ConfigFiles::PythonPip,
             ConfigFiles::RubyGemsLock
           ].freeze
         end
diff --git a/ee/lib/ai/context/dependencies/config_files/python_pip.rb b/ee/lib/ai/context/dependencies/config_files/python_pip.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0ffec846df13d2d4193343fdc686d67eb46de9b5
--- /dev/null
+++ b/ee/lib/ai/context/dependencies/config_files/python_pip.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Ai
+  module Context
+    module Dependencies
+      module ConfigFiles
+        class PythonPip < Base
+          OPTION_REGEX = /^-/
+          NAME_VERSION_REGEX = /(?<name>^[^!=><~]+)(?<version>[!=><~]+.*$)?/
+          OTHER_SPECIFIERS_REGEX = /[@;]+.*$/ # Matches URL or other non-version specifiers at the end of line
+          COMMENT_ONLY_REGEX = /^#/
+          INLINE_COMMENT_REGEX = /\s+#.*$/
+
+          def self.file_name_glob
+            'requirements.txt'
+          end
+
+          def self.lang_name
+            'Python'
+          end
+
+          private
+
+          ### Example format:
+          #
+          # requests>=2.0,<3.0      # Version range
+          # numpy==1.26.4           # Exact version match
+          # fastapi-health!=0.3.0   # Exclusion
+          #
+          # # New supported formats
+          # pytest >= 2.6.4 ; python_version < '3.8'
+          # openpyxl == 3.1.2
+          # urllib3 @ https://github.com/path/main.zip
+          #
+          # # Nested requirement files currently not supported
+          # # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/491800
+          # -r other_requirements.txt
+          # # Other options
+          # -i https://pypi.org/simple
+          # --python-version 3
+          #
+          def extract_libs
+            content.each_line.filter_map do |line|
+              line.strip!
+              next if line.blank? || Regexp.union(COMMENT_ONLY_REGEX, OPTION_REGEX).match?(line)
+
+              parse_lib(line)
+            end
+          end
+
+          def parse_lib(line)
+            line.gsub!(Regexp.union(INLINE_COMMENT_REGEX, OTHER_SPECIFIERS_REGEX), '')
+            match = NAME_VERSION_REGEX.match(line)
+
+            Lib.new(name: match[:name], version: match[:version]) if match
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/ee/spec/lib/ai/context/dependencies/config_files/python_pip_spec.rb b/ee/spec/lib/ai/context/dependencies/config_files/python_pip_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f0209ab189d4cef20d5edff863e801d473187225
--- /dev/null
+++ b/ee/spec/lib/ai/context/dependencies/config_files/python_pip_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ai::Context::Dependencies::ConfigFiles::PythonPip, feature_category: :code_suggestions do
+  it 'returns the expected language value' do
+    expect(described_class.lang).to eq('python')
+  end
+
+  it_behaves_like 'parsing a valid dependency config file' do
+    let(:config_file_content) do
+      <<~CONTENT
+        requests>=2.0,<3.0      # Version range
+        numpy==1.26.4           # Exact version match
+        python_dateutil>=2.5.3
+        fastapi-health!=0.3.0
+
+        # New supported formats
+        pytest >= 2.6.4 ; python_version < '3.8'
+        openpyxl == 3.1.2
+        urllib3 @ https://github.com/path/main.zip
+        requests [security] >= 2.8.1, == 2.8.*
+
+        # Nested requirement files currently not supported
+        -r other_requirements.txt
+        # Other options
+        -i https://pypi.org/simple
+        --python-version 3
+        --no-clean
+        -e .
+      CONTENT
+    end
+
+    let(:expected_formatted_lib_names) do
+      [
+        'requests (>=2.0,<3.0)',
+        'numpy (==1.26.4)',
+        'python_dateutil (>=2.5.3)',
+        'fastapi-health (!=0.3.0)',
+        'pytest (>= 2.6.4)',
+        'openpyxl (== 3.1.2)',
+        'urllib3',
+        'requests [security] (>= 2.8.1, == 2.8.*)'
+      ]
+    end
+  end
+
+  it_behaves_like 'parsing an invalid dependency config file' do
+    let(:invalid_config_file_content) { '' }
+    let(:expected_parsing_error_message) { 'file empty' }
+  end
+
+  describe '.matches?' do
+    using RSpec::Parameterized::TableSyntax
+
+    where(:path, :matches) do
+      'requirements.txt'            | true
+      'dir/requirements.txt'        | true
+      'dir/subdir/requirements.txt' | true
+      'dir/requirements'            | false
+      'xrequirements.txt'           | false
+      'Requirements.txt'            | false
+      'requirements_txt'            | false
+      'requirements'                | false
+    end
+
+    with_them do
+      it 'matches the file name glob pattern at various directory levels' do
+        expect(described_class.matches?(path)).to eq(matches)
+      end
+    end
+  end
+end