Every pip install that has to build or download a package leaves something behind. On a Mac that has been doing Python work for a while — data science notebooks, a handful of virtual environments per project, the occasional pip install -r requirements.txt inside a Docker build tested locally — pip's cache can quietly grow into multiple gigabytes without ever showing up anywhere you would normally look. Here is what it actually stores and the right way to trim it.

Where the cache lives

On macOS, pip's cache directory defaults to ~/Library/Caches/pip. Older pip versions, and some Linux-influenced tooling, use ~/.cache/pip instead — if you have both, you have probably used more than one pip version or run pip inside a container that wrote to the Linux-style path via a bind mount. Check which one your current pip is using with:

pip cache dir

Inside, pip organises the cache into a wheel cache (compiled .whl files, ready to install without rebuilding) and an HTTP cache (raw responses from PyPI, including the index metadata pip needs to resolve versions). Both matter for install speed. Neither is required for correctness — pip can always re-fetch or rebuild.

Why it grows the way it does

Every package version you have ever installed, across every project and every virtual environment on the machine, adds an entry. Unlike a virtual environment, the cache is shared and content-addressed, so installing the same version of numpy in ten different venvs only stores it once. What makes the cache grow relentlessly is version churn: a data science project pinned to pandas==1.5.3 last year and pandas==2.2.0 today both get stored, forever, unless something clears them out.

Packages that ship compiled C extensions are the worst offenders by size — numpy, scipy, pillow, torch wheels can each be tens to hundreds of megabytes, and pip keeps every version you have ever pulled down.

pip cache purge versus pip cache remove

These two commands are often confused because they sound similar in intent.

pip cache purge

Deletes the entire cache — both the wheel cache and the HTTP cache — in one shot. Equivalent in spirit to npm's cache clean --force: the next install of anything starts from zero and re-downloads or rebuilds.

pip cache remove <package-name>

Deletes only cache entries matching a name pattern. pip cache remove numpy clears every cached wheel whose name matches numpy*, leaving everything else untouched. This is the better tool when you know exactly which package's cached wheel is stale or was built against the wrong Python version, and you don't want to lose the cache for anything else.

There is also a read-only command worth knowing:

pip cache list

Prints every cached wheel so you can see what is actually in there before deciding what to remove.

When a stale wheel actually causes problems

The classic failure looks like this: you upgraded your Python version (say from 3.11 to 3.12), and pip install for a package with native extensions suddenly fails or, worse, silently installs a wheel built for the old interpreter ABI. Wheels are tagged with the Python version and platform they were built for, so in principle pip should not reuse an incompatible one — but on machines with several Python installations (Homebrew Python, pyenv-managed versions, Xcode's system Python) and inconsistent PATH ordering, it is easy to end up in a confusing state where the wrong interpreter is picking up a cached wheel meant for another.

pip cache remove <package> for the specific package, followed by a fresh install, resolves this without wiping everything else you have cached.

How pip's cache coexists with uv, Poetry, and Pipenv

If you have adopted newer Python tooling, it is worth knowing that pip's cache is not the only one on the machine, and they mostly do not share storage:

Tool Cache location on macOS Shares with pip?
pip ~/Library/Caches/pip
uv ~/Library/Caches/uv No — separate store, though uv can read pip-compatible wheels during resolution
Poetry ~/Library/Caches/pypoetry (includes cache and virtualenvs) No
Pipenv Uses pip under the hood; typically still writes to pip's own cache directory Partially

The practical result: if you use uv or Poetry for most projects but occasionally fall back to plain pip install for a one-off script, you can end up maintaining two or three separate multi-gigabyte caches side by side, each unaware of the others. There is no harm in that beyond disk space — each tool's cache format is different enough that sharing wasn't a realistic design goal — but it does mean cleaning "the Python cache" on a Mac that uses several tools means checking several folders, not one.

A sensible cleanup routine

For a Mac with years of Python work on it:

  1. pip cache dir to confirm the active location, and du -sh that path to see the current size.
  2. pip cache list to skim what is actually cached, if the size surprises you.
  3. pip cache purge if you want a clean slate and don't mind slower installs for a while as things re-download.
  4. Repeat the size check for ~/Library/Caches/uv and ~/Library/Caches/pypoetry if you use those tools, since purging pip's cache does nothing for them.
  5. Remember that virtual environments themselves (the venv or .venv folders inside each project) are usually a bigger and more scattered consumer of space than any package manager's cache. A cache holds one copy per version; a venv holds a full copy per project.

Where VolumeLens fits in

Python's tooling has fragmented enough that "clear the cache" can mean four different folders depending on what you used to install a package. VolumeLens does not care which tool created a folder — it scans your whole disk and shows every directory sized to scale, so ~/Library/Caches/pip sitting next to ~/Library/Caches/uv and a dozen abandoned .venv folders becomes obvious at a glance rather than something you have to remember to check one command at a time. Try it the next time pip install complains about disk space before you have any idea why.