npm & PyPI Package Stats Scraper: Downloads & Trends
Pricing
Pay per event
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
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:andmaintainer: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
| Field | Description |
|---|---|
registry | Default registry for bare names: npm (default) or pypi. URLs and npm: / pypi: prefixes override it, so one run can mix both. |
packages | Package names or URLs, e.g. react, @apify/log, https://www.npmjs.com/package/express, requests, https://pypi.org/project/numpy/, pypi:flask. |
searchQuery | npm search text with optional qualifiers: keywords:scraper, author:sindresorhus, maintainer:apify. Found packages are added to packages. npm only. |
maxSearchResults | Max packages taken from the search (default 50, up to 1,000). |
includeHistory | Add dailyDownloads (array of { date, downloads }). |
historyDays | Days of history (default 30, max 365; PyPI keeps about 180 days). |
monitorMode | Add changes since the previous run (weekly downloads, new release). |
monitorId | Separate saved state per watchlist (default default). |
minChangePercent | Monitor 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:
weeklyGrowthPercentcompares the last 7 days with the 7 days before (from daily data).downloadsPreviousWeekis the previous week's total.dependenciesCountcounts runtime dependencies of the latest version (npmdependencies; PyPIrequires_distwithout optional extras).maintainersCountis a count only. No e-mail addresses are collected.authoris a name only.organizationis the npm scope (@apify/log→apify) or the PyPI organization that owns the project.deprecatedholds npm's deprecation message (or the PyPI yank reason) of the latest version.downloadsSourcetells where the numbers come from:api.npmjs.org,pypistats.org, ornpm search index(a fallback used when the npm downloads API is unavailable; it provides weekly and monthly totals only).downloadsWarningexplains missing numbers, e.g. a temporary outage of the downloads API.- Search results also have
dependentsandsearchScorefrom 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-monitorunderstate-<monitorId>. - The first run for a package outputs it with
firstSeenInMonitor: trueand empty "previous" fields. - Later runs compare with the last reported values. Packages skipped by
minChangePercentkeep 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 ofminChangePercent. - 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.
Legal
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.