diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 59941811eea69e38a085c13fb6f364e52d9ac905..c8546299745fe5571bcebd2c670fc31c4a947091 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -5,6 +5,7 @@ variables:
 stages:
   - docker
   - install
+  - lint
   - test
 
 docker:
@@ -48,6 +49,25 @@ install:
   rules:
     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $COMPILE_DOCKER == null
 
+pep8:
+  stage: lint
+  image: registry.git.laquadrature.net/la-quadrature-du-net/raaspotter/base:latest
+  needs: [install]
+  tags:
+    - unprivileged
+  cache:
+    key: $CI_COMMIT_REF_SLUG
+    paths:
+    - bin/
+    - lib/
+    - pyvenv.cfg
+  script:
+    - source bin/activate
+    - pycodestyle --first --show-source *.py
+  allow_failure: true
+  rules:
+    - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "push"
+
 .default_pref:
   stage: test
   image: registry.git.laquadrature.net/la-quadrature-du-net/raaspotter/base:latest
diff --git a/requirements.txt b/requirements.txt
index 4da0c3692b58d326823e03817f50158290ffcd69..4780587264f61534b78ed7ee43f7e7b76e51c532 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,6 +2,7 @@ beautifulsoup4>=4.12.3
 dateparser>=1.2.0
 Mastodon.py>=1.8.1
 pdfminer.six>=20231228
+pycodestyle>=2.2.0
 PyVirtualDisplay>=3.0
 requests>=2.31.0
 selenium>=4.18.1