# npm Package Monitor: Versions, License & Downloads (`cliqtomedia/npm-package-metadata-monitor`) Actor

Check up to 100 npm packages per run: latest dist-tag and highest stable semver, release dates, license, repository, maintainers count, deprecation, weekly downloads, and new releases since a date or since the last run.

- **URL**: https://apify.com/cliqtomedia/npm-package-metadata-monitor.md
- **Developed by:** [Cliqto Media](https://apify.com/cliqtomedia) (community)
- **Categories:** Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.56 / 1,000 package records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

Check up to 100 npm packages in one run and get one row per package: the `latest` dist-tag, the highest stable semver version, release dates, declared license, repository, maintainers count, deprecation and weekly downloads. The data comes from the public npm registry and the npm downloads API, with no login or API key.

Use it to watch your dependencies for new releases (since a date or since your last run) or to build a package metadata table. A run with the five prefilled packages takes a few seconds and costs about $0.0055.

![npm Package Release Monitor: list your npm packages, get one row per package with latest dist-tag, highest stable version, license, downloads, and the new releases since a date or since your last run](https://api.apify.com/v2/key-value-stores/xM41fAFFsPA32mgjo/records/README-BANNER-20261012.png)

### Table of contents

- [What it does](#what-it-does)
- [What data you get](#what-data-you-get)
- [Quick start](#quick-start)
- [Input](#input)
- [Input examples](#input-examples)
- [Output example](#output-example)
- [Output fields](#output-fields)
- [Pricing](#pricing)
- [Use cases](#use-cases)
- [Monitoring and scheduling](#monitoring-and-scheduling)
- [API, export and integrations](#api-export-and-integrations)
- [Limits and partial results](#limits-and-partial-results)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
- [Related Actors](#related-actors)
- [Support](#support)

### What it does

You give a list of npm package names. For each name, the Actor reads the package document from the [npm registry](https://registry.npmjs.org) and, if you want, the last-week download count from the [npm downloads API](https://github.com/npm/registry/blob/main/docs/download-counts.md). It writes one Dataset row per package.

The Actor keeps two version answers apart:

- `latestVersion` is the version the `latest` dist-tag points to. This is what `npm install <name>` installs.
- `highestStableVersion` is the highest non-prerelease version by semver order.

They are often the same, but not always. For example, a project can publish a fix for an old major line after the new major. `latestIsHighestStable` tells you if they match.

The Actor can also report **new releases**: versions published since a date (`sinceDate`) or since the previous run with the same `monitorKey`.

#### Good fit

- Watch your project's dependencies and see which ones had new releases since last week.
- Build a table of packages with license, repository, maintainers count and deprecation.
- Compare weekly downloads and release activity of several packages.

#### Not a fit / limits

- It is **not a security scanner**. It does not check vulnerabilities, malware or code. `latestHasProvenance` only says that npm has a build attestation for the latest version.
- It does not verify licenses. `license` is what the package author declared.
- It reads only the public npm registry. Private registries, GitHub Packages and other registries are not supported.
- It does not resolve dependency trees and does not read your `package.json` or lock file. You list the package names.

### What data you get

| Group | Fields |
| --- | --- |
| Versions | `latestVersion`, `highestStableVersion`, `highestVersion`, `latestIsHighestStable`, `distTags`, `versionsCount`, `prereleaseVersionsCount`, `deprecatedVersionsCount` |
| Dates | `createdAt`, `latestPublishedAt`, `lastReleaseAt`, `lastStableReleaseAt`, `daysSinceLastRelease`, `recentReleases` |
| Package facts | `description`, `license`, `repositoryUrl`, `homepage`, `bugsUrl`, `maintainersCount`, `deprecated`, `deprecationMessage`, `latestHasProvenance`, `latestDependenciesCount`, `latestUnpackedSize`, `nodeEngine` |
| Popularity | `weeklyDownloads`, `downloadsPeriod` |
| Monitoring | `newReleases`, `newReleasesCount`, `baselineKind`, `baselineAt` |
| Provenance of data | `status`, `provider`, `fetchedAt`, `sourceUpdatedAt`, `error` |

Maintainer names and email addresses are never output. You get only `maintainersCount`.

### Quick start

1. Open the **Input** tab.
2. In **npm packages** (`packages`), keep the prefilled names (`react`, `express`, `lodash`, `@types/node`, `typescript`) or add your own.
3. Keep the other settings as they are.
4. Click **Start**.
5. Open the **Output** tab and check the **Packages** view: `latestVersion`, `highestStableVersion`, `license` and `weeklyDownloads`.

Expected result: one row with status `complete` for each package, in a few seconds.

### Input

| Field | Plain name | Type | Required | Default | Allowed values | What it changes | Recommendation |
| --- | --- | --- | --- | --- | --- | --- | --- |
| `packages` | npm packages | array of strings | yes | prefill: `react`, `express`, `lodash`, `@types/node`, `typescript` | 1–100 unique names | Which packages to check | Use exact names. Scoped names like `@types/node` work. |
| `includePrereleases` | Include prereleases | boolean | no | `false` | `true`, `false` | Adds prereleases (canary, beta, rc…) to `recentReleases`, `newReleases` and `daysSinceLastRelease` | Keep `false` if you only care about stable releases. |
| `sinceDate` | New releases since date | string | no | empty | `YYYY-MM-DD` (UTC) or ISO date-time, not in the future | Fills `newReleases` with versions published on or after this date | Use for a one-time "what changed since…" check. |
| `monitorKey` | Monitor key | string | no | empty | 1–63 letters, digits, `-`, `_` | Remembers what the run saw; the next run with the same key reports only newer versions | Use one key per package list, for example `my-app-deps`. |
| `onlyNewReleases` | Only output packages with new releases | boolean | no | `false` | `true`, `false` | Writes only packages with new releases; others are checked but not written | Needs `sinceDate` or `monitorKey`. Good for scheduled monitoring. |
| `includeDownloads` | Include weekly downloads | boolean | no | `true` | `true`, `false` | Adds `weeklyDownloads` from the npm downloads API | Turn off if you do not need popularity data. The price is the same. |
| `maxRecentReleases` | Recent releases per package | integer | no | `10` | 0–100 | How many newest versions go into `recentReleases` | Use `0` for smaller rows. |

**How package names are read.** Each entry can be a name (`react`), a scoped name (`@babel/core`), an npmjs.com link (`https://www.npmjs.com/package/@babel/core`) or a name with a version (`lodash@4.17.21`). The version part is ignored, and the run summary shows a warning. Names are case-sensitive: `JSONStream` and `jsonstream` are different packages. Exact repeats are removed before the run. A name that npm cannot have gets a free row with status `invalid`, and no request is made for it. You can also send `packages` as one comma- or newline-separated string through the API.

#### Interacting settings

| When | Setting A | Setting B | What happens |
| --- | --- | --- | --- |
| Both are set | `monitorKey` | `sinceDate` | Packages already in the snapshot are compared with the previous run. New packages in the list are compared with `sinceDate`. |
| First run with a key | `monitorKey` | — | This run is the baseline: `newReleases` is `null` and `baselineKind` is `initial`. The next run reports changes. |
| Monitoring only | `onlyNewReleases` | `sinceDate` or `monitorKey` | Without a baseline the run stops with `INVALID_INPUT`. Packages without new releases are checked and charged at a lower price, but not written. |
| Prereleases | `includePrereleases` | `sinceDate` / `monitorKey` | With `false`, a new canary or beta is not a new release. |

### Input examples

#### Check a few packages (the prefill)

```json
{
  "packages": ["react", "express", "lodash", "@types/node", "typescript"]
}
```

Expected behavior: the Actor reads five registry documents and the download counts. Expected output: five `complete` rows with `latestVersion`, `highestStableVersion`, `license`, `weeklyDownloads`. Cost: $0.0055 on the Free plan.

#### Releases since a date

```json
{
  "packages": ["react", "express", "lodash", "@types/node", "typescript"],
  "sinceDate": "2026-10-01"
}
```

Expected output: the same rows, plus `newReleases` with the versions published on or after 1 October 2026, newest first. `[]` means no new releases.

#### Weekly monitoring of your dependencies

```json
{
  "packages": ["react", "express", "lodash", "@types/node", "typescript"],
  "monitorKey": "my-app-deps",
  "onlyNewReleases": true
}
```

Expected behavior: the first run saves a baseline and writes all packages. Each next run writes only packages with versions published since the previous run. If nothing changed, the run ends with status `NO_CHANGES` and an empty Dataset.

### Output example

This is a real row for `express` from the prefill run (trimmed: `recentReleases` shows 2 of 10 items).

```json
{
  "input": "express",
  "packageName": "express",
  "status": "complete",
  "npmUrl": "https://www.npmjs.com/package/express",
  "registryUrl": "https://registry.npmjs.org/express",
  "description": "Fast, unopinionated, minimalist web framework",
  "latestVersion": "5.3.0",
  "distTags": { "latest": "5.3.0", "latest-4": "4.22.3" },
  "highestStableVersion": "5.3.0",
  "highestVersion": "5.3.0",
  "latestIsHighestStable": true,
  "versionsCount": 290,
  "prereleaseVersionsCount": 43,
  "deprecatedVersionsCount": 173,
  "createdAt": "2010-12-29T19:38:25.450Z",
  "modifiedAt": "2026-10-09T12:56:55.078Z",
  "latestPublishedAt": "2026-10-09T12:56:54.505Z",
  "lastReleaseAt": "2026-10-09T12:56:54.505Z",
  "lastStableReleaseAt": "2026-10-09T12:56:54.505Z",
  "daysSinceLastRelease": 3,
  "license": "MIT",
  "repositoryUrl": "https://github.com/expressjs/express",
  "repositoryRaw": "git+https://github.com/expressjs/express.git",
  "repositoryDirectory": null,
  "homepage": "https://expressjs.com/",
  "bugsUrl": "https://github.com/expressjs/express/issues",
  "maintainersCount": 5,
  "deprecated": false,
  "deprecationMessage": null,
  "latestHasProvenance": true,
  "latestDependenciesCount": 28,
  "latestUnpackedSize": 76638,
  "nodeEngine": ">= 18",
  "weeklyDownloads": 144987450,
  "downloadsPeriod": { "start": "2026-10-05", "end": "2026-10-11" },
  "recentReleases": [
    { "version": "5.3.0", "publishedAt": "2026-10-09T12:56:54.505Z", "isPrerelease": false, "deprecated": false },
    { "version": "4.22.3", "publishedAt": "2026-09-14T06:46:38.631Z", "isPrerelease": false, "deprecated": false }
  ],
  "newReleases": null,
  "newReleasesCount": null,
  "baselineKind": "none",
  "baselineAt": null,
  "unpublishedAt": null,
  "provider": "npm public registry (registry.npmjs.org) and npm downloads API (api.npmjs.org)",
  "fetchedAt": "2026-10-12T14:34:04.374Z",
  "sourceUpdatedAt": "2026-10-09T12:56:55.078Z",
  "error": null
}
```

**null and 0 are different.** `null` means unknown or not declared. `0` means the real value is zero. For example, `weeklyDownloads: 0` means nobody downloaded the package last week, and `weeklyDownloads: null` means the count was not requested or the downloads API failed.

### Output fields

| Field | Meaning | Type | Can be null? | Example |
| --- | --- | --- | --- | --- |
| `input` | The entry as you typed it | string | no | `lodash@4.17.21` |
| `packageName` | Exact npm name that was looked up | string | yes, for `invalid` | `lodash` |
| `status` | Row result, see the table below | string | no | `complete` |
| `npmUrl` | Package page on npmjs.com | string | yes, for `invalid` | `https://www.npmjs.com/package/express` |
| `registryUrl` | Registry document the data came from | string | yes, for `invalid` | `https://registry.npmjs.org/express` |
| `description` | Package description (up to 2000 characters) | string | yes | `Fast, unopinionated…` |
| `latestVersion` | Version of the `latest` dist-tag | string | yes | `5.3.0` |
| `distTags` | All dist-tags and their versions | object | yes | `{"latest":"5.3.0","next":"…"}` |
| `highestStableVersion` | Highest non-prerelease version by semver | string | yes, if only prereleases exist | `5.3.0` |
| `highestVersion` | Highest version by semver, prereleases included | string | yes | `19.3.0` |
| `latestIsHighestStable` | `true` if `latestVersion` equals `highestStableVersion` | boolean | yes, if unknown | `true` |
| `versionsCount` | Number of published versions | integer | yes | `290` |
| `prereleaseVersionsCount` | How many versions are prereleases or not valid semver | integer | yes | `43` |
| `deprecatedVersionsCount` | How many versions are deprecated | integer | yes | `173` |
| `createdAt` | First publish time (ISO 8601, UTC) | string | yes | `2010-12-29T19:38:25.450Z` |
| `modifiedAt` | Last change of the registry document | string | yes | `2026-10-09T12:56:55.078Z` |
| `latestPublishedAt` | Publish time of `latestVersion` | string | yes | `2026-10-09T12:56:54.505Z` |
| `lastReleaseAt` | Newest publish time of any version | string | yes | `2026-10-09T12:56:54.505Z` |
| `lastStableReleaseAt` | Newest publish time of a stable version | string | yes | `2026-10-09T12:56:54.505Z` |
| `daysSinceLastRelease` | Whole days since the last stable release (any release with `includePrereleases`) | integer | yes | `3` |
| `license` | Declared license of the latest version, usually an SPDX expression | string | yes, if not declared | `MIT` |
| `repositoryUrl` | Repository as an https URL (credentials and `.git` removed) | string | yes | `https://github.com/expressjs/express` |
| `repositoryRaw` | Repository value as declared | string | yes | `git+https://github.com/expressjs/express.git` |
| `repositoryDirectory` | Folder inside a monorepo | string | yes | `packages/react` |
| `homepage` | Declared homepage | string | yes | `https://expressjs.com/` |
| `bugsUrl` | Declared issue tracker | string | yes | `https://github.com/expressjs/express/issues` |
| `maintainersCount` | Number of npm maintainer accounts | integer | yes | `5` |
| `deprecated` | `true` if the latest version is deprecated | boolean | yes | `false` |
| `deprecationMessage` | The author's deprecation message | string | yes | `use String.prototype.padStart()` |
| `latestHasProvenance` | `true` if the latest version has an npm provenance attestation | boolean | yes | `true` |
| `latestDependenciesCount` | Runtime `dependencies` of the latest version | integer | yes | `28` |
| `latestUnpackedSize` | Unpacked size of the latest version, bytes | integer | yes | `76638` |
| `nodeEngine` | `engines.node` range of the latest version | string | yes | `>= 18` |
| `weeklyDownloads` | Downloads in the last full week | integer | yes, if off or failed | `144987450` |
| `downloadsPeriod` | Dates the count covers | object | yes | `{"start":"2026-10-05","end":"2026-10-11"}` |
| `recentReleases` | Newest versions with dates, newest first | array | no (can be `[]`) | `[{"version":"5.3.0",…}]` |
| `newReleases` | Versions published since the baseline, newest first | array | yes, if no baseline | `[]` |
| `newReleasesCount` | Number of items in `newReleases` | integer | yes, if no baseline | `0` |
| `baselineKind` | What `newReleases` is compared with: `snapshot`, `sinceDate`, `initial`, `none` | string | no | `none` |
| `baselineAt` | Baseline time | string | yes | `2026-10-01T00:00:00.000Z` |
| `unpublishedAt` | When the package was unpublished | string | yes | `null` |
| `provider` | Data source | string | no | `npm public registry…` |
| `fetchedAt` | When the row was fetched | string | no | `2026-10-12T14:34:04.374Z` |
| `sourceUpdatedAt` | When the registry document last changed | string | yes | `2026-10-09T12:56:55.078Z` |
| `error` | Why a row is not complete: `code` and `message` | object | yes | `{"code":"NOT_FOUND","message":"…"}` |

Each item in `recentReleases` and `newReleases` has `version`, `publishedAt`, `isPrerelease` and `deprecated`.

#### Row status

| `status` | Meaning | Charged? |
| --- | --- | --- |
| `complete` | All requested data is in the row | yes |
| `partial` | Package data is there, but `weeklyDownloads` is missing (see `error`) | yes |
| `not_found` | npm has no package with this name (HTTP 404). This is an answer, not an error | no |
| `unpublished` | The package existed, but all versions were removed | no |
| `invalid` | Not a valid npm name, no request was made | no |
| `error` | The lookup failed (see `error.code`) | no |

#### Output surfaces

| Situation | Where to look | What you see |
| --- | --- | --- |
| Normal run | Dataset, view **Packages** | One row per package |
| Monitoring | Dataset, view **New releases** | `newReleases`, `baselineKind`, `baselineAt` |
| Nothing found | Dataset rows with `not_found` / `invalid`; run summary status `NO_RESULTS` | Check the names |
| No new releases with `onlyNewReleases` | Empty Dataset; run summary status `NO_CHANGES` | Nothing to do |
| Source problem | Rows with `error`; run summary status `PARTIAL` or `ERROR` | Run again later |

Every run also saves `RUN_SUMMARY` in the default key-value store: status, counts (complete, not found, invalid, errors, skipped), downloads coverage, baseline and source notes.

### Pricing

This Actor uses pay-per-event pricing. You pay only for these events:

| Event | When | Free | Bronze | Silver | Gold |
| --- | --- | ---: | ---: | ---: | ---: |
| Actor start | Once per run (per 1 GB of memory; default memory is 1 GB) | $0.0015 | $0.0015 | $0.0015 | $0.0015 |
| Package record | Each `complete` or `partial` row written to the Dataset | $0.0008 | $0.00075 | $0.0007 | $0.00065 |
| Unchanged package check | With `onlyNewReleases`: each package that was checked but had no new releases, so no row was written | $0.0002 | $0.0002 | $0.0002 | $0.0002 |

Rows with `not_found`, `unpublished`, `invalid` and `error` are free. Weekly downloads do not cost extra. A run where every name is not found or invalid costs only the Actor start.

#### Cost examples (Free plan prices)

| Scenario | Input | Events | Cost |
| --- | --- | --- | ---: |
| Prefill | 5 packages | 1 start + 5 records | $0.0055 |
| Small list | 10 packages | 1 start + 10 records | $0.0095 |
| Full run | 100 packages | 1 start + 100 records | $0.0815 |
| 1,000 packages | 10 runs of 100 | 10 starts + 1,000 records | $0.815 |
| Monitoring, nothing new | 100 packages, `onlyNewReleases` | 1 start + 100 unchanged checks | $0.0215 |
| Monitoring, 3 packages changed | 100 packages, `onlyNewReleases` | 1 start + 3 records + 97 unchanged checks | $0.0233 |

You can set a maximum total charge for a run. When the next event would go over it, the Actor stops early, writes what it has and sets status `CAPPED` in the run summary. The rest of the packages are listed in `skippedPackages`.

### Use cases

| Job | Input | Key fields | Next step |
| --- | --- | --- | --- |
| Weekly dependency release check | `packages`, `monitorKey`, `onlyNewReleases` | `newReleases`, `latestVersion`, `deprecated` | Send the Dataset to Slack or email with an Apify integration |
| "What changed since our last upgrade?" | `packages`, `sinceDate` | `newReleases`, `latestIsHighestStable` | Plan upgrades |
| Package inventory | `packages` | `license`, `repositoryUrl`, `maintainersCount`, `deprecated` | Export to CSV or Excel |
| Compare packages | `packages` | `weeklyDownloads`, `daysSinceLastRelease`, `versionsCount` | Sort in a spreadsheet |

### Monitoring and scheduling

1. Add your packages and a `monitorKey`, for example `my-app-deps`.
2. Run once. This saves the baseline in a named key-value store `npm-package-metadata-monitor` in your Apify account.
3. Create an Apify [schedule](https://docs.apify.com/platform/schedules) for this input, for example every Monday.
4. Turn on `onlyNewReleases` if you want only changed packages in the Dataset.

Each run compares with the newest publish time it saw for each package in the previous run with the same key. The snapshot learns only about packages the run really checked, so a stopped or failed run does not hide releases from the next one. Use a different `monitorKey` for each package list.

### API, export and integrations

- **API:** start a run with the [Apify API](https://docs.apify.com/api/v2) and read the Dataset items. Use `?view=overview` for the short table or `?view=releases` for monitoring fields.
- **Export:** download the Dataset as JSON, CSV, Excel, XML or HTML from the Output tab.
- **Scheduling and webhooks:** use Apify schedules to run on a timer and webhooks or integrations (Slack, email, Zapier, Make) to act when a run finishes.

#### Use with AI agents (MCP)

This Actor works with the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp). MCP server URL with only this Actor:

`https://mcp.apify.com?tools=cliqtomedia/npm-package-metadata-monitor`

Smallest useful input:

```json
{ "packages": ["react", "express"] }
```

Key output fields: `latestVersion` (what `npm install` installs), `highestStableVersion` (highest stable semver), `newReleases` (versions since the baseline), `license` (declared license), `deprecated`. A run with up to 5 packages usually finishes in under 10 seconds and costs $0.0015 plus $0.0008 per package on the Free plan. The limit is 100 packages per run.

### Limits and partial results

- Up to **100 unique packages** per run. For more, start several runs.
- The Actor stops its own work at about 4 minutes of a 5-minute default timeout. In tests, 100 large packages (React, TypeScript, AWS SDK and others) took 53 seconds.
- A safety limit of 120 MB applies to each registry document; a bigger document gives a row with status `error` and code `SOURCE_TOO_LARGE`. The largest documents we tested (about 31 MB, packages like `next` and `aws-sdk`) took a few seconds each.
- If the npm downloads API fails, package rows are still written with `weeklyDownloads: null` and status `partial`.
- If the npm registry fails or does not answer, the Actor retries a few times and then stops asking. The rest of the packages are listed as skipped, and the run summary status is `PARTIAL` or `ERROR`. These rows are not charged.
- Download counts are npm's own numbers and can change after the week ends.

### Troubleshooting

#### A package shows `not_found`

Symptom: `status` is `not_found`.
Likely reason: the name is wrong or has a different case. npm names are case-sensitive.
Action: check the name on npmjs.com. A scoped package needs the scope: `@types/node`, not `node`.

#### `weeklyDownloads` is null

Symptom: `status` is `partial` and `error.code` is `RATE_LIMITED` or `SOURCE_UNAVAILABLE`.
Likely reason: the npm downloads API did not answer in time.
Action: run again later, or set `includeDownloads` to `false` if you do not need downloads.

#### The run status is `NO_CHANGES`

Likely reason: no package had new releases since `sinceDate` or since the previous run with this `monitorKey`. With `onlyNewReleases` on, the Dataset is empty. Without it, the Dataset still has all rows, each with `newReleasesCount` 0.
Action: nothing to fix. Turn `onlyNewReleases` off to see all rows.

#### `newReleases` is null

Likely reason: this is the first run with this `monitorKey` (the baseline), or you did not set `sinceDate` or `monitorKey`.
Action: run again with the same `monitorKey`, or add a `sinceDate`.

#### The run stops with `INVALID_INPUT`

Likely reason: more than 100 packages, an empty list, a future `sinceDate`, a bad `monitorKey`, or `onlyNewReleases` without `sinceDate` or `monitorKey`.
Action: read the status message. It names the field to fix.

### FAQ

#### Do I need an npm account or token?

No. The Actor reads only public data from the npm registry and the npm downloads API.

#### Why is `latestVersion` lower than `highestStableVersion`?

The `latest` dist-tag is set by the package authors. Sometimes they publish a new version for an old line, or they move `latest` back. `latestVersion` is what `npm install` gives you; `highestStableVersion` is the highest stable number.

#### Does this Actor tell me if a package is safe?

No. It reports what the registry declares: versions, dates, license, repository, deprecation and downloads. It does not check vulnerabilities, malware or the code.

#### How fresh is the data?

Each row is read from the registry during the run. `fetchedAt` shows when, and `sourceUpdatedAt` shows when the registry document last changed.

### Related Actors

- [Software End-of-Life Checker](https://apify.com/cliqtomedia/software-end-of-life-checker): check if your runtime and framework versions (Node.js, Python, databases) are still supported.

### Support

Open an issue in the **Issues** tab of this Actor for a bug, a question or a feature idea. Include the run ID, your input (package names are fine) and the error text. Never send tokens or passwords.

Data from the public [npm registry](https://www.npmjs.com/) under the [npm Open-Source Terms](https://docs.npmjs.com/policies/open-source-terms). This Actor is not affiliated with or endorsed by npm, Inc. or GitHub, Inc.

# Changelog

This Actor's version history is a separate document: https://apify.com/cliqtomedia/npm-package-metadata-monitor/changelog.md

# Actor input Schema

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

Up to 100 unique npm package names per run, e.g. react, @types/node. npmjs.com/package/... links and name@version also work (the version part is ignored). Names are case-sensitive; exact repeats are removed. Invalid names get a free row with status "invalid".

## `includePrereleases` (type: `boolean`):

Include prerelease versions (canary, beta, rc, next…) in recentReleases, newReleases and daysSinceLastRelease. highestStableVersion always ignores prereleases.

## `sinceDate` (type: `string`):

Report versions published on or after this date in newReleases, e.g. 2026-10-01 (UTC) or an ISO date-time. Leave empty to skip. With monitorKey, packages already in the snapshot are compared with the previous run instead.

## `monitorKey` (type: `string`):

Any name, e.g. my-app-deps. The Actor remembers what it saw under this key (in a named key-value store in your account) and the next run reports only versions published since then. The first run is the baseline (newReleases null). Letters, digits, - and \_ only.

## `onlyNewReleases` (type: `boolean`):

With sinceDate or monitorKey: write only packages that have new releases (and packages seen for the first time under monitorKey, as the baseline). Unchanged packages are checked for a smaller fee and not written. Not found, invalid and failed packages are still listed for free.

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

Add last-week download counts from the npm downloads API. If that API fails, metadata is still returned with weeklyDownloads null and status "partial".

## `maxRecentReleases` (type: `integer`):

How many of the newest versions (with publish dates) to list in recentReleases. 0 turns the list off.

## Actor input object example

```json
{
  "packages": [
    "react",
    "express",
    "lodash",
    "@types/node",
    "typescript"
  ],
  "includePrereleases": false,
  "onlyNewReleases": false,
  "includeDownloads": true,
  "maxRecentReleases": 10
}
```

# Actor output Schema

## `packages` (type: `string`):

One row per package: versions, release dates, license, repository, maintainers count, deprecation and weekly downloads.

## `releases` (type: `string`):

Release monitoring view: new releases since sinceDate or the previous run, with baseline.

## `runSummary` (type: `string`):

Status, counts (found, not found, invalid, errors, skipped), downloads coverage, baseline and source notes.

# 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": [
        "react",
        "express",
        "lodash",
        "@types/node",
        "typescript"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cliqtomedia/npm-package-metadata-monitor").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": [
        "react",
        "express",
        "lodash",
        "@types/node",
        "typescript",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("cliqtomedia/npm-package-metadata-monitor").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": [
    "react",
    "express",
    "lodash",
    "@types/node",
    "typescript"
  ]
}' |
apify call cliqtomedia/npm-package-metadata-monitor --silent --output-dataset

```

## MCP server setup

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

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/sze0B6xxqeYrYPzlh/builds/IrRQRQnQPd50byexe/openapi.json
