Convert requirements.txt to pyproject.toml
Convert a requirements.txt (or requirements.in) into a pyproject.toml — runtime and dev dependency groups, with extras, version pins and environment markers preserved. Runs in your browser.
Why use this tool?
Use this converter when you're moving a project from a requirements.txt (or a pip-tools requirements.in) to a modern pyproject.toml — the layout uv, Hatch and pip all read. Paste your runtime requirements (and dev requirements separately), fill in the project name/version/requires-python, and get a pyproject.toml with your dependencies under [project] and your dev tools under [dependency-groups].dev. Extras, version specifiers and environment markers are carried over verbatim, and anything that can't be represented as a dependency — hashes, index URLs, constraints, editable installs — is reported rather than silently dropped.
Paste a requirements.txt (or a requirements.in). A pip freeze file works too, but it lists transitive packages as well — review which ones actually belong in your project's dependencies.
uv lock locally to resolve and verify.Line-by-line mapping (6)
| line | source | result |
|---|---|---|
| 1 | requests>=2.31,<3 | requests>=2.31,<3 |
| 2 | flask[async]==3.0.1 | flask[async]==3.0.1 |
| 3 | numpy>=1.26 ; python_version >= "3.10" | numpy>=1.26 ; python_version >= "3.10" |
| 4 | click~=8.1 | click~=8.1 |
| 1 | pytest>=8 | pytest>=8 |
| 2 | ruff | ruff |
The file above is an offline syntax conversion. To actually resolve and lock versions, download it and run uv locally — this is where dependency resolution happens (this tool doesn't resolve or contact PyPI):
# after saving pyproject.toml in your project: uv lock # resolve + pin all versions into uv.lock uv sync # create the environment
Or skip this converter and let uv build the project from scratch — uv resolves versions and may add its own bounds, so the result can differ from the offline conversion above:
uv init --bare uv add "click~=8.1" "flask[async]==3.0.1" "numpy>=1.26 ; python_version >= "3.10"" "requests>=2.31,<3" uv add --dev "pytest>=8" "ruff"
Runs entirely in your browser. It converts requirement declarations and reports the installation instructions it can't carry over (hashes, index URLs, constraints, editable installs) — an output can be valid TOML yet not reproduce your original install, so review the unresolved items before shipping.
Tool facts
- Supported Python
- PEP 621 [project] · PEP 735 dependency-groups · uv-style output
- Input limit
- Limited only by your device
- Last reviewed
- 2026-09-05
What it can't do
- •Resolve or pin versions — it converts syntax only; run 'uv lock' locally to resolve and verify.
- •Contact PyPI or check that a package (or a wheel for your Python/OS) actually exists.
- •Follow -r / -c file includes — paste each referenced file's contents into the matching input.
- •Auto-migrate editable installs (-e) or turn a pip freeze into a curated dependency list — those need manual review.
About requirements.txt → pyproject.toml Converter
A pyproject.toml declares your project's dependencies in a standard, tool-agnostic way: runtime dependencies go in [project].dependencies (PEP 621), and development dependencies go in [dependency-groups] (PEP 735) — standardized dev groups that are excluded from your built package's metadata. This tool maps a requirements.txt onto that structure: each requirement line becomes a PEP 508 dependency string, and a separate dev input becomes the dev group.
It preserves meaning before formatting. Version pins, extras (like flask[async]) and environment markers (like ; python_version >= "3.10") are kept exactly — markers are not rewritten (python_version and python_full_version are different variables), and entries are never de-duplicated by name, because two lines for the same package can carry different markers for different Python versions or platforms. Sorting the output is a presentation choice, not a correctness one.
Crucially, a requirements file is a mix of dependency declarations and installation instructions, and a converted file can be valid TOML yet not reproduce the original install. So the tool separates four things: TOML validity, dependency-syntax validity, conversion completeness, and dependency resolution. It does the first three; it does not resolve versions or contact PyPI. Dropped --hash verification, --index-url configuration, and skipped -c constraints are flagged prominently as an 'unresolved items' list, and the output is labelled Incomplete until you review them. To actually resolve and pin, download the file and run uv lock locally.
Related: package your project with the Python-to-EXE builder, or format and lint it with the Ruff tool and type checker.
Supported requirements syntax
What the converter recognises and how each line is handled. Declarations become dependencies; installation instructions are reported as unresolved items.
name, version specifiers, extras
requests>=2.31,<3 and flask[async]==3.0.1 convert directly, kept verbatim.
environment markers
numpy>=1.26 ; python_version >= "3.10" is preserved exactly (never rewritten to python_full_version).
direct URL references
pkg @ https://host/pkg-1.0-py3-none-any.whl is kept, including any #fragment (URL fragments are not mistaken for comments).
dev requirements
the separate dev input becomes [dependency-groups].dev (PEP 735).
line continuations & comments
backslash continuations are joined first (like pip), then inline comments are stripped — a '#' inside a URL is left intact.
--hash=…
removed from the dependency and reported: pyproject dependencies don't carry hashes, so pinned-artifact verification is no longer enforced (use uv lock).
--index-url / --extra-index-url / -f
reported, not converted — these change where packages come from and belong in uv/pip config, not pyproject.
-c constraints
reported as incomplete — constraints restrict versions without adding dependencies and can't become [project] dependencies.
-r includes
reported — the nested file isn't loaded; paste its contents into the matching input.
-e editable / -e .
reported for manual migration; -e . is your own project, not a dependency, so it is never converted into a self-dependency.
Frequently Asked Questions
Explore Other Tools
AST Python Obfuscator
Free online Python obfuscator: rename identifiers, encrypt strings, hide imports and flatten control flow at the AST level, then download standalone Python.
Python Script Formatter
Format Python to PEP 8 instantly with Black, autopep8, YAPF or isort — with a before/after diff view and Black options (keep quotes, no magic comma).
Online Python Compiler
Run Python 3.14, 3.13, 3.12 or 3.11 directly in your browser — pick a version, pip-install packages, and execute instantly.
Python Script Minifier
Minify Python with python-minifier: strip comments, rename variables, and optionally remove docstrings, annotations and asserts, hoist literals and combine imports — with per-option toggles and a live size readout.