diff --git a/.coveragerc b/.coveragerc
index 2e47573f9..f15474e24 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -11,6 +11,7 @@ show_missing = true
 [run]
 branch = true
 cover_pylib = false
+plugins = Cython.Coverage
 relative_files = true
 source =
   tests
diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml
index 544b21c8a..638148916 100644
--- a/.github/workflows/ci-cd.yml
+++ b/.github/workflows/ci-cd.yml
@@ -109,6 +109,15 @@ jobs:
       os: ${{ matrix.os }}
       source-tarball-name: ${{ needs.pre-setup.outputs.sdist-name }}
       dists-artifact-name: ${{ needs.pre-setup.outputs.dists-artifact-name }}
+      cython-tracing: >-  # Cython line tracing for coverage collection
+        ${{
+          (
+            github.event_name == 'push'
+            && contains(github.ref, 'refs/tags/')
+          )
+          && '0'
+          || '1'
+        }}
 
   test:
     name: Test
@@ -202,6 +211,34 @@ jobs:
       shell: bash
     - name: Self-install
       run: python -Im pip install '${{ steps.wheel-file.outputs.path }}'
+    - name: Produce the C-files for the Coverage.py Cython plugin
+      if: >-  # Only works if the dists were built with line tracing
+        !matrix.no-extensions
+        && (
+          github.event_name != 'push'
+          || !contains(github.ref, 'refs/tags/')
+        )
+      run: >
+        set -eEuo pipefail
+
+
+        python -Im cython
+        -X linetrace=true
+        -X embedsignature=true
+        -X emit_code_comments=true
+        yarl/*.pyx
+      shell: bash
+    - name: Disable the Cython.Coverage Produce plugin
+      if: >-  # Only works if the dists were built with line tracing
+        matrix.no-extensions
+        || (
+          github.event_name == 'push'
+          && contains(github.ref, 'refs/tags/')
+        )
+      run: |
+        set -eEuo pipefail
+        sed -i 's/^plugins = .*//g' .coveragerc
+      shell: bash
     - name: Run unittests
       env:
         YARL_NO_EXTENSIONS: ${{ matrix.no-extensions }}
diff --git a/.github/workflows/reusable-build-wheel.yml b/.github/workflows/reusable-build-wheel.yml
index 588790389..757529097 100644
--- a/.github/workflows/reusable-build-wheel.yml
+++ b/.github/workflows/reusable-build-wheel.yml
@@ -9,6 +9,11 @@ on:
         description: Workflow artifact name containing dists
         required: true
         type: string
+      cython-tracing:
+        description: Whether to build Cython modules with line tracing
+        default: '0'
+        required: false
+        type: string
       os:
         description: VM OS to use, without version suffix
         default: ubuntu
@@ -64,6 +69,9 @@ jobs:
       uses: pypa/cibuildwheel@v2.16.2
       env:
         CIBW_ARCHS_MACOS: x86_64 arm64 universal2
+        CIBW_ENVIRONMENT: >-  # Cython line tracing for coverage collection
+          PIP_CONSTRAINT="requirements/cython.txt"
+          YARL_CYTHON_TRACING="${{ inputs.cython-tracing }}"
 
     - name: Upload built artifacts for testing and publishing
       uses: actions/upload-artifact@v3
diff --git a/CHANGES/961.contrib.rst b/CHANGES/961.contrib.rst
new file mode 100644
index 000000000..baae3584d
--- /dev/null
+++ b/CHANGES/961.contrib.rst
@@ -0,0 +1,15 @@
+Coverage collection has been implemented for the Cython modules
+-- by :user:`webknjaz`.
+
+It will also be reported to Codecov from any non-release CI jobs.
+
+To measure coverage in a development environment, *yarl* can be
+installed in editable mode, which requires an environment variable
+``YARL_CYTHON_TRACING=1`` to be set:
+
+.. code-block:: console
+
+    $ YARL_CYTHON_TRACING=1 python -Im pip install -e .
+
+Editable install produces C-files required for the Cython coverage
+plugin to map the measurements back to the PYX-files.
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 1834d405c..23ea7a44a 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -1,10 +1,12 @@
 Bluesky
 Bugfixes
 Changelog
+Codecov
 Cython
 GPG
 IPv
 PRs
+PYX
 Towncrier
 Twitter
 UTF
diff --git a/requirements/test.txt b/requirements/test.txt
index bffbe96e4..2cadfd3fe 100644
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -1,3 +1,4 @@
+-r cython.txt
 idna==3.4
 multidict==6.0.4
 pytest==7.4.3