npm Download Trends & Package Comparison
Pricing
from $1.40 / 1,000 package analyseds
npm Download Trends & Package Comparison
Compare npm package downloads (daily, weekly or monthly) for any list of packages: growth %, week-over-week and month-over-month change, a 0-100 index, market share, version adoption and outage-gap correction. Public npm downloads API only. Independent tool, not affiliated with npm, Inc. or GitHub.
Pricing
from $1.40 / 1,000 package analyseds
Rating
0.0
(0)
Developer
Doyle Pounders
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
11 hours ago
Last modified
Categories
Share
Package Download Trends & Comparison
Independent tool. Not affiliated with, sponsored or endorsed by npm, Inc. or GitHub. npm is a registered trademark of npm, Inc.
Current as of 2026-10-26. Behaviour, limits and data-source rules were checked against the sources linked below on that date.
Compare download counts for any list of packages in the npm public registry. You get growth % (week over week, month over month, second half vs first half), a 0–100 comparison index, market share, rank, momentum labels, version adoption and clean daily / weekly / monthly series. Everything comes from npm's official public downloads API (docs). No login, no proxies, no scraping of npmjs.com pages.
Why use it instead of calling the API yourself?
- Outage-gap correction: npm's downloads API reports 0 downloads for every package on some days (processing outages). The run below found 13 such days in 120 days, e.g. 2026-10-13…15 and 2026-10-19…21. Raw sums and week-over-week numbers built on them are wrong. This Actor detects those days and interpolates them by default (marked
estimated). It can also exclude them or keep the raw zeros. - No fake zeros at the end: npm returns
0(not an error) for days it hasn't published yet. Each run checks the last published day first and never goes past it (dataAvailableThrough). - Bulk-aware and polite: up to 128 unscoped packages per request, automatic chunking past npm's 365-day/18-month limits (npm download-counts docs), scoped packages one by one, and at most 1 request per second as npm's crawler policy asks.
Real run (2026-10-26, about 9:55 PM America/Chicago = 2026-10-27 02:55 UTC)
Input (demo/INPUT.json):
{"packages": ["react","vue","svelte","@angular/core","solid-js","preact","htmx.org","https://www.npmjs.com/package/@sveltejs/kit","this-package-does-not-exist-zz9q","Not A Valid Name"],"lookbackDays": 120,"granularity": "weekly","gapHandling": "interpolate","includeSeries": true,"includeVersions": true,"includeMetadata": true}
Result: 8 ok packages, 1 not_found and 1 invalid_name. It made 20 API requests in 19.2 s (Actor time). Data ran through 2026-10-25.
| Rank | Package | Downloads (gap-corrected) | Index 0–100 | Share % | 30 d vs prev 30 d % | Momentum |
|---|---|---|---|---|---|---|
| 1 | react | 3,127,868,076 | 100 | 72.06 | 16.08 | growing |
| 2 | preact | 579,777,786 | 18.5 | 13.36 | 23.42 | growing |
| 3 | vue | 280,931,057 | 9 | 6.47 | 16.34 | growing |
| 4 | @angular/core | 107,772,792 | 3.4 | 2.48 | 4.97 | stable |
| 5 | svelte | 105,568,572 | 3.4 | 2.43 | 23.74 | growing |
| 6 | solid-js | 85,915,463 | 2.7 | 1.98 | 70.82 | surging |
| 7 | @sveltejs/kit | 48,710,485 | 1.6 | 1.12 | 28.61 | surging |
| 8 | htmx.org | 4,389,454 | 0.1 | 0.1 | 16.1 | growing |
The run also writes SERIES.csv to the key-value store: one column per package, ready for Google Sheets or Excel charts.
Output
One row per input. This is the solid-js row from the run above, unedited except that series, suspectedGapDays and the version lists are trimmed ("..."):
{"input": "solid-js","package": "solid-js","packageUrl": "https://www.npmjs.com/package/solid-js","startDate": "2026-06-28","endDate": "2026-10-25","granularity": "weekly","gapHandling": "interpolate","status": "ok","days": 120,"totalDownloads": 85915463,"avgDailyDownloads": 715962.2,"medianDailyDownloads": 611085,"peakDownloads": 1816203,"peakDate": "2026-10-22","minDownloads": 191119,"minDate": "2026-07-04","firstDayDownloads": 224820,"lastDayDownloads": 910328,"trendChangePct": 99.68,"last7Downloads": 9197325,"prev7Downloads": 9227182,"weekOverWeekPct": -0.32,"last30Downloads": 36107837,"prev30Downloads": 21138438,"monthOverMonthPct": 70.82,"slopePctPer30d": 34.64,"weekendToWeekdayRatio": 0.517,"zeroDays": 0,"rawTotalDownloads": 72341363,"momentum": "surging","suspectedGapDays": ["2026-07-12","2026-08-14","2026-09-03","..."],"peakFollowsGap": true,"versions": {"window": "npm \"last-week\" per-version preset (npm does not return its dates; it can lag the daily data)","versionsTotalDownloads": 5235386,"versionCountWithDownloads": 523,"topVersions": [{"version": "1.9.17","downloads": 1458725,"sharePct": 27.86},{"version": "1.9.15","downloads": 1327675,"sharePct": 25.36},"..."],"majorVersionShares": [{"major": "1","downloads": 5067928,"sharePct": 96.8},{"major": "2","downloads": 166093,"sharePct": 3.17},"..."]},"metadata": {"latestVersion": "1.9.17","description": "A declarative JavaScript library for building user interfaces.","license": "MIT","homepage": "https://solidjs.com","repository": "https://github.com/solidjs/solid","deprecated": null,"dependencyCount": 3,"hasTypes": true,"moduleType": "esm","nodeEngine": null},"relativeIndex": 2.7,"shareOfComparisonPct": 1.98,"rank": 6,"packagesCompared": 8,"dataAvailableThrough": "2026-10-25","lastPeriodPartial": false,"series": [{"period": "2026-06-22","downloads": 224820,"days": 1,"estimatedDays": 0,"avgDailyDownloads": 224820,"partial": true,"index": 0.1},{"period": "2026-06-29","downloads": 2643213,"days": 7,"estimatedDays": 0,"avgDailyDownloads": 377601.9,"partial": false,"index": 1.2},"...",{"period": "2026-10-19","downloads": 9197325,"days": 7,"estimatedDays": 3,"avgDailyDownloads": 1313903.6,"partial": false,"index": 4.1}]}
Free rows look like this:
{"input": "this-package-does-not-exist-zz9q", "package": "this-package-does-not-exist-zz9q", "packageUrl": "https://www.npmjs.com/package/this-package-does-not-exist-zz9q", "startDate": "2026-06-28", "endDate": "2026-10-25", "granularity": "weekly", "gapHandling": "interpolate", "status": "not_found", "error": "Package not found in the npm registry (or no download data for this range)."}
Field notes:
totalDownloadsis gap-corrected.rawTotalDownloadsis npm's raw sum, which counts gap days as 0.peakFollowsGap: truemeans the peak is the day right after an outage. npm sometimes books part of the missed downloads on that day, so treat that peak with care. In the run above, 7 of the 8 packages "peaked" on 2026-10-22, just after the 10-19…21 outage.series[].partial: truemarks a weekly or monthly bucket cut by the date range, typically the first and/or last bucket. CompareavgDailyDownloadsrather thandownloadsfor those buckets.lastPeriodPartialtells you whether the newest bucket is partial.versionscomes from npm's per-version "last-week" endpoint. npm doesn't return which 7 days that covers, and its "last-week" presets can lag the daily data, so use it for shares, not exact weekly totals.metadataholds only non-personal fields from the registry (version, description, licence, repository, homepage, deprecation, dependency count, types, ESM). Author and maintainer names or emails are never collected.weekendToWeekdayRatiois a rough signal: low values usually mean CI and automated installs dominate. That's a heuristic, not a measurement.- Statuses:
ok(charged), plus free statuses:not_found,invalid_name,skipped(your Max cost per run was reached) anderror.
Input
| Field | Default | Notes |
|---|---|---|
packages | ["react","vue"] | Names (react, @angular/core, react@18), npm i x strings or npmjs.com URLs. Duplicates removed. Empty input runs the default. |
lookbackDays | 90 | Used when startDate is empty. npm data starts 2015-01-10. |
startDate / endDate | – / last published day | endDate after the last published day is clamped (logged, endDateClamped in SUMMARY). |
granularity | daily | weekly (Monday start) or monthly. Metrics always use daily data. |
gapHandling | interpolate | exclude or keep. |
includeSeries / includeVersions / includeMetadata | true | The last two cost one extra request per package each. |
contactInfo | – | Optional. Your contact, appended to the User-Agent. |
Limits and tips
- Speed: about 1 request per second. 100 packages over ≤ 365 days with versions and metadata ≈ 1 bulk request + 200 extra requests ≈ 3.5 minutes (est.). Turn off versions/metadata for faster runs.
- Memory: series are held in memory to compute the cross-package index. Above about 500,000 package-days (e.g. 200 packages × 7 years daily), the run logs a warning. Use weekly/monthly granularity, fewer packages per run, or 1 GB+ memory.
- Downloads ≠ users. npm counts tarball downloads, including CI, mirrors and bots (npm docs).
- Gap detection is heuristic. A day is a gap when it is zero for ≥ 80% of the active packages in the run, or zero amid steady traffic for a single package. Very small packages are never "corrected".
- Days before a package's first download in the window are real zeros and are never corrected. The same goes for a package's own trailing zeros (removed, renamed or abandoned). Only zero days between real downloads, and run-wide outage days, are treated as gaps, and corrected days are flagged
estimated.rawTotalDownloadsalways keeps npm's raw sum. - The end date is npm's latest published day, probed at run start. Only if that probe fails does the Actor fall back to two days ago and trim trailing days that are 0 for every package.
Pricing (pay per event)
package-trend once per ok row. All other rows are free. The run stops charging at your Max cost per run. Packages beyond it come back as free skipped rows, and every input still gets a row. See PRICING.md.
Legal and data notes
- Data source: npm's public downloads API and registry, used at ≤ 1 request/second with an identifying User-Agent:
DownloadTrendsBot/0.1.0 (+https://apify.com/capable_santolina/download-trends-for-npm-packages; pounderswork@mail.grokbot.com) apify-sdk/3 node/<version>. See npm's crawler policy and Open-Source Terms.api.npmjs.org/robots.txtreturns 404 (no restrictions), and npmjs.com web pages are never requested. - No personal data: maintainer and author fields are dropped.
- Trademark: "npm" is used only to describe the data source, following npm's logo and usage policy. The Actor title deliberately leaves out the npm mark. npm is a registered trademark of npm, Inc. No npm logo is used.
- Contact / takedown: pounderswork@mail.grokbot.com.