Harbor Registry Extractor
Pricing
from $0.35 / 1,000 records
Harbor Registry Extractor
Point at any self-hosted Harbor container registry and extract its public projects, repositories, image artifacts (with vulnerability-scan severity) and instance fingerprint via the open /api/v2.0 REST API. One actor, any Harbor — no per-host scraper.
Pricing
from $0.35 / 1,000 records
Rating
0.0
(0)
Developer
Datamule
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
A GENERIC "point at any Harbor container registry" Apify actor — the supply-chain /
SBOM sibling of the netdata / grafana / gatus / uptime-kuma self-hosted-infra runners,
over the container-registry population. Harbor (goharbor/harbor, a CNCF graduated
project) is THE on-prem DockerHub / Quay alternative — it runs on Kubernetes clusters
across enterprise, research and government. Public projects are anonymous-browsable by
design and /systeminfo + /health are unauthenticated on every install — so ONE actor
spans every reachable instance, no per-host scraper and no host enumeration.
Input
| Field | Mode | Meaning |
|---|---|---|
sources (required) | all | One or more Harbor base URLs — https://registry.cern.ch, https://demo.goharbor.io, or any self-hosted install. The /api/v2.0/... path is appended for you. |
mode | — | projects (default), repositories, artifacts, or discovery. |
project | repositories, artifacts | The Harbor project name to drill into (e.g. acc). Required for those two modes. |
repository | artifacts | A single repo name relative to the project. Empty = walk every repo in the project. |
q | projects, repositories | Harbor-native fuzzy filter (?q=), e.g. name=~acc. |
name | projects | Exact project-name filter (?name=). |
page / pageSize | all | Harbor-native paging (1-based page; page size 1–100). |
maxRecords | all | Global cap across every source (one row = one billable event). |
bearer | all | Optional bearer token / robot account for a private instance (Authorization: Bearer ***). Never logged. |
extraHeaders | all | Optional extra request headers (JSON). |
Modes
- projects (default) — paginated
/api/v2.0/projects→ one flat row per public project:projectId,name,ownerName,repoCount,public,autoScan,severity,creationTime,updateTime, plus a lossless_raw. An instance that gates the project list (private-only) but leaves/systeminfoopen falls back to a single discovery fingerprint row instead of nothing. - repositories —
/projects/{project}/repositories→ one row per repo:name,artifactCount,pullCount,creationTime,updateTime. - artifacts —
/projects/{project}/repositories/{repo}/artifacts→ one row per image:digest,tags[],size,pushTime,pullTime,architecture/os, and the vulnerability-scan rollup (scanSeverity,scanTotal,scanFixable). Give arepositoryto walk one repo, or omit it to walk every repo in the project (bounded bymaxRecords). - discovery —
/systeminfo+/health(+/api/version) → one fingerprint row per instance:_harborVersion,apiVersion,authMode,selfRegistration,oidcProviderName,health,componentCount,unhealthyComponents. A cheap way to fingerprint many instances at once.
Behaviour
- The parse is the moat. Harbor's project / repo / artifact shapes drift across
v2.0 → v2.11 and installs populate different optional fields —
harbor_versionis documented but is not returned anonymously on many installs (CERN and the vendor demo both omit it);auto_sbom_generationappears on newer installs only. So every field is read by key presence (dict.get) and Harbor's nestedmetadatastring-bools ("public": "true") are coerced to real booleans. A row missing an optional field yieldsnull, never a crash. Every original object is preserved verbatim in_raw. - Many instances leave
/systeminfo+/healthopen but gate the project list to logged-in users. In projects mode such a source still yields a discovery fallback row rather than being dropped. - A source that is auth-gated on everything, unreachable / DNS-failed, timing out, or returns a non-Harbor body is a clean skip-with-warning, and the batch continues. A run where every source was skipped fails fast (exit 91) so nothing broken ships. A single valid instance with 0 public projects yields 0 records and a clean exit 0.
- Private instances are supported via an optional
bearertoken / robot account — never required for anonymous instances, never logged.
Output
One flat, fully-nullable row per record (project / repository / artifact / instance),
plus a lossless _raw with the original object. Example (projects mode, registry.cern.ch):
{"_type": "project","_source": "https://registry.cern.ch","_mode": "projects","_software": "harbor","projectId": 1009,"name": "acc","ownerName": "kbenothm","repoCount": 987,"public": true,"autoScan": true,"severity": "critical","creationTime": "2021-05-18T14:04:05.724Z","updateTime": "2021-05-18T14:04:05.724Z"}
Pricing
Pay-per-event: one record charge per emitted row.
Example input
{"sources": ["https://registry.cern.ch"],"mode": "projects","maxRecords": 100}