/flags/pip/pip-install-constraint
pip install -c constraints.txt: limit versions without installing them
- tool
- pip
- command
- pip install, pip download, pip wheel
- flag
- -c, --constraint FILE
- default
- none
pip install -c constraints.txt -r requirements.txt installs what requirements.txt asks for, but every package that ends up being installed, including transitive dependencies, must also satisfy the version limits in constraints.txt. A constraint never causes a package to be installed by itself. Use it to hold back one problematic dependency (urllib3<2), to share one set of tested versions across many projects, or to reproduce a known-good environment without turning every dependency into a direct requirement.
A constraint on a transitive dependency
requests allows urllib3 1.21 up to 2.x; the constraint keeps it on the 1.26 series:
echo "requests==2.32.3" > requirements.txt
echo "urllib3<2" > constraints.txt
echo "--- without -c"
pip download --disable-pip-version-check -q -d a -r requirements.txt
ls a | grep -o "^urllib3-[0-9]*"
echo "--- with -c constraints.txt"
pip download --disable-pip-version-check -q -d b -r requirements.txt -c constraints.txt
ls b | grep -o "^urllib3-[0-9]*"
echo "--- a constraint alone installs nothing"
pip download --disable-pip-version-check -q -d c -c constraints.txt six==1.16.0
ls cOutput
--- without -c urllib3-2 --- with -c constraints.txt urllib3-1 --- a constraint alone installs nothing six-1.16.0-py2.py3-none-any.whl
The project never mentions urllib3, yet the constraint changes which major version is downloaded. In the last call urllib3 is not fetched at all, because nothing requires it. pip download resolves exactly like pip install, without changing the environment.
Requirements versus constraints
| Aspect | requirements.txt (-r) | constraints.txt (-c) |
|---|---|---|
| Causes installation | Yes | No |
| Applies to transitive dependencies | Only if they are listed | Yes, always |
| Allowed entries | Names, versions, URLs, editables, extras | Names with version specifiers only (no extras, no -e) |
| Typical content | What the project needs | Versions the organisation tested |
| Environment variable | - | PIP_CONSTRAINT |
Shared constraints for many projects
A common pattern is one constraints file per platform or release train, generated from a tested environment with pip freeze:
pip freeze > constraints-2026-10.txt
pip install -c constraints-2026-10.txt -r requirements.txtEach project keeps its short requirements.txt, and all of them resolve to the same versions wherever they overlap.
Pitfalls
- A constraint that no release satisfies makes the install fail with No matching distribution found or a
ResolutionImpossibleconflict report; read the "The conflict is caused by" lines. - The resolver introduced in pip 20.3 rejects extras in constraints files (
pkg[extra]==1.0); write the bare name. - Constraints do not check integrity. Combine pinned requirements with --require-hashes for that.
uv pip installaccepts the same-coption and file format, and adds--overridefor forcing a version a package does not allow.
FAQ
What is the difference between requirements.txt and constraints.txt?
A requirements file says what to install. A constraints file only says which versions are allowed if a package gets installed; listing a package there never causes it to be installed.
Can I set a constraints file for every pip command?
Yes. Set PIP_CONSTRAINT=/path/constraints.txt in the environment, or constraint = /path/constraints.txt in pip.conf.
What happens when a constraint conflicts with a requirement?
The resolver fails with ResolutionImpossible and explains which requirement and which constraint cannot both be satisfied. Constraints are never silently ignored.