Open almost any Python package security tool and you'll see download counts used as a health indicator. pip-audit and safety don't rank by them directly, but supply-chain scoring frameworks like Scorecard and Deps.dev use them as an input. Dependency dashboards frequently sort by them. And, in my experience, humans making dependency decisions use them heavily — the package with ten million downloads a month feels safer than the one with ten thousand. The problem is that PyPI download statistics are a far noisier signal than that mental model suggests. This is a look at what the numbers actually measure, how to read them for security purposes, and where they break.
What Gets Counted
PyPI does not publish real-time download counts on project pages anymore — they were removed in 2013 because they were considered unreliable and easy to game, a decision that has quietly aged very well. What does exist is the pypi public dataset in Google BigQuery, populated by Fastly's CDN logs. Every download from the main PyPI CDN produces a log entry with the project name, version, file type, Python version, operating system, installer, and a hashed client identifier. Ee Durbin and Dustin Ingram have discussed the dataset's structure in several PyCon talks and in the PyPI blog throughout 2023 and 2024.
The BigQuery table bigquery-public-data.pypi.file_downloads is therefore the source of truth for most PyPI download numbers you see in the wild. Tools like pypistats.org, libraries.io, and Ecosyste.ms (launched by Andrew Nesbitt in late 2023 and significantly updated through 2024) all query variants of this dataset.
What that means for anyone reading a download count:
The count is downloads, not installs, and not unique users. A CI system that installs requests ten thousand times in a day to build ten thousand containers shows up as ten thousand downloads. The count includes mirrors, automated scanners, and researcher scrapers. Rows are attributed by installer client, so pip, poetry, pdm, and uv all show up separately — a shift in ecosystem tooling can look like a change in package popularity even when nothing has actually shifted.
The Gaming Problem
Because CDN logs are the source, anyone with a credit card and a willingness to run pip install in a loop can inflate a package's download count. Academic researchers have documented this — a 2022 paper from researchers at NC State ("What Do Package Dependencies Tell Us About Semantic Versioning?" and related follow-ups) flagged implausible download ratios on some packages as evidence of artificial inflation.
Phylum's supply-chain reports through 2023 and 2024 have repeatedly noted malicious packages with suspiciously high download counts, where the attacker's goal was to make the package look more established before the real payload shipped. Checkmarx's research team tracked several campaigns in 2024 where new packages accumulated 10,000+ downloads in their first week from what looked like distributed but coordinated installer traffic.
Download count is therefore a trailing, gameable indicator, not a leading truthful one. A package with a million downloads is probably, but not certainly, widely used. A package with ten downloads is probably, but not certainly, obscure.
Reading the Numbers for Security
That said, download statistics are not useless for security — they're just not reliable on their own. Used carefully, a few signals emerge from the BigQuery data that are genuinely informative.
Sudden changes in download volume. A package whose weekly downloads go from 500 to 50,000 in a week without a corresponding GitHub star surge or discussion thread is worth looking at. Either it became a transitive dependency of something popular (investigate which), or something is inflating the count.
Ratio of CI-like downloads to human-like downloads. The installer user-agent and the python_version fields let you separate pip calls running on Linux containers from calls running on macOS developer laptops. A package whose downloads are 98% Linux-in-container and 2% human is probably being used in automated pipelines only, which is a different risk profile than a package that shows up on developer machines.
Version distribution. For a well-maintained package, a large share of recent downloads should cluster on recent versions. A package where the majority of downloads are for a two-year-old version is either extremely stable or has a dependency-pinning pattern that means its maintainers don't have much leverage to ship security updates. Either way, worth knowing.
Geographic distribution. CDN logs include approximate region information. A package with downloads concentrated in one region in a way inconsistent with its stated audience can be a weak signal of a targeted attack campaign. This is a noisier signal than the others.
The Mirror Problem
A significant fraction of PyPI traffic goes through mirrors — corporate internal mirrors, university mirrors, and public regional mirrors like tsinghua.edu.cn. Downloads through these mirrors do not show up in the Fastly logs and therefore do not show up in BigQuery. For a package with a large enterprise user base, the "real" download count can be 2-5x the visible BigQuery count.
This matters for two reasons. First, popular packages look less popular than they are — the gap between a package's download count and its actual footprint is large for business-critical dependencies. Second, a package that's popular inside enterprises but quiet on public statistics is invisible to researchers, tooling vendors, and security analysts who rely on the BigQuery numbers.
What Ecosyste.ms and OpenSSF Scorecard Add
Ecosyste.ms aggregates multiple registries' data and produces cross-ecosystem popularity signals. It's useful for comparing PyPI popularity to related packages on npm, crates.io, and so on — if a package is nominally popular on PyPI but has no comparable ecosystem presence elsewhere, that's interesting.
OpenSSF Scorecard (scorecard.dev, maintained by OpenSSF since 2020 and significantly updated through 2024) doesn't use download counts directly but does use them as an input to its "popular package" filter. The Criticality Score project, which feeds Scorecard, has been iterating on more robust popularity signals precisely because raw download counts are unreliable. The 2024 Criticality Score v2 weights signals like active contributors, release cadence, and transitive dependency count alongside raw downloads.
For a security team today, the right posture is: use download counts as one input, understand that they're gameable, and cross-reference against GitHub stars, active maintainer count, release history, and dependency graph centrality before treating a package as trusted.
How Safeguard Helps
Safeguard ingests PyPI download statistics alongside GitHub activity, maintainer history, and transitive dependency graphs to produce a composite popularity and health score for each package your projects depend on. When a package's download pattern shifts sharply — a sudden surge, a drop to zero, a change in installer mix — Safeguard flags it in your supply-chain timeline with context about whether the change correlates with a new release, a maintainer change, or an external event. This gives your engineers a realistic read on package health without asking them to interpret noisy raw numbers on pypistats.org.