Sometimes the newest version of a package is exactly what you do not want. A tutorial was written against an older release, your project depends on behaviour that changed, or a new version has a bug you need to avoid. pip makes it easy to install a precise older version once you know the syntax. This guide shows you how to pin an exact version, how to discover which versions exist, and how to make the choice permanent with a requirements file so your project stays reproducible.
Quick Answer
Install an exact version with the double-equals operator: pip install package-name==1.2.3, for example pip install requests==2.28.1. To see which versions are available, run pip index versions package-name or check the release history on the package’s PyPI page. Do the work inside a virtual environment, and record the pin in requirements.txt so the setup can be recreated later.
The Version Specifier Syntax
The text after the package name is called a version specifier, and pip understands several forms:
package==1.2.3— exactly this version, nothing else. This is the true “pin”.package<2.0— the newest version below 2.0. Handy when a major release broke compatibility.package>=1.5,<2.0— a range, combining conditions with a comma.package~=1.4.2— compatible release: at least 1.4.2 but below 1.5. It allows patch updates while blocking feature changes.package!=1.9.0— any version except this one, useful for dodging a single bad release.
On Windows PowerShell, quote the whole argument when it contains characters like < or >, for example pip install "requests<3", because the shell may otherwise interpret them as redirection. The official pip install documentation lists every specifier form with examples.
How to Find Which Versions Exist
- Ask pip directly: run
pip index versions requests. pip prints the available versions and marks the one currently installed, if any. This command is labelled experimental but works reliably. - Deliberately request an impossible version: the older trick
pip install "requests=="produces an error message listing every version pip can see. It is ugly but effective on older pip releases. - Browse PyPI: open the package page on pypi.org and click Release history. You will see every version with its release date, which helps you match the era of a tutorial or a project’s documentation.
- Check the installed version: before changing anything, run
pip show requestsso you know what you are moving away from and can return if needed.
Installing the Older Version Safely
- Activate your virtual environment. Downgrading a package globally can break other projects. Inside a project environment, the change affects only that project. If environments are new to you, our guide on creating a Python virtual environment on Windows 11 covers the setup.
- Install with the pin:
pip install requests==2.28.1. pip will uninstall the current version and install the requested one, along with compatible versions of its dependencies. - Verify: run
pip show requestsagain and confirm the version line matches your pin. Then run your project and its tests if it has any. - Record it: add the pinned line to
requirements.txt, either by typing it yourself or withpip freeze > requirements.txt, which captures exact versions of everything installed.
When pip Refuses the Older Version
Sometimes the install fails even though the version exists. The usual reason is your Python version: very old package releases may not offer prebuilt wheels for Python 3.12, and pip then falls back to building from source, which can fail without compilers installed. Another reason is a dependency conflict, where another installed package demands a newer release of the same library; pip prints a clear resolver message naming both sides. In that case, install the conflicting packages together in one command so pip can plan around both pins. If you see the specific message about no matching version at all, our guide to pip’s “could not find a version” error explains each of its causes.
Common Mistakes to Avoid
- Using a single equals sign.
package=1.2.3is not valid pip syntax. Version pins need the double equals==. - Downgrading in the global Python. Other projects and tools may depend on the newer release. Always pin inside a virtual environment.
- Forgetting to update requirements.txt. A pin that lives only in your terminal history vanishes the moment anyone rebuilds the environment.
- Pinning without asking why. Old versions stop receiving security fixes. Note the reason for the pin, and re-test against newer releases from time to time.
Understanding pip’s Resolver When Pins Collide
Modern pip checks your whole environment for consistency, so a downgrade can trigger a negotiation you did not expect. If another installed package declares it needs the newer version of the one you are pinning down, pip prints a ResolutionImpossible report listing the conflicting requirements. Read it literally: it names the package that demands the higher version and the pin you requested. Your options are to install a compatible older version of the demanding package as well, to pin both together in a single command so pip can solve them jointly, or to accept the newer library and adapt your code.
For projects with several interlocking pins, a constraints file helps: it looks like a requirements file but only limits versions of packages that get installed for other reasons, without installing anything itself. Teams use constraints to hold a known-good combination steady across many machines. Whichever mechanism you use, the discipline is the same as the rest of this guide: make version choices explicit, write them into a file in the project, and let pip’s resolver verify the whole set at once instead of discovering conflicts one runtime error at a time.
Conclusion
Installing an older package version is one command: pip install package==x.y.z. Find the right version with pip index versions or the PyPI release history, do it inside a virtual environment, verify with pip show, and freeze the pin into requirements.txt. That turns a quick downgrade into a reproducible project setup.
Frequently Asked Questions
How do I upgrade back to the latest version later?
Run pip install --upgrade package-name, or simply install without the pin and pip will choose the newest compatible release. Remember to update requirements.txt afterwards with pip freeze, or the next environment rebuild will restore the old pin.
Can I install two versions of the same package at once?
Not in the same environment. One environment holds exactly one version of each package. If two projects need different versions, give each project its own virtual environment, which is precisely the problem virtual environments were designed to solve.
What does the version number format mean?
Most Python packages follow a three-part scheme: major, minor, and patch. A major change may break compatibility, minor versions add features, and patches fix bugs. That is why pinning below the next major version, such as package<3, is a popular compromise between stability and updates.
Why does pip try to build the old package from source?
Because no prebuilt wheel exists for your Python version and operating system combination. Old releases predate newer Pythons, so pip falls back to the source distribution. On Windows this often fails without build tools; choosing a slightly newer release with published wheels is usually the practical answer.
How do I uninstall the pinned version and start fresh?
Run pip uninstall package-name inside the environment; pip removes that version cleanly. Then install whichever release you actually want, with or without a pin. If an environment has accumulated layers of experiments and uninstalls, the cleanest reset of all is to delete the environment folder, recreate it, and install once from your requirements file — one deliberate combination instead of the archaeology of everything you tried along the way.
How do I pin versions for a whole project at once?
List every package with its pin in requirements.txt, one per line, then install everything with pip install -r requirements.txt. pip resolves the entire set together, which also surfaces conflicts between pins early instead of one package at a time.


Leave a Reply