npm Download Trends & Package Comparison avatar

npm Download Trends & Package Comparison

Pricing

from $1.40 / 1,000 package analyseds

Go to Apify Store
npm Download Trends & Package Comparison

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

Doyle Pounders

Maintained by Community

Actor 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.

RankPackageDownloads (gap-corrected)Index 0–100Share %30 d vs prev 30 d %Momentum
1react3,127,868,07610072.0616.08growing
2preact579,777,78618.513.3623.42growing
3vue280,931,05796.4716.34growing
4@angular/core107,772,7923.42.484.97stable
5svelte105,568,5723.42.4323.74growing
6solid-js85,915,4632.71.9870.82surging
7@sveltejs/kit48,710,4851.61.1228.61surging
8htmx.org4,389,4540.10.116.1growing

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:

  • totalDownloads is gap-corrected. rawTotalDownloads is npm's raw sum, which counts gap days as 0.
  • peakFollowsGap: true means 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: true marks a weekly or monthly bucket cut by the date range, typically the first and/or last bucket. Compare avgDailyDownloads rather than downloads for those buckets. lastPeriodPartial tells you whether the newest bucket is partial.
  • versions comes 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.
  • metadata holds 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.
  • weekendToWeekdayRatio is 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) and error.

Input

FieldDefaultNotes
packages["react","vue"]Names (react, @angular/core, react@18), npm i x strings or npmjs.com URLs. Duplicates removed. Empty input runs the default.
lookbackDays90Used when startDate is empty. npm data starts 2015-01-10.
startDate / endDate– / last published dayendDate after the last published day is clamped (logged, endDateClamped in SUMMARY).
granularitydailyweekly (Monday start) or monthly. Metrics always use daily data.
gapHandlinginterpolateexclude or keep.
includeSeries / includeVersions / includeMetadatatrueThe 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. rawTotalDownloads always 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.

  • 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.txt returns 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.