# npm Scraper: Package Data, Versions, Downloads & Search (`winterlock/npm-package-scraper`) Actor

Export npm package metadata, full version history with publish dates and deprecations, daily download series and registry search results. Official npm APIs, scoped packages supported, no login.

- **URL**: https://apify.com/winterlock/npm-package-scraper.md
- **Developed by:** [Alex Burton](https://apify.com/winterlock) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 package or search hits

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## npm Scraper: Package Data, Versions, Downloads & Search

Export npm registry data to JSON, CSV or Excel. Everything comes from npm's official registry and downloads APIs, so there is no HTML parsing, no login and nothing that breaks when npmjs.com is redesigned.

One Actor, four jobs:

| Mode | What you get |
|---|---|
| **Package details** | Version, description, licence, repository, author, maintainers, dependency list and counts, Node requirement, deprecation status, tarball size, file count and download total |
| **Version history** | Every published version with its publish date, dist-tags, pre-release and deprecation flags, licence, size and file count |
| **Daily downloads** | One row per day, for any period up to 18 months |
| **Registry search** | npm search results with weekly and monthly downloads, dependents count, publisher, maintainers, licence, repository and npm's relevance score |

### Why use this one

- **Deprecations are first-class.** Every version carries `isDeprecated` and the maintainer's reason. Auditing a dependency tree for abandoned packages is a single run.
- **Daily download series, not just a total.** Most npm tools show one number. This gives you a row per day so you can chart adoption or spot the week a package took off.
- **Scoped packages just work.** `@scope/name` is percent-encoded for you, which is the usual reason a hand-rolled npm script returns 404.
- **Sized for speed.** Package details reads npm's small per-version document rather than the full package manifest, which for a popular package is close to a megabyte of version history you did not ask for. Turn on *Include publish dates* only when you need it.
- **Search rows are ready to rank.** Each hit carries weekly and monthly downloads and its dependents count beside npm's relevance score, so you can sort by real adoption instead of search order. (npm no longer computes its old quality, popularity and maintenance sub-scores, so they are not included.)

### How to use it

1. Choose **What to scrape**.
2. Add **Packages** by name or npmjs.com link, or write **Search queries**.
3. Click **Start**, then download the results or pull them through the Apify API.

#### Example input: audit a dependency list

```json
{
  "mode": "packageDetails",
  "packages": ["express", "lodash", "request", "@apify/consts"],
  "includeDownloads": true
}
```

#### Example input: chart a year of adoption

```json
{
  "mode": "downloads",
  "packages": ["vitest"],
  "downloadsStart": "2026-01-01",
  "downloadsEnd": "2026-10-01"
}
```

#### Example input: find the leading packages in a niche

```json
{
  "mode": "search",
  "searchQueries": ["pdf generation", "keywords:web-scraping"],
  "maxResultsPerSearch": 100
}
```

### Output

Each item carries a `type` field: `package`, `version`, `downloads` or `searchHit`.

**Package**

```json
{
  "type": "package",
  "registry": "npm",
  "name": "express",
  "version": "5.3.0",
  "description": "Fast, unopinionated, minimalist web framework",
  "license": "MIT",
  "author": "TJ Holowaychuk",
  "repositoryUrl": "https://github.com/expressjs/express",
  "dependencyCount": 24,
  "nodeRequirement": ">= 18",
  "isDeprecated": false,
  "unpackedSizeBytes": 213655,
  "fileCount": 16,
  "downloads": 635513489,
  "downloadsPeriod": "2026-09-13..2026-10-12",
  "url": "https://www.npmjs.com/package/express"
}
```

**Daily downloads**

```json
{ "type": "downloads", "registry": "npm", "name": "express", "day": "2026-09-01", "downloads": 24656639 }
```

### Download date ranges

npm serves at most 18 months of daily download counts per request. A longer span
is rejected before the run starts rather than coming back empty — split it into
shorter runs.

### Pricing

Pay only for results:

| Result | Price |
|---|---|
| Package or search hit | $5.00 per 1,000 |
| Version or download day | $1.00 per 1,000 |

Set a maximum spend per run in the run options and the Actor stops cleanly when it is reached.

### Limits to know about

These come from npm's APIs, not from this Actor:

- **Download history goes back 18 months** per request, and npm's download data starts in 2015. Longer ranges return an error, so split them into several runs.
- **Download counts are per package, not per version.** npm does not publish per-version download numbers.
- **Search results are capped at 5,000 per query** by the registry, and relevance ranking is npm's own.
- **Publish dates need the full package document.** They are off by default because that document is large; turn on *Include publish dates* to get `createdAt`, `modifiedAt` and `versionCount`.
- Private and unpublished packages are not available anonymously and return nothing.

### FAQ

**Do I need an npm account or token?** No. Everything here is public registry data.

**Does it handle scoped packages?** Yes. Pass `@scope/name` exactly as you would type it.

**Can I watch a package daily?** Yes. Create a schedule in Apify Console and connect the dataset to Slack, Google Sheets, Zapier or Make.

**Why is `versionCount` empty?** It only appears when *Include publish dates* is on, because it is read from the full package document.

### Feedback

Found a bug or need a field that is missing? Open an issue on the Actor's **Issues** tab.

# Actor input Schema

## `mode` (type: `string`):

Package metadata, every published version, a daily download series, or a registry search.

## `packages` (type: `array`):

Package names (express, @apify/consts) or npmjs.com links. Scoped names are encoded for you.

## `searchQueries` (type: `array`):

For Registry search. npm search qualifiers work too, for example: web scraping keywords:crawler

## `maxResultsPerSearch` (type: `integer`):

For Search. How many packages to return per query. npm serves up to 250 per request.

## `includeDownloads` (type: `boolean`):

Adds one request per package to fetch its download total.

## `includePublishDates` (type: `boolean`):

Adds createdAt, modifiedAt and versionCount. This downloads the full package document, which is close to a megabyte for popular packages, so it is off by default.

## `maxVersionsPerPackage` (type: `integer`):

Version history mode only.

## `newestVersionsFirst` (type: `boolean`):

For Versions. On, the newest versions come first and the cap keeps the most recent ones. Off, the history starts from the first release.

## `downloadsPeriod` (type: `string`):

Used by Daily downloads, and by Package details when download counts are on.

## `downloadsStart` (type: `string`):

YYYY-MM-DD. Overrides the period above. npm serves at most 18 months of history per request.

## `downloadsEnd` (type: `string`):

YYYY-MM-DD. Required if a start date is given.

## `maxItems` (type: `integer`):

Stop the run after saving this many items. Leave empty for no limit.

## `maxConcurrency` (type: `integer`):

How many requests run at once. The registry copes well with four; raise it for large package lists.

## `proxyConfiguration` (type: `object`):

Not needed for most runs. The npm registry is generous with anonymous traffic.

## Actor input object example

```json
{
  "mode": "packageDetails",
  "packages": [
    "express"
  ],
  "searchQueries": [
    "web scraping"
  ],
  "maxResultsPerSearch": 50,
  "includeDownloads": true,
  "includePublishDates": false,
  "maxVersionsPerPackage": 100,
  "newestVersionsFirst": true,
  "downloadsPeriod": "last-month",
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "packages": [
        "express"
    ],
    "searchQueries": [
        "web scraping"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("winterlock/npm-package-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "packages": ["express"],
    "searchQueries": ["web scraping"],
}

# Run the Actor and wait for it to finish
run = client.actor("winterlock/npm-package-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "packages": [
    "express"
  ],
  "searchQueries": [
    "web scraping"
  ]
}' |
apify call winterlock/npm-package-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,winterlock/npm-package-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/xrPAoXAZlweyVRHlk/builds/UxZfYUOg5aAyzyEeK/openapi.json
