Skip to content

Repology Lookup ​

The versions each nixpkgs channel carries for a package, and the newest version any repository Repology tracks has, read from Repology or from this service's own mirror of it.

Endpoint ​

GET /api/v1/nix/repology/:package

The path is under /nix/. An earlier edition of this page named /api/v1/repology/:package, which has never answered.

Path Parameters ​

ParameterTypeRequiredDescription
packagestringYesPackage name, drawn from letters, digits, ., -, _ and /.

nixpkgs versions its attribute names and Repology does not, so a miss on the exact name falls back to the unversioned project: openssl_3 to openssl, python3 to python. When that happens the response carries matchedName and exactNameMatch: false, because being told about python while believing you asked about python3 is a useful answer and a dangerous one. A bare trailing digit is only stripped for names on an explicit list: log4j2 is its own project rather than a version of log4j.

Response ​

json
{
  "success": true,
  "data": {
    "found": true,
    "package": "curl",
    "normalizedName": "curl",
    "versions": {
      "nixos-26.05": { "version": "8.22.0", "status": "newest", "vulnerable": false },
      "nixpkgs-unstable": { "version": "8.22.0", "status": "newest", "vulnerable": false },
      "nixos-25.11": { "version": "8.20.0", "status": "outdated", "vulnerable": false }
    },
    "newestVersion": "8.22.0",
    "newestRepo": "aerynos",
    "fromMirror": true,
    "repologyUrl": "https://repology.org/project/curl/versions"
  },
  "timestamp": "2026-09-28T01:02:54.539Z"
}

Response Fields ​

FieldTypeDescription
foundbooleanWhether Repology knows the project. false with success: true is a checked negative.
packagestringThe name asked for
normalizedNamestringThe name after nixpkgs-style normalisation
matchedNamestringPresent when the exact name missed and an unversioned project answered instead
exactNameMatchbooleanPresent with matchedName; false when the fallback was used
versionsobjectKeyed by Repology repository name: nixpkgs-unstable and each nixos-<series>
versions.<repo>.versionstringThe version that repository carries
versions.<repo>.statusstringRepology's status for it: newest, outdated, devel, unique, legacy
versions.<repo>.vulnerablebooleanRepology's own vulnerability flag for that version
newestVersionstring|nullThe newest version any tracked repository carries
newestRepostring|nullWhich repository carries it
fromMirrorbooleanTrue when the answer came from this service's copy of Repology rather than from Repology. Those are different claims about freshness.
repologyUrlstringThe project page on Repology

When Repology cannot be read ​

An upstream failure answers 200 with success: false, degraded: true and data.found: false, cached for five minutes so retries do not hammer Repology. found: false there means the lookup failed, not that Repology lacks the package; read success and degraded before found.

json
{
  "success": false,
  "degraded": true,
  "data": { "found": false, "package": "curl", "error": "Upstream service unavailable", "versions": {} },
  "timestamp": "2026-09-28T01:02:54.539Z"
}

A name with characters package names never carry answers 400.

Examples ​

bash
curl "https://api.vulnpatch.dev/api/v1/nix/repology/curl"
curl "https://api.vulnpatch.dev/api/v1/nix/repology/openssl"

Code Examples ​

javascript
async function checkPackageVersion(packageName) {
  const response = await fetch(
    `https://api.vulnpatch.dev/api/v1/nix/repology/${packageName}`
  );
  const body = await response.json();

  if (!body.success) {
    console.log(`Repology could not be read: ${body.data.error}`);
    return;
  }
  if (!body.data.found) {
    console.log(`Repology does not know ${packageName}`);
    return;
  }

  console.log(`Newest anywhere: ${body.data.newestVersion} (${body.data.newestRepo})`);
  const unstable = body.data.versions['nixpkgs-unstable'];
  if (unstable) {
    console.log(`nixpkgs-unstable: ${unstable.version} (${unstable.status})`);
  }
}
python
import requests

def check_package_version(package_name):
    response = requests.get(
        f'https://api.vulnpatch.dev/api/v1/nix/repology/{package_name}'
    )
    body = response.json()

    if not body['success']:
        print(f"Repology could not be read: {body['data']['error']}")
        return
    if not body['data']['found']:
        print(f"Repology does not know {package_name}")
        return

    data = body['data']
    print(f"Newest anywhere: {data['newestVersion']} ({data['newestRepo']})")
    unstable = data['versions'].get('nixpkgs-unstable')
    if unstable:
        print(f"nixpkgs-unstable: {unstable['version']} ({unstable['status']})")

Caching ​

Answers are cached for two hours; failures for five minutes. The X-Cache header says which you received.