# Dependency Release Monitor - npm, PyPI, GitHub (`lowlanddata/dependency-release-monitor`) Actor

Watch npm, PyPI and GitHub releases in one feed. Every row names the semver bump and flags the ones that look breaking, and a run stays quiet until something ships. No API key, no GitHub token.

- **URL**: https://apify.com/lowlanddata/dependency-release-monitor.md
- **Developed by:** [Lowland Data](https://apify.com/lowlanddata) (community)
- **Categories:** Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $18.50 / 1,000 result delivereds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Dependency Release Monitor - npm, PyPI & GitHub

Watches the packages your code depends on and tells you when one ships a new version - across **npm**, **PyPI** and **GitHub releases** in a single schema. Every row says how big the jump is (`major`, `minor`, `patch`), whether it looks **breaking**, and what the release notes actually said. It remembers what it has already reported, so a run is quiet until something genuinely ships.

**Live health record:** [lowlanddata.com/status/dependency-release-monitor](https://lowlanddata.com/status/dependency-release-monitor/) - 30-day success rate and daily canary results, failures included. Full input/output reference: [tool page](https://lowlanddata.com/tools/dependency-release-monitor/).

It reads the registries' own public endpoints - the npm registry document, the PyPI JSON API, and the GitHub releases feed. No API key, no GitHub token, no rate-limit babysitting, no scraping around a defence. Maintainer names and addresses sit in two of those three sources; none of them are read, so a row carries versions and dates and nothing about a person.

### Quick start (30 seconds, no keys needed)

1. Hit **Start** with the prefilled `packages: ["npm:zod", "pypi:requests", "github:apify/crawlee"]`. It finishes in seconds and returns the current version of each - that is the baseline.
2. Replace the list with your own. Write `npm:name`, `pypi:name` or `github:owner/repo`; a bare `express` means npm and a bare `owner/repo` means GitHub.
3. Add a **daily schedule** (Actor page -> Schedule). From then on the runs are silent until one of your dependencies publishes.

Point a webhook at it and a new release lands in Slack, a Linear ticket, or your own endpoint before you read it on a changelog site.

### Who uses this

- **Platform and infra teams** watch the 30 libraries that hold production up, filter `isBreaking: true`, and open a ticket only for those.
- **Agencies maintaining many client stacks** run one profile per client with its own `stateStoreName`, so each digest carries that client's dependencies only.
- **Security and compliance people** track when an upstream stops shipping, using `releasedAt` to spot a package that has gone quiet for a year.
- **AI coding agents** call it over MCP before proposing an upgrade: "what changed in these five packages this month, and does any of it break me?"
- **Anyone who has ever been surprised by a major version** in a Monday morning CI failure.

### What you get

One JSON item per **release**. The first run pushes each package's current version so you can see what is being watched; after that, only versions published since the last run.

A quiet patch release:

```json
{
  "package": "zod",
  "ecosystem": "npm",
  "version": "4.5.4",
  "previousVersion": "4.5.3",
  "releasedAt": "2026-08-29T17:55:42.775Z",
  "semverBump": "patch",
  "isBreaking": false,
  "isPrerelease": false,
  "url": "https://www.npmjs.com/package/zod/v/4.5.4",
  "isBaseline": false
}
```

The row you actually bought the tool for - a major bump, with the notes that say why:

```json
{
  "package": "acme/widget",
  "ecosystem": "github",
  "version": "v2.0.0",
  "previousVersion": "v1.9.3",
  "releasedAt": "2026-09-01T08:12:00.000Z",
  "semverBump": "major",
  "isBreaking": true,
  "isPrerelease": false,
  "url": "https://github.com/acme/widget/releases/tag/v2.0.0",
  "highlights": ["drops Node 18", "renames the client export"],
  "notes": "Breaking change\n- drops Node 18\n- renames the client export",
  "isBaseline": false
}
```

And the one everybody else's README hides - a package that could not be read. The run does not die for it; the failure is recorded, the other packages still report, and the run summary says how many targets failed:

```text
WARN  github:acme/private-repo failed: HTTP 404
INFO  [Status message]: 3 new releases across 12 watched packages.
```

Field honesty notes:

- `previousVersion` is the version published immediately before this one, by version order - not by date. A back-ported `1.4.9` released after `2.0.0` is still recorded as following `1.4.8`.
- `semverBump` is `unknown` when a tag is not a version at all (`nightly`, `2026-09-01`), because guessing would be worse than saying so.
- `isBreaking` is true on a major bump, on a `0.x` minor bump (where projects actually put their breaks), or when the release notes announce one. It is a strong hint, not a promise - read the notes.
- `notes` and `highlights` exist only where the source publishes them, which in practice means GitHub releases. npm and PyPI publish no release text at all, and inventing one is not on the table.
- `releasedAt` for GitHub is the release's own timestamp, which can differ from the tag's commit date.

### How change detection works

Every monitor on this store is vague about this, so here it is in full:

- **Where the memory lives.** A named key-value store on *your* account (`stateStoreName`, default `dependency-release-monitor-state`). One entry per profile - the hash of your package list. Nothing about your monitor is stored anywhere else; there is no server on my side holding your list.
- **What the first run does.** It records every version currently published as already-seen, and pushes one row per package (its current version) so the run is not empty. That is the baseline. Set `emitBaseline: false` if you want the first run silent.
- **What later runs do.** They fetch the current version list, subtract everything already seen, and report the difference. Nothing new means an empty run.
- **Does a quiet check still cost?** Only the actor start. There is no per-check charge: a run that finds nothing costs a fraction of a cent, which is what makes an hourly schedule sane.
- **Changing the list.** Adding or removing a package changes the profile, so the new profile takes one baseline run before it alerts. Use a separate `stateStoreName` per client or per project to keep them independent.
- **Starting over.** `resetState: true` forgets everything and re-baselines.

### What a release monitor costs

Pay per outcome: checking is free, you pay when there is news.

| Event                 | Price                                | When it is charged                          |
| --------------------- | ------------------------------------ | ------------------------------------------- |
| **New release alert** | $0.0199 (from $0.0185 on paid plans) | A version published since the last run      |
| **Baseline result**   | $0.00199                             | Once per package on your **first run only** |
| **Actor start**       | $0.005                               | Per run, whatever it finds                  |

Live prices are always the ones on this page's Pricing tab. A worked example: 25 packages watched hourly. The first run costs $0.005 + 25 x $0.00199 = about 5.5 cents. Every quiet run after that costs half a cent, and a busy month with 40 real releases costs roughly $4.40 including all 720 checks. New Apify accounts come with free monthly platform credits, so the first runs cost nothing out of pocket.

#### Why an alert costs more than a row

Because the value is in what is *not* sent. Anything can print a list of versions; the work here is remembering across runs so that a row appearing in your inbox means something changed. You pay for the signal, not for the polling.

### Input reference

| Field                | Type     | Default                            | What it does                                                                |
| -------------------- | -------- | ---------------------------------- | --------------------------------------------------------------------------- |
| `packages`           | string\[] | three sample packages              | What to watch: `npm:name`, `pypi:name`, `github:owner/repo`, or a bare name |
| `onlyBreaking`       | boolean  | `false`                            | Alert only on releases flagged breaking                                     |
| `includePrereleases` | boolean  | `false`                            | Include alpha, beta and rc versions                                         |
| `includeNotes`       | boolean  | `true`                             | Include the full release-notes text where the source has one                |
| `maxPerPackage`      | integer  | `20`                               | Cap per package per run, so one nightly-build dependency cannot flood a run |
| `emitBaseline`       | boolean  | `true`                             | Push current versions on the first run                                      |
| `resetState`         | boolean  | `false`                            | Forget the memory and re-baseline                                           |
| `stateStoreName`     | string   | `dependency-release-monitor-state` | Which named store holds this monitor's memory                               |
| `maxItems`           | integer  | `500`                              | Stop after this many rows                                                   |

The package list is also accepted under `dependencies`, `deps`, `repos` or `libraries`, and a single comma-separated string works as well as a list - so an AI agent's first guess at the input tends to run.

### Scheduling and API use

Daily is right for most stacks; hourly is affordable because quiet runs are nearly free. Start a run over the API:

```bash
curl -X POST "https://api.apify.com/v2/acts/lowlanddata~dependency-release-monitor/runs?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"packages":["npm:zod","npm:express","pypi:django","github:apify/crawlee"],"onlyBreaking":true}'
```

Then fetch only the breaking ones from the dataset:

```bash
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?format=json&filter=isBreaking"
```

### Use it with AI agents (MCP)

Every tool here doubles as an MCP endpoint, so Claude, Cursor or your own agent can run it directly: [dependency-release-monitor/api/mcp](https://apify.com/lowlanddata/dependency-release-monitor/api/mcp). A prompt that works as-is:

```text
Using the dependency release monitor, check npm:zod, npm:hono and pypi:fastapi
for anything published in the last month, and tell me which upgrades look breaking.
```

### Is this legal, and what about personal data

Yes - and it is boring on purpose. The actor reads three public endpoints that exist to be read by package managers, at a handful of requests per run. It authenticates to nothing and needs no token.

The npm registry document carries maintainer names and email addresses, PyPI carries an author and author-email, and the GitHub feed carries the publishing account. **None of them are read.** The parser takes versions, dates, tags and notes; a test in the build feeds each source a record stuffed with fake names and addresses and fails if any of it survives to the output. So the rows are safe to store, forward and archive without a compliance conversation.

### Sources and honest coverage notes

- **npm** - `registry.npmjs.org`, the same document `npm install` reads. Complete version history with publication timestamps.
- **PyPI** - `pypi.org/pypi/<name>/json`. Yanked releases are skipped, since a yanked version is one you are being told not to install.
- **GitHub** - the repository's public releases feed. Repositories that tag without creating **releases** publish nothing to that feed, so a project using bare tags will look quiet. Private repositories are not accessible.
- Ecosystems not covered yet: crates.io, Packagist, Maven, Go modules, RubyGems. If you want one, [ask](mailto:contact@lowlanddata.com) - adding a registry is a small job.

### FAQ

**Does it open pull requests like Dependabot?** No, and deliberately. This is the notification half: it tells you what shipped, in one feed across three ecosystems, wherever you already read things. Nothing is written to your repository.

**Will an hourly schedule bankrupt me?** No. A run that finds nothing charges only the actor start, so hourly costs about 12 cents a month plus whatever real releases happen.

**Can I watch a package I do not depend on?** Yes - competitors' SDKs, a framework you are evaluating, anything with a public registry entry.

**Why is my GitHub repository silent?** It probably tags without publishing releases. Watch the package on npm or PyPI instead if it publishes there.

**Can I get only major versions?** `onlyBreaking: true` gives majors, `0.x` minors and anything whose notes announce a break.

**Where does my package list live?** In a key-value store on your own Apify account. I never see it.

### More tools from Lowland Data

Same house rules everywhere: clean schemas, public sources, no personal data in the output.

| Tool                                                                            | What it does                                                       |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| [SSL & Domain Expiry Monitor](https://apify.com/lowlanddata/ssl-domain-monitor) | Certificate and domain-registration countdowns for a list of hosts |
| [US Federal Grants Monitor](https://apify.com/lowlanddata/grants-gov-monitor)   | New federal funding opportunities matching your profile            |
| [Company Jobs Scraper](https://apify.com/lowlanddata/company-jobs-scraper)      | Every open role from any Greenhouse or Lever board                 |

Full catalogue: [lowlanddata.com/catalogue](https://lowlanddata.com/catalogue/).

### Support

Something wrong, a registry you need, or a release the monitor missed? Open an issue on the **Issues** tab with the run ID, or write to <contact@lowlanddata.com>. Reports get read the same day.

# Actor input Schema

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

One per line: npm:zod, pypi:requests, github:apify/crawlee. A bare name means npm; owner/repo means GitHub. Leave empty to use the sample list.

## `onlyBreaking` (type: `boolean`):

Major bumps, 0.x minor bumps, and releases whose notes announce a breaking change.

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

Alpha, beta and release-candidate versions. Off by default.

## `includeNotes` (type: `boolean`):

Full release notes text where the source publishes it (GitHub releases).

## `maxPerPackage` (type: `integer`):

Caps a package that publishes nightly builds so it cannot flood one run.

## `emitBaseline` (type: `boolean`):

The first run records what is already published and pushes each package's current version, so you can see what is being watched.

## `resetState` (type: `boolean`):

Forget everything seen before and start a fresh baseline.

## `stateStoreName` (type: `string`):

Named key-value store holding what this monitor has already reported.

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

Stop after this many rows.

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

Registry APIs are public; the default datacenter proxy is plenty.

## Actor input object example

```json
{
  "packages": [
    "npm:zod",
    "pypi:requests",
    "github:apify/crawlee"
  ],
  "onlyBreaking": false,
  "includePrereleases": false,
  "includeNotes": true,
  "maxPerPackage": 20,
  "emitBaseline": true,
  "resetState": false,
  "stateStoreName": "dependency-release-monitor-state",
  "maxItems": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per release: version, date, semver bump, breaking flag and notes. First run: the current version of each package; afterwards: only releases published since.

# 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": [
        "npm:zod",
        "pypi:requests",
        "github:apify/crawlee"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lowlanddata/dependency-release-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": [
        "npm:zod",
        "pypi:requests",
        "github:apify/crawlee",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lowlanddata/dependency-release-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": [
    "npm:zod",
    "pypi:requests",
    "github:apify/crawlee"
  ]
}' |
apify call lowlanddata/dependency-release-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lowlanddata/dependency-release-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/7gnNqeZIOasEjxwgI/builds/dzagLLobKcZ141sPG/openapi.json
