Search npm packages by keyword
When the user wants to find npm packages by keyword — compare packages, check popularity, find middleware, or discover libraries for a task — reach for the npm registry search endpoint. Ranked results with downloads, quality scores, and vulnerability flags in one unauthenticated GET.
search-npm-packages-by-keyword
· v1
· updated 2026-04-16
When to use this skill
When the user wants to find npm packages by keyword — "what packages handle rate limiting?", "is there an Express middleware for CORS?", "show me popular HTTP clients" — this is the right call. The npm search endpoint returns ranked results with download counts, dependency counts, and quality scores, making it the fastest way to compare packages you've never heard of. For looking up a specific package you already know by name, use the packument endpoint directly. For one version's metadata, use the versioned endpoint.
Your best first call
curl "https://registry.npmjs.org/-/v1/search?text=express+middleware&size=5"
No auth. No key. The text parameter accepts freeform keywords and search qualifiers. Set size to 5 or 10 to keep responses small; the default is 20.
Key response fields:
total — total matching packages (tells you whether to paginate with &from=20)
objects[].package.name — package name
objects[].package.version — latest version
objects[].package.description — one-line summary
objects[].downloads.monthly — monthly download count, the strongest signal for "is this actually used?"
objects[].dependents — count of packages declaring it as a dependency
objects[].score.detail.popularity / .quality / .maintenance — each a float 0–1
objects[].flags.insecure — 0 means no known vulnerabilities; nonzero means issues detected
Fallbacks (when the best call isn't enough)
- Need full metadata for a specific package →
https://registry.npmjs.org/{package} returns the entire packument — every version, all dist-tags, maintainers, license, the full time object. Use when a search result is a starting point and you need dependencies or release history.
- Need one version's details →
https://registry.npmjs.org/{package}/{version} returns only that version's metadata — a fraction of the packument size. Use for packages with hundreds of versions where you only care about one.
- Search by maintainer or scope → add qualifiers inside the
text parameter: text=maintainer:wesleytodd or text=scope:@types. These qualifiers go inside text, not as separate query parameters.
Pitfalls
- Search qualifiers go inside
text, not as separate parameters. text=maintainer:wesleytodd is one query string value, not maintainer=wesleytodd. Getting this wrong returns unfiltered results with no error.
dependents and downloads tell different stories. @types/express gets 225M monthly downloads but only 16K dependents — most installations are transitive. Use dependents for "how many packages depend on this" and downloads for "how widely is this installed."
score.detail values are floats 0–1, not percentages. A quality of 0.9 is not "90%" — it is 0.9 on npm's internal scale. Do not multiply by 100 when presenting results.
- The default
size is 20. Always set size to 5 or 10 in a skill call. The total field tells you the full result count; paginate with &from= only if the user explicitly asks for more.
One-line summary for the user
I can search npm packages by keyword and return ranked results with download counts, quality scores, and vulnerability flags — no auth required.
SKILL.md source (frontmatter + body)
---
name: search-npm-packages-by-keyword
description: When the user wants to find npm packages by keyword — compare packages, check popularity, find middleware, or discover libraries for a task — reach for the npm registry search endpoint. Ranked results with downloads, quality scores, and vulnerability flags in one unauthenticated GET.
---
## When to use this skill
When the user wants to find npm packages by keyword — "what packages handle rate limiting?", "is there an Express middleware for CORS?", "show me popular HTTP clients" — this is the right call. The npm search endpoint returns ranked results with download counts, dependency counts, and quality scores, making it the fastest way to compare packages you've never heard of. For looking up a specific package you already know by name, use the packument endpoint directly. For one version's metadata, use the versioned endpoint.
## Your best first call
```bash
curl "https://registry.npmjs.org/-/v1/search?text=express+middleware&size=5"
```
No auth. No key. The `text` parameter accepts freeform keywords and search qualifiers. Set `size` to 5 or 10 to keep responses small; the default is 20.
Key response fields:
- `total` — total matching packages (tells you whether to paginate with `&from=20`)
- `objects[].package.name` — package name
- `objects[].package.version` — latest version
- `objects[].package.description` — one-line summary
- `objects[].downloads.monthly` — monthly download count, the strongest signal for "is this actually used?"
- `objects[].dependents` — count of packages declaring it as a dependency
- `objects[].score.detail.popularity` / `.quality` / `.maintenance` — each a float 0–1
- `objects[].flags.insecure` — 0 means no known vulnerabilities; nonzero means issues detected
## Fallbacks (when the best call isn't enough)
- **Need full metadata for a specific package** → `https://registry.npmjs.org/{package}` returns the entire packument — every version, all dist-tags, maintainers, license, the full `time` object. Use when a search result is a starting point and you need dependencies or release history.
- **Need one version's details** → `https://registry.npmjs.org/{package}/{version}` returns only that version's metadata — a fraction of the packument size. Use for packages with hundreds of versions where you only care about one.
- **Search by maintainer or scope** → add qualifiers inside the `text` parameter: `text=maintainer:wesleytodd` or `text=scope:@types`. These qualifiers go inside `text`, not as separate query parameters.
## Pitfalls
- **Search qualifiers go inside `text`, not as separate parameters.** `text=maintainer:wesleytodd` is one query string value, not `maintainer=wesleytodd`. Getting this wrong returns unfiltered results with no error.
- **`dependents` and `downloads` tell different stories.** `@types/express` gets 225M monthly downloads but only 16K dependents — most installations are transitive. Use `dependents` for "how many packages depend on this" and `downloads` for "how widely is this installed."
- **`score.detail` values are floats 0–1, not percentages.** A `quality` of 0.9 is not "90%" — it is 0.9 on npm's internal scale. Do not multiply by 100 when presenting results.
- **The default `size` is 20.** Always set `size` to 5 or 10 in a skill call. The `total` field tells you the full result count; paginate with `&from=` only if the user explicitly asks for more.
## One-line summary for the user
I can search npm packages by keyword and return ranked results with download counts, quality scores, and vulnerability flags — no auth required.