1,500 widely-used npm and PyPI packages, ranked by weekly downloads and enriched with registry metadata and known vulnerabilities from OSV.dev.
Checking whether a package is stale, deprecated, or has a known CVE means either paying for a dependency-scanning platform or writing your own glue code against three separate public APIs (npm registry, PyPI JSON API, OSV.dev). This dataset does that glue work once a day for 1,500 packages that people actually depend on, and commits the result as plain JSON/CSV.
weeklyDownloads from npm's own download API. PyPI has no public download-count API at all, so its 500 packages come from a curated/keyword-search approach without a download-based ranking signal. Treat this as a documented approximation of widely-used packages, not a definitive top-1000/top-500 list.
riskFlags are five independent mechanical checks; weighting a CVE against staleness against maintainer count is a judgment call this dataset deliberately does not make.latestVersion.weeklyDownloads and maintainerCount are always null for PyPI — its public JSON API exposes neither.deprecated means different things per ecosystem: npm's own deprecation flag vs. PyPI's release-level "yanked" status.| Field | Type | Notes |
|---|---|---|
ecosystem | string | npm or pypi |
name | string | Package name |
found | boolean | false if the registry lookup failed at fetch time |
latestVersion | string | null | Latest published version |
description | string | null | Short description from the registry |
license | string | null | Free-text license string, not normalized to SPDX |
repositoryUrl | string | null | Source repository, when published |
weeklyDownloads | number | null | npm only; always null for PyPI |
publishedAt | string | null | ISO timestamp of the latest release |
deprecated | boolean | null | npm deprecation flag / PyPI yanked status |
deprecationReason | string | null | Verbatim message when deprecated is true |
vulnerabilityCount | number | null | Known OSV.dev vulnerabilities; null if lookup failed |
vulnerabilities | array | { id, severity } OSV/GHSA/CVE id and severity |
riskFlags | array of strings | stale, deprecated, has-known-vulns, no-repository, single-maintainer |
maintainerCount | number | null | npm only; always null for PyPI |
scrapedAt | string | ISO timestamp of this fetch |
{
"ecosystem": "npm",
"name": "minimatch",
"found": true,
"latestVersion": "10.2.6",
"description": "a glob matcher in javascript",
"license": "BlueOak-1.0.0",
"repositoryUrl": "ssh://git@github.com/isaacs/minimatch",
"weeklyDownloads": 696143360,
"publishedAt": "2026-07-27T19:00:09.469Z",
"deprecated": false,
"deprecationReason": null,
"vulnerabilityCount": 5,
"vulnerabilities": [
{ "id": "GHSA-23c5-xmqv-rm74", "severity": "HIGH" },
{ "id": "GHSA-3ppc-4f35-3m26", "severity": "HIGH" },
{ "id": "GHSA-7r86-cg39-jmmj", "severity": "HIGH" },
{ "id": "GHSA-f8q6-p94x-37v3", "severity": "HIGH" },
{ "id": "GHSA-hxm2-r34f-qmc5", "severity": "HIGH" }
],
"riskFlags": ["has-known-vulns", "single-maintainer"],
"scrapedAt": "2026-08-06T09:36:33.418Z",
"maintainerCount": 1
}
curl -s https://raw.githubusercontent.com/ConorsCode/open-dependency-risk/main/data/packages.json | jq '.[] | select(.riskFlags | contains(["has-known-vulns"]))' | head -50
import pandas as pd
df = pd.read_json("https://raw.githubusercontent.com/ConorsCode/open-dependency-risk/main/data/packages.json")
df[df["vulnerabilityCount"] > 0].sort_values("weeklyDownloads", ascending=False).head(20)
const pkgs = await fetch("https://raw.githubusercontent.com/ConorsCode/open-dependency-risk/main/data/packages.json").then(r => r.json());
console.log(pkgs.filter(p => p.riskFlags.includes("has-known-vulns")).length, "packages with known vulns");
package.json/requirements.txt, instead of a fixed 1,500-package list refreshed once a day? Package Intel Scraper on Apify (paid, pay-per-result) queries the same registries and OSV.dev live.