diff --git a/reqs_checker.py b/reqs_checker.py
new file mode 100644
index 0000000000000000000000000000000000000000..2abd5a48f859593ed4def8cf896737a29b006b7d
--- /dev/null
+++ b/reqs_checker.py
@@ -0,0 +1,52 @@
+import re
+
+
+def read_requirements_txt(file_path):
+    with open(file_path, 'r') as file:
+        lines = file.readlines()
+
+    def _dev_req_index():
+        return next((i for i, line in enumerate(lines) if "# dev requirements" in line), len(lines))
+
+    dev_req_index = _dev_req_index()
+    assert dev_req_index != len(lines), f"Missing # dev requirements section in {file_path}"
+
+    return [line.strip() for line in lines[:_dev_req_index()] if line.strip() and not line.startswith('#')]
+
+
+def read_requirements_setup(file_path):
+    with open(file_path, 'r') as file:
+        content = file.read()
+
+    # Find and extract the install_requires section
+    matches = re.findall(r'install_requires=\[(.*?)\]', content, re.DOTALL)
+    if matches:
+        return re.findall(r'"([^"]+)"', matches[0])
+
+    return []
+
+
+def compare_requirements(reqs, setup_reqs):
+    missing_in_setup = set(reqs) - set(setup_reqs)
+    missing_in_requirements = set(setup_reqs) - set(reqs)
+
+    return missing_in_setup, missing_in_requirements
+
+
+def main():
+    reqs = read_requirements_txt('requirements.txt')
+    setup_reqs = read_requirements_setup('setup.py')
+
+    missing_in_setup, missing_in_requirements = compare_requirements(reqs, setup_reqs)
+
+    if not missing_in_setup and not missing_in_requirements:
+        print("Requirements are synchronized.")
+    else:
+        if missing_in_setup:
+            print("Missing or different in setup.py:", ', '.join(missing_in_setup))
+        if missing_in_requirements:
+            print("Missing or different in requirements.txt:", ', '.join(missing_in_requirements))
+
+
+if __name__ == "__main__":
+    main()
diff --git a/requirements.txt b/requirements.txt
index ce50fc8a1259acf7d6bc9ddfc4f05c4b2fc26d3f..555629c57a3ffb4f28efcec53893d285ba88dd37 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,29 +1,30 @@
 jsonschema~=4.20.0
 fastapi~=0.104.1
-pydantic~=2.0.3
-ansible-runner==2.3.4
-uvicorn[standard]~=0.22.0
-httpx~=0.25.1
-
+pydantic~=2.5.1
+ansible~=9.0.1
+requests~=2.31.0
+uvicorn~=0.22.0
+ncclient~=0.6.13
+xmltodict~=0.13.0
+netaddr~=0.9.0
+jmespath~=1.0.0
+dictdiffer~=0.9.0
+ansible-runner~=2.3.3
+junos-eznc~=2.6.8
+jxmlease~=1.0.3
 ansible-core~=2.16.0
 ansible_merge_vars~=5.0.0
+httpx~=0.25.1
 GitPython~=3.1.40
 jinja2==3.1.2
-junos-eznc~=2.6.8
-jxmlease~=1.0.3
-ncclient~=0.6.13
 ruamel.yaml~=0.18.5
-xmltodict~=0.13.0
-dictdiffer~=0.9.0
-jmespath~=1.0.1
 
 # dev requirements
 pytest~=7.4.3
-Faker~=20.0.3
+Faker~=20.1.0
 responses~=0.24.1
 sphinx~=7.2.6
 sphinx-rtd-theme~=1.3.0
-requests~=2.31.0
 docutils~=0.18.1
 isort~=5.12.0
 black~=23.11.0
diff --git a/setup.py b/setup.py
index 24315c22f4fc64bd2ade4886cdffe2f61f5f8910..4d4fa260cae1cceaed6220de2e6119ea51e504e1 100644
--- a/setup.py
+++ b/setup.py
@@ -9,21 +9,21 @@ setup(
     url="https://gitlab.geant.org/goat/gap/lso",
     packages=find_packages(),
     install_requires=[
-        "jsonschema~=4.18.0",
-        "fastapi~=0.100.0",
-        "pydantic~=2.0.2",
-        "ansible~=8.1.0",
+        "jsonschema~=4.20.0",
+        "fastapi~=0.104.1",
+        "pydantic~=2.5.1",
+        "ansible~=9.0.1",
         "requests~=2.31.0",
         "uvicorn~=0.22.0",
         "ncclient~=0.6.13",
         "xmltodict~=0.13.0",
-        "netaddr~=0.8.0",
+        "netaddr~=0.9.0",
         "jmespath~=1.0.0",
         "dictdiffer~=0.9.0",
         "ansible-runner~=2.3.3",
         "junos-eznc~=2.6.8",
         "jxmlease~=1.0.3",
-        "ansible-core~=2.15.1",
+        "ansible-core~=2.16.0",
         "ansible_merge_vars~=5.0.0",
         "httpx~=0.25.1",
         "GitPython~=3.1.40",
diff --git a/tox.ini b/tox.ini
index 927b8974a48b33a3031b4b28dce6c342837cf1eb..7b8473166840d896e4e96b910b2f938dfb43a815 100644
--- a/tox.ini
+++ b/tox.ini
@@ -31,3 +31,4 @@ commands =
     coverage xml
     coverage html
     coverage report --fail-under 80
+    python reqs_checker.py
\ No newline at end of file