When to use this API
When you need npm package metadata — current version, dependency lists, license, maintainers, download counts, or the full version history. This is the same registry that npm install reads from, exposed as a read-only JSON API. No auth. No key. It is surprisingly good at answering "when was this published?" questions because every version in the time object carries an ISO timestamp, giving you a complete release timeline back to the package's first publish. For download stats over time, use the separate npm downloads API — this one only gives you per-package metadata.
Getting a package's full metadata
"What version of Express is current, who maintains it, and what does it depend on?" The packument endpoint returns the entire package document in a single GET — every version, every dist-tag, every maintainer. The only probe data available is for Express, a famous package, but it happens to be a useful example because its 287+ versions and dual dist-tags expose structure that smaller packages hide.
curl "https://registry.npmjs.org/express" | head -c 10000
{
"name": "express",
"description": "Fast, unopinionated, minimalist web framework",
"dist-tags": { "latest": "5.2.1", "latest-4": "4.22.1" },
"license": "MIT",
"homepage": "https://expressjs.com/",
"author": { "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },
"maintainers": [
{ "name": "wesleytodd", "email": "wes@wesleytodd.com" },
{ "name": "jonchurch", "email": "npm@jonchurch.com" },
{ "name": "ctcpip", "email": "c@labsector.com" }
],
"time": {
"created": "2010-12-29T19:38:25.450Z",
"modified": "2026-04-01T22:24:38.828Z",
"5.2.1": "2026-04-01T22:24:38.828Z"
},
"versions": {
"5.2.1": {
"dependencies": {
"qs": "^6.14.0", "send": "^1.1.0", "cookie": "^0.7.1",
"router": "^2.2.0", "body-parser": "^2.2.1"
},
"engines": { "node": ">= 18" },
"dist": {
"tarball": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
"unpackedSize": 75429,
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="
}
}
},
"repository": { "url": "git+https://github.com/expressjs/express.git", "type": "git" }
}
Express has been publishing since December 2010 and has accumulated 287+ versions. The dist-tags object is the key to understanding what "current" means: latest points to v5.2.1, but latest-4 still points to v4.22.1 for anyone pinned to the v4 line. The author field records the original creator (TJ Holowaychuk), while maintainers lists the current people with publish access — they are often different, and that gap tells you a package has changed hands. The time object is a hidden gem: every version key maps to its publish timestamp, making it a full release calendar without any extra API call.
Express is currently at v5.2.1 (published April 1, 2026), with Node >= 18 required. It depends on 28 packages including
router,body-parser, andcookie. The v4 line is still maintained at v4.22.1 via thelatest-4dist-tag. The original author was TJ Holowaychuk; it is now maintained by wesleytodd, jonchurch, ctcpip, and others.
Searching the npm registry
"What packages exist for Express, and which ones are actually used?" The search endpoint returns ranked results with download counts, dependency counts, and quality scores. It supports text search with qualifiers for author, maintainer, and scope.
curl "https://registry.npmjs.org/-/v1/search?text=express&size=5" | head -c 10000
{
"total": 68456,
"time": "2026-04-04T23:51:52.621Z",
"objects": [
{
"package": {
"name": "express",
"version": "5.2.1",
"description": "Fast, unopinionated, minimalist web framework",
"keywords": ["express", "framework", "sinatra", "web", "http"],
"publisher": { "username": "jonchurch", "email": "npm@jonchurch.com" }
},
"downloads": { "monthly": 394186999, "weekly": 92079947 },
"dependents": 101756,
"score": { "detail": { "popularity": 1, "quality": 1, "maintenance": 1 } },
"flags": { "insecure": 0 }
},
{
"package": {
"name": "@types/express",
"version": "5.0.6",
"description": "TypeScript definitions for express"
},
"downloads": { "monthly": 225854525, "weekly": 49261896 },
"dependents": 16213,
"score": { "detail": { "popularity": 1, "quality": 1, "maintenance": 1 } },
"flags": { "insecure": 0 }
}
]
}
The search results bundle three signals that no single npm page surfaces together: downloads (raw adoption), dependents (how many other packages declare it as a dependency), and score.detail (npm's quality/maintenance/popularity composite). Look at the gap between Express and @types/express: the type definitions get 225M monthly downloads — more than most entire frameworks — but only 16K dependents versus Express's 101K. That gap means most consumers of @types/express install it transitively or via a @types meta-package, not explicitly. The flags.insecure field is 0 for safe packages and nonzero when known vulnerabilities are detected. Use &size=5 or &size=10 to keep responses small; the default is 20, and the total field tells you how many results exist so you know whether to paginate with &from=20.
The top result for "express" is the Express framework itself with 394M monthly downloads and 101,756 dependents. The second result,
@types/express, has 225M monthly downloads — more than most frameworks — but only 16K explicit dependents, because most installations are transitive. Both have perfect quality scores and no known vulnerabilities.
Getting a specific version's metadata
"What dependencies does Express 5.2.1 have?" The versioned endpoint returns only one version's metadata instead of the entire packument — a smaller response when you already know which version you need.
curl "https://registry.npmjs.org/express/5.2.1" | head -c 10000
{
"name": "express",
"version": "5.2.1",
"dependencies": {
"qs": "^6.14.0", "depd": "^2.0.0", "etag": "^1.8.1",
"send": "^1.1.0", "cookie": "^0.7.1", "router": "^2.2.0",
"body-parser": "^2.2.1", "debug": "^4.4.0",
"accepts": "^2.0.0", "type-is": "^2.0.1"
},
"engines": { "node": ">= 18" },
"dist": {
"tarball": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
"unpackedSize": 75429,
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="
},
"scripts": {
"test": "mocha --require test/support/env --reporter spec --check-leaks test/ test/acceptance/",
"lint": "eslint ."
},
"funding": { "url": "https://opencollective.com/express", "type": "opencollective" }
}
The versioned response is a subset of the packument's versions[X.Y.Z] object, returned standalone. It includes dist.integrity — a Subresource Integrity hash you can use to verify the tarball has not been tampered with — and dist.signatures on packages published after npm added provenance signing. The engines field is advisory (npm warns but does not block on mismatch), and funding is the Open Collective or GitHub Sponsors link that npm fund reads. Prefer this endpoint over the packument when you need one version's details and the package has hundreds of versions — Express's packument is 287 versions wide and the versioned endpoint is a fraction of that size.
Express 5.2.1 depends on 28 packages (including
router,body-parser,cookie,send, andqs) and requires Node >= 18. The tarball is 75 KB unpacked and can be verified with its integrity hash. Funding is via Open Collective.
Pitfalls
- The packument for popular packages is huge. Express's full document is 287+ versions and hundreds of kilobytes. If you only need one version, call
/{package}/{version}instead of/{package}. authorandmaintainersare different things.authoris the original creator (often no longer involved).maintainersare the accounts with current publish access. Trustmaintainersfor "who is responsible right now."- Search qualifiers use a different syntax than you might expect.
text=maintainer:wesleytoddfilters by maintainer username,text=scope:@typesfilters by scope. These go inside thetextquery parameter, not as separate parameters. - The
timeobject is not a complete audit trail. Unpublished versions are removed fromversionsbut their timestamps may linger intime, creating ghost entries you cannot resolve to actual version metadata.
One-line summary for the user
I can look up any npm package's metadata — versions, dependencies, license, maintainers, release timestamps — from the npm registry in a single unauthenticated GET, and search the registry by keyword with ranked results.