Required Reading
~5 min

API Reference

Every endpoint that powers npmscan.com — public, unauthenticated, and free to call directly.

Public & unauthenticated
No API key, no signup, no CORS restrictions. Base URL is https://npmscan.com/api— it's the same read-only data that powers the website. Please be a good citizen: cache results client-side and avoid tight polling loops.
Building an AI agent instead?
Skip raw HTTP — npmscan also runs a public MCP server at https://npmscan.com/api/mcpwith six ready-made tools for package, version, and vulnerability lookups. Same data, no API key, one line of config. There's also a plaintext /llms.txt if your agent just wants a map of the site.
Rate limited
Each endpoint group below (npm registry, vulnerabilities, advisories, feeds, GitHub) is capped at 30 requests / 60s per IP. Going over returns 429 Too Many Requests with a Retry-After header telling you how many seconds to wait. /api/mcp has its own separate limit at the same rate. Cache responses client-side to stay well under it.

NPM Registry

Search the npm registry and pull package or version metadata — mirrored with a registry fallback for reliability.

GET/api/npm/package/:name

Full package metadata — dist-tags, every published version, maintainers, license.

Query / route params
NameTypeRequiredDescription
namestringrequirednpm package name (URL-encode scoped names, e.g. %40scope%2Fname). Passed as a path segment.
Request
curl "https://npmscan.com/api/npm/package/lodash"
Response200 OK
{
  "name": "lodash",
  "dist-tags": { "latest": "4.17.21" },
  "versions": {
    "4.17.21": {
      "name": "lodash",
      "version": "4.17.21",
      "license": "MIT",
      "dist": {
        "shasum": "679591c564c3bffaae8454cf0b3df370c3d6911",
        "tarball": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
        "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4..."
      }
    }
    /* ...every other published version */
  },
  "time": {
    "created": "2012-04-23T16:37:11.912Z",
    "modified": "2024-05-01T10:02:00.000Z",
    "4.17.21": "2021-02-20T15:42:16.552Z"
  },
  "maintainers": [{ "name": "jdalton", "email": "john.david.dalton@gmail.com" }],
  "license": "MIT",
  "repository": { "type": "git", "url": "git+https://github.com/lodash/lodash.git" }
}
Error — unknown package404 Not Found
{ "error": "Package not found" }
  • Response is the full npm registry packument — can be large for packages with many published versions.
GET/api/npm/package/:name/version/:version

Manifest for one exact version — the fastest way to check install scripts and dependencies before installing.

Query / route params
NameTypeRequiredDescription
namestringrequirednpm package name.
versionstringrequiredExact version or dist-tag (e.g. 1.4.2 or latest).
Request
curl "https://npmscan.com/api/npm/package/example-package/version/1.4.2"
Response200 OK
{
  "name": "example-package",
  "version": "1.4.2",
  "description": "Example package for documentation purposes.",
  "license": "MIT",
  "scripts": {
    "preinstall": "node ./scripts/check-platform.js",
    "postinstall": "node ./scripts/postinstall.js",
    "test": "jest"
  },
  "dependencies": { "chalk": "^5.3.0" },
  "dist": {
    "integrity": "sha512-abc123...",
    "shasum": "9c1a4d2f...",
    "tarball": "https://registry.npmjs.org/example-package/-/example-package-1.4.2.tgz",
    "fileCount": 12,
    "unpackedSize": 48213
  },
  "maintainers": [{ "name": "maintainer-handle", "email": "maintainer@example.com" }]
}
Error — unknown version404 Not Found
{ "error": "Package version not found" }
  • `scripts.preinstall` / `scripts.postinstall` are what actually runs on install — check them here rather than trusting the README.

Vulnerability Intelligence

Proxies to OSV.dev, scoped to the npm ecosystem by default. Use the batch endpoint to scan an entire package.json or lockfile in one request — it's the same call npmscan.com/analyze makes under the hood.

POST/api/osv/query

Known vulnerabilities affecting a single package, optionally scoped to one version.

Body params (application/json)
NameTypeRequiredDescription
namestringrequirednpm package name.
versionstringoptionalNarrow results to a specific version. Omit for all known advisories.
ecosystemstringoptionalDefaults to "npm".
Request
curl -X POST https://npmscan.com/api/osv/query \
  -H "Content-Type: application/json" \
  -d '{"name":"lodash","version":"4.17.15"}'
Response200 OK
{
  "vulns": [
    {
      "id": "GHSA-35jh-r3h4-6jhm",
      "summary": "Prototype Pollution in lodash",
      "aliases": ["CVE-2020-8203"],
      "modified": "2022-01-27T00:00:00Z",
      "published": "2020-07-15T00:00:00Z",
      "database_specific": { "severity": "HIGH" },
      "affected": [
        {
          "package": { "name": "lodash", "ecosystem": "npm" },
          "ranges": [
            { "type": "ECOSYSTEM", "events": [{ "introduced": "0" }, { "fixed": "4.17.19" }] }
          ]
        }
      ],
      "references": [
        { "type": "ADVISORY", "url": "https://github.com/advisories/GHSA-35jh-r3h4-6jhm" }
      ]
    }
  ]
}
  • `vulns` is empty (not omitted) when the package has no known advisories for the given version.
  • Unlike the batch endpoint below, `ecosystem` isn't restricted to npm — this passes straight through to OSV.dev, so PyPI, Go, crates.io, Maven, RubyGems, and any other OSV-supported ecosystem work too.
POST/api/osv/batch

Known vulnerabilities for up to 100 packages in one call — built for scanning a whole package.json.

Body params (application/json)
NameTypeRequiredDescription
packagesArray<{ name, version? }>requiredUp to 100 items. `version` is optional per item.
Request
curl -X POST https://npmscan.com/api/osv/batch \
  -H "Content-Type: application/json" \
  -d '{"packages":[{"name":"lodash","version":"4.17.15"},{"name":"minimist","version":"1.2.0"}]}'
Response200 OK
{
  "results": [
    { "vulns": [{ "id": "GHSA-35jh-r3h4-6jhm", "summary": "Prototype Pollution in lodash" }] },
    { "vulns": [{ "id": "GHSA-vh95-rmgr-6w4m", "summary": "Prototype Pollution in minimist" }] }
  ]
}
Error — batch too large400 Bad Request
{ "error": "Packages array must contain at most 100 items" }
  • `results[i]` corresponds positionally to `packages[i]` you sent — same order, one entry per package.
  • This is exactly what powers the batch scan on npmscan.com/analyze: parse your package.json or package-lock.json (v1–v3) into a { name, version } list for every dependency, POST it here, then optionally call GET /api/npm/package/:name per package to flag outdated versions. Paste the file directly into /analyze for the full UI with that enrichment built in.

Security Advisories

Reviewed GitHub Security Advisories for the npm ecosystem — useful for a "what shipped this week" feed or as a fallback when OSV.dev hasn't ingested a just-published advisory yet.

GET/api/advisories/latest

Latest reviewed npm advisories, newest first.

Query / route params
NameTypeRequiredDescription
pagenumberoptionalPage number, 30 per page. Defaults to 1.
severitystringoptionalFilter: low, medium, high, critical, or all.
Request
curl "https://npmscan.com/api/advisories/latest?severity=critical&page=1"
Response200 OK
{
  "advisories": [
    {
      "id": "GHSA-xxxx-xxxx-xxxx",
      "cve": "CVE-2024-00000",
      "ghsaUrl": "https://github.com/advisories/GHSA-xxxx-xxxx-xxxx",
      "summary": "Remote code execution via crafted input",
      "severity": "critical",
      "publishedAt": "2024-05-01T00:00:00Z",
      "updatedAt": "2024-05-02T00:00:00Z",
      "packages": [
        { "name": "example-package", "affectedRange": "< 2.0.1", "patchedVersion": "2.0.1" }
      ]
    }
  ]
}
  • Flattened and simplified from GitHub's advisory schema; scoped to `ecosystem=npm`, `type=reviewed`.
GET/api/advisories/:id

A single advisory by GHSA or CVE id, reshaped into OSV's vulnerability schema.

Query / route params
NameTypeRequiredDescription
idstringrequiredGHSA id (e.g. GHSA-xxxx-xxxx-xxxx) or CVE id.
Request
curl "https://npmscan.com/api/advisories/GHSA-xxxx-xxxx-xxxx"
Response200 OK
{
  "id": "GHSA-xxxx-xxxx-xxxx",
  "summary": "Remote code execution via crafted input",
  "details": "Full advisory description...",
  "aliases": ["CVE-2024-00000"],
  "modified": "2024-05-02T00:00:00Z",
  "published": "2024-05-01T00:00:00Z",
  "database_specific": { "severity": "CRITICAL", "cwe_ids": ["CWE-94"] },
  "severity": [{ "type": "CVSS_V3", "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" }],
  "affected": [
    {
      "package": { "name": "example-package", "ecosystem": "npm" },
      "ranges": [{ "type": "ECOSYSTEM", "events": [{ "introduced": "0" }, { "fixed": "2.0.1" }] }]
    }
  ],
  "references": [{ "type": "ADVISORY", "url": "https://github.com/advisories/GHSA-xxxx-xxxx-xxxx" }]
}
Error — unknown advisory404 Not Found
{ "error": "Advisory not found" }
  • Same response shape as OSV — GitHub publishes immediately, OSV.dev syncs on its own delayed schedule. Query /api/osv/query first and fall back to this for a specific id.

RSS Feeds

Live XML feeds for anyone who'd rather subscribe in a feed reader, Slack/Discord RSS bridge, or SIEM than poll a REST endpoint. These live off the site root, not under /api.

GET/latest-vulnerabilities/rss.xml

The 30 most recent reviewed npm advisories, newest first — the RSS version of the advisories feed above.

Request
curl "https://npmscan.com/latest-vulnerabilities/rss.xml"
Response200 OK — application/rss+xml
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>NPMSCan - Latest NPM Vulnerabilities</title>
  <link>https://npmscan.com/latest-vulnerabilities</link>
  <atom:link href="https://npmscan.com/latest-vulnerabilities/rss.xml" rel="self" type="application/rss+xml" />
  <description>Live feed of reviewed security advisories affecting the npm ecosystem (GitHub Advisory Database).</description>
  <ttl>60</ttl>
  <item>
    <title>GHSA-xxxx-xxxx-xxxx (CVE-2024-00000): Remote code execution via crafted input</title>
    <link>https://npmscan.com/vulnerability/GHSA-xxxx-xxxx-xxxx</link>
    <atom:link href="https://npmscan.com/vulnerability/GHSA-xxxx-xxxx-xxxx/rss.xml" rel="related" type="application/rss+xml" />
    <guid isPermaLink="false">GHSA-xxxx-xxxx-xxxx</guid>
    <pubDate>Wed, 01 May 2024 00:00:00 GMT</pubDate>
    <description>severity: critical | packages: example-package | rss: https://npmscan.com/vulnerability/GHSA-xxxx-xxxx-xxxx/rss.xml | source: https://github.com/advisories/GHSA-xxxx-xxxx-xxxx</description>
  </item>
</channel>
</rss>
  • `<ttl>60</ttl>` — feeds are effectively live; a reader polling once a minute won't miss anything.
  • Each item links to its own per-vulnerability feed via an atom:link rel="related", so a reader can offer "subscribe to just this CVE" from the main feed.
GET/vulnerability/:id/rss.xml

Single-item feed for one vulnerability — full OSV detail (affected ranges, references, CVSS scores) packed into the item description.

Query / route params
NameTypeRequiredDescription
idstringrequiredAn OSV-recognized id (GHSA ids reliably resolve). This hits OSV.dev's /v1/vulns/:id directly — unlike /api/advisories/:id, it doesn't go through GitHub's API or accept a bare CVE id.
Request
curl "https://npmscan.com/vulnerability/GHSA-35jh-r3h4-6jhm/rss.xml"
Response200 OK — application/rss+xml
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>NPMSCan - GHSA-35jh-r3h4-6jhm</title>
  <link>https://npmscan.com/vulnerability/GHSA-35jh-r3h4-6jhm</link>
  <ttl>1440</ttl>
  <item>
    <title>GHSA-35jh-r3h4-6jhm: Prototype Pollution in lodash</title>
    <link>https://npmscan.com/vulnerability/GHSA-35jh-r3h4-6jhm</link>
    <guid isPermaLink="false">GHSA-35jh-r3h4-6jhm</guid>
    <pubDate>Wed, 15 Jul 2020 00:00:00 GMT</pubDate>
    <category>high</category>
    <category>CVE-2020-8203</category>
    <description>id: GHSA-35jh-r3h4-6jhm
aliases: CVE-2020-8203
severity: high
published: 2020-07-15T00:00:00Z

affected:
- lodash (&lt; 4.17.19)

references:
- ADVISORY: https://github.com/advisories/GHSA-35jh-r3h4-6jhm</description>
  </item>
</channel>
</rss>

GitHub Repository Insights

Repo and maintainer signals pulled live from the GitHub API — stars, recent activity, and account age are useful trust signals alongside the package data above.

GET/api/github/stars

Stargazer count for a GitHub repository.

Query / route params
NameTypeRequiredDescription
urlstringrequiredFull GitHub repo URL, e.g. https://github.com/owner/repo.
Request
curl "https://npmscan.com/api/github/stars?url=https://github.com/lodash/lodash"
Response200 OK
{ "stars": 59892 }
Error — bad url400 Bad Request
{ "error": "Invalid GitHub repository URL" }
GET/api/github/repo/commits

Most recent commits on the repo's default branch.

Query / route params
NameTypeRequiredDescription
urlstringrequiredFull GitHub repo URL.
Request
curl "https://npmscan.com/api/github/repo/commits?url=https://github.com/lodash/lodash"
Response200 OK
{
  "commits": [
    {
      "sha": "a1b2c3d",
      "html_url": "https://github.com/owner/repo/commit/a1b2c3d",
      "message": "Fix regression in X",
      "author_login": "octocat",
      "author_name": "The Octocat",
      "author_avatar_url": "https://avatars.githubusercontent.com/u/1?v=4",
      "date": "2024-05-01T12:00:00Z"
    }
  ]
}
  • Last 10 commits.
GET/api/github/repo/contributors

Top contributors by commit count.

Query / route params
NameTypeRequiredDescription
urlstringrequiredFull GitHub repo URL.
Request
curl "https://npmscan.com/api/github/repo/contributors?url=https://github.com/lodash/lodash"
Response200 OK
{
  "contributors": [
    { "login": "octocat", "contributions": 482, "html_url": "https://github.com/octocat", "avatar_url": "https://avatars.githubusercontent.com/u/1?v=4" }
  ]
}
  • Top 10 by contribution count.
GET/api/github/repo/issues

Most recently updated issues (pull requests excluded).

Query / route params
NameTypeRequiredDescription
urlstringrequiredFull GitHub repo URL.
Request
curl "https://npmscan.com/api/github/repo/issues?url=https://github.com/lodash/lodash"
Response200 OK
{
  "issues": [
    {
      "number": 123,
      "title": "Memory leak on large payloads",
      "html_url": "https://github.com/owner/repo/issues/123",
      "state": "open",
      "labels": ["bug"],
      "author_login": "someuser",
      "author_avatar_url": "https://avatars.githubusercontent.com/u/2?v=4",
      "created_at": "2024-04-20T09:00:00Z",
      "updated_at": "2024-04-25T09:00:00Z"
    }
  ]
}
  • Up to 10 issues, sorted by most recently updated.
GET/api/github/user

Maintainer profile — account age, follower count, and other trust signals.

Query / route params
NameTypeRequiredDescription
usernamestringoptionalGitHub username. Provide this or `url`.
urlstringoptionalA repo URL to derive the owner from, e.g. https://github.com/owner/repo.
Request
curl "https://npmscan.com/api/github/user?username=sindresorhus"
Response200 OK
{
  "login": "sindresorhus",
  "name": "Sindre Sorhus",
  "html_url": "https://github.com/sindresorhus",
  "avatar_url": "https://avatars.githubusercontent.com/u/170270?v=4",
  "created_at": "2010-03-01T12:00:00Z",
  "public_repos": 1000,
  "followers": 50000,
  "following": 50,
  "blog": "https://sindresorhus.com",
  "twitter_username": "sindresorhus",
  "company": null,
  "location": "Oslo, Norway",
  "bio": null
}
  • A brand-new account with one popular package is a very different risk profile than a maintainer active for a decade — this endpoint is what powers that check.