npm & PyPI Package Stats Scraper: Downloads & Trends avatar

npm & PyPI Package Stats Scraper: Downloads & Trends

Pricing

Pay per event

Go to Apify Store
npm & PyPI Package Stats Scraper: Downloads & Trends

npm & PyPI Package Stats Scraper: Downloads & Trends

Get metadata and download statistics for npm and PyPI packages: daily/weekly/monthly downloads, week-over-week growth, daily history, versions, release dates, license, repository and dependencies. Search npm by keyword or author and monitor download changes between runs.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Max Prozapas

Max Prozapas

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

npm & PyPI Package Stats — Downloads, Versions & Trends

Get download statistics and metadata for any npm or PyPI package in one clean dataset: daily, weekly and monthly downloads, week-over-week growth, optional daily download history, latest version, number of versions, first and latest release dates, days since the last release, license, homepage, GitHub repository, keywords, author, maintainers count and number of dependencies.

Paste package names or URLs (react, @apify/log, https://pypi.org/project/requests/), or discover npm packages by keyword, author or maintainer with npm search. Turn on monitor mode to see how downloads and versions changed since the previous run. No API key, no login, no browser.

Why this package stats scraper

  • npm and PyPI in one run: JavaScript/Node.js and Python packages side by side, with the same output fields.
  • Download numbers that matter: last day, last week, last month, previous week and week-over-week growth in %.
  • Daily download history (up to 365 days for npm, ~180 days for PyPI) for charts and trend analysis.
  • Release health: versions count, first release, latest release, days since last release, deprecated flag.
  • Discovery: npm search with keywords:, author: and maintainer: qualifiers, up to 1,000 packages.
  • Monitoring: change in weekly downloads and new releases since the last run. Filter out small changes.
  • Scoped packages (@scope/name), package URLs and version suffixes (react@18, requests==2.31) just work.
  • Official public sources: registry.npmjs.org, api.npmjs.org, pypi.org JSON API and pypistats.org.
  • Polite and robust: bulk requests (128 npm packages per call), low concurrency, retries with backoff on 429, respects the pypistats.org rate limit. One failing package never stops the run.

Use cases

  • Developer tool market research: size a market by the downloads of every library in a category (keywords:orm, keywords:testing, keywords:llm), find the leaders and the fastest-growing challengers.
  • Competitor tracking for open source and devtools companies: follow your SDK against competitors' SDKs every week, catch their new releases and adoption spikes.
  • VC, investor and dev-rel dashboards: feed weekly downloads and growth of portfolio or target projects into Google Sheets, Looker Studio, Notion or your data warehouse.
  • Dependency due diligence: before adopting a package, check whether it is maintained (days since release, versions, maintainers), deprecated, how popular it is and how many dependencies it pulls in.
  • AI agents and LLM tools: give an agent structured, fresh package data (via the Apify API or MCP) to answer "which library should I use?" or to enrich code-generation and research workflows.

Input

FieldDescription
registryDefault registry for bare names: npm (default) or pypi. URLs and npm: / pypi: prefixes override it, so one run can mix both.
packagesPackage names or URLs, e.g. react, @apify/log, https://www.npmjs.com/package/express, requests, https://pypi.org/project/numpy/, pypi:flask.
searchQuerynpm search text with optional qualifiers: keywords:scraper, author:sindresorhus, maintainer:apify. Found packages are added to packages. npm only.
maxSearchResultsMax packages taken from the search (default 50, up to 1,000).
includeHistoryAdd dailyDownloads (array of { date, downloads }).
historyDaysDays of history (default 30, max 365; PyPI keeps about 180 days).
monitorModeAdd changes since the previous run (weekly downloads, new release).
monitorIdSeparate saved state per watchlist (default default).
minChangePercentMonitor mode: output only packages whose weekly downloads changed by at least this % or that have a new release (default 0 = all).

Example input: compare frameworks across npm and PyPI

{
"registry": "npm",
"packages": ["react", "vue", "@apify/log", "pypi:requests", "pypi:numpy"],
"includeHistory": true,
"historyDays": 30
}

Example input: market map of an npm category

{
"searchQuery": "keywords:scraper",
"maxSearchResults": 200
}

Example input: weekly competitor watch

{
"registry": "pypi",
"packages": ["langchain", "llama-index", "haystack-ai", "dspy"],
"monitorMode": true,
"monitorId": "llm-frameworks",
"minChangePercent": 10
}

Output

One row per package. Real example output (PyPI, with includeHistory: true, historyDays: 7):

{
"registry": "pypi",
"name": "requests",
"url": "https://pypi.org/project/requests/",
"description": "Python HTTP for Humans.",
"latestVersion": "2.34.2",
"license": "Apache-2.0",
"homepage": null,
"repositoryUrl": "https://github.com/psf/requests",
"keywords": [],
"author": "Kenneth Reitz",
"maintainersCount": 3,
"organization": null,
"versionsCount": 160,
"firstReleaseAt": "2011-02-14T08:49:42.641Z",
"latestReleaseAt": "2026-05-14T19:25:26.443Z",
"daysSinceLastRelease": 152,
"dependenciesCount": 4,
"deprecated": null,
"requiresNode": null,
"requiresPython": ">=3.10",
"downloadsLastDay": 51084441,
"downloadsLastWeek": 310931263,
"downloadsLastMonth": 1202777296,
"downloadsPreviousWeek": 304164213,
"weeklyGrowthPercent": 2.2,
"downloadsPeriodEnd": "2026-10-13",
"downloadsSource": "pypistats.org",
"dailyDownloads": [
{ "date": "2026-10-07", "downloads": 49420957 },
{ "date": "2026-10-08", "downloads": 50831095 },
{ "date": "2026-10-09", "downloads": 48758092 },
{ "date": "2026-10-10", "downloads": 32720021 },
{ "date": "2026-10-11", "downloads": 32364605 },
{ "date": "2026-10-12", "downloads": 45752052 },
{ "date": "2026-10-13", "downloads": 51084441 }
],
"downloadsWarning": null,
"input": "pypi:requests",
"scrapedAt": "2026-10-14T10:31:08.523Z"
}

Real example output (npm, growth and history fields omitted for brevity):

{
"registry": "npm",
"name": "vue",
"url": "https://www.npmjs.com/package/vue",
"description": "The progressive JavaScript framework for building modern web UI.",
"latestVersion": "3.5.44",
"license": "MIT",
"homepage": "https://vuejs.org/",
"repositoryUrl": "https://github.com/vuejs/core",
"keywords": ["vue"],
"author": "Evan You",
"maintainersCount": 2,
"versionsCount": 597,
"firstReleaseAt": "2013-12-07T06:09:46.299Z",
"latestReleaseAt": "2026-10-13T07:45:32.806Z",
"daysSinceLastRelease": 1,
"dependenciesCount": 5,
"deprecated": null,
"organization": null,
"requiresNode": null,
"requiresPython": null,
"downloadsLastDay": 3372286,
"downloadsLastWeek": 17643787,
"downloadsLastMonth": 75864263,
"downloadsPeriodEnd": "2026-10-12",
"downloadsSource": "api.npmjs.org",
"input": "vue",
"scrapedAt": "2026-10-14T10:31:08.523Z"
}

Field notes:

  • weeklyGrowthPercent compares the last 7 days with the 7 days before (from daily data). downloadsPreviousWeek is the previous week's total.
  • dependenciesCount counts runtime dependencies of the latest version (npm dependencies; PyPI requires_dist without optional extras).
  • maintainersCount is a count only. No e-mail addresses are collected. author is a name only.
  • organization is the npm scope (@apify/log → apify) or the PyPI organization that owns the project.
  • deprecated holds npm's deprecation message (or the PyPI yank reason) of the latest version.
  • downloadsSource tells where the numbers come from: api.npmjs.org, pypistats.org, or npm search index (a fallback used when the npm downloads API is unavailable; it provides weekly and monthly totals only).
  • downloadsWarning explains missing numbers, e.g. a temporary outage of the downloads API.
  • Search results also have dependents and searchScore from npm search.

In monitor mode every row additionally has:

{
"firstSeenInMonitor": false,
"previousCheckedAt": "2026-10-14T10:19:15.237Z",
"previousLatestVersion": "2.5.4",
"newRelease": false,
"previousDownloadsLastWeek": 100000000,
"downloadsLastWeekChange": 115951378,
"downloadsLastWeekChangePercent": 116,
"previousDownloadsLastMonth": 802155590,
"downloadsLastMonthChange": 0,
"downloadsLastMonthChangePercent": 0
}

A per-package report (output or not, errors such as Package not found on npm, warnings) and the npm search totals are saved to the SUMMARY record of the run's key-value store.

How monitoring works

  • State is saved in the named key-value store package-stats-monitor under state-<monitorId>.
  • The first run for a package outputs it with firstSeenInMonitor: true and empty "previous" fields.
  • Later runs compare with the last reported values. Packages skipped by minChangePercent keep their old baseline, so slow but steady growth is reported once it adds up to the threshold.
  • A new latest version is always reported (newRelease: true), regardless of minChangePercent.
  • If the run's cost limit is reached, unreported packages are compared again in the next run.

Pricing

Pay per package: you pay a small fee for each package row in the dataset (event package). Packages that do not exist, cannot be parsed, or are skipped by minChangePercent in monitor mode are free. Set a maximum cost per run and the Actor stops cleanly when it is reached.

FAQ

Where does the data come from? From the official public APIs: the npm registry (registry.npmjs.org), npm download counts (api.npmjs.org), npm search, the PyPI JSON API (pypi.org/pypi/<name>/json) and pypistats.org (PyPI download counts from the public BigQuery dataset, without mirrors).

Why are npm and PyPI download numbers not directly comparable? They count different things. npm counts tarball downloads from the npm registry (including CI installs). PyPI numbers come from pypistats.org and exclude known mirrors. Use them to compare packages within the same ecosystem and to follow trends over time.

Can I get downloads for a specific date range? Turn on includeHistory and set historyDays (up to 365 for npm, about 180 for PyPI). You get one value per day in dailyDownloads and can aggregate it any way you need.

Does it work with scoped npm packages? Yes. @scope/name, https://www.npmjs.com/package/@scope/name and @scope/name@1.2.3 are all supported. Scoped packages are queried one by one (the npm downloads API does not support them in bulk), unscoped ones in bulk.

Can I search PyPI? PyPI has no public search API, so searchQuery works for npm only. For PyPI, pass package names or URLs.

Why is downloadsLastDay or weeklyGrowthPercent sometimes null? The npm downloads API occasionally has outages. The Actor then falls back to npm search totals (weekly and monthly) and explains the gap in downloadsWarning. Very new packages also have less than two weeks of data.

How fresh are the numbers? npm and pypistats.org publish download counts once per day, usually for the previous UTC day. downloadsPeriodEnd shows the last day included.

Limitations

  • Download counts are published daily by the registries, not in real time.
  • PyPI daily history is limited to what pypistats.org keeps (about 180 days).
  • pypistats.org allows about 60 requests per minute, so PyPI runs process about 25-30 packages per minute.
  • Private packages and private registries are not supported.

The Actor reads only public data from the official npm and PyPI APIs and pypistats.org, the same data shown on the package pages. It does not log in or bypass any protection, and it does not collect personal data such as e-mail addresses (maintainers are counted, authors are reported by name only, as published by the package owner). Package names, descriptions and other metadata belong to their authors. Make sure your use of the data complies with applicable laws and the terms of npm and PyPI.