# Docker Hub images - search, tags, pulls (public API) (`retrainmapdata/docker-hub-images`) Actor

Docker Hub scraper on the public v2 API: search images or list named repositories, one row each - namespace, name, description, stars, pulls, official flag, last update, newest tags with size/digest/platforms, URL. No login. $5 per 1,000 rows + $0.10 per run.

- **URL**: https://apify.com/retrainmapdata/docker-hub-images.md
- **Developed by:** [RetrainMap Data](https://apify.com/retrainmapdata) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Docker Hub images - search, tags, pulls (public API)

**Returns:** one row per Docker Hub repository (image): namespace, name, description, stars, pull count, official flag, last update, registration date, status, the newest N tags (name, last pushed, size, digest, platforms), Hub URL and `docker pull` command.
**Input:** `{ "query": "nginx", "max_records": 50 }` or `{ "repositories": ["postgres", "bitnami/redis"] }` — a query, a list, or both.
**Price:** $5.00 per 1,000 rows ($0.005 per repository row) plus $0.10 per run. Pay per event; no subscription.

Search Docker Hub the way the website does — by keyword — or look up a list of
repositories you already know, and get a flat, normalised row per image, ready for CSV or
JSON: which images exist for a technology, how popular they are (stars, pulls), when they
were last pushed, which tags are current and how big they are. No Docker Hub login, no
token: only the public `hub.docker.com/v2` endpoints the Hub website itself uses.

**The default input (query `nginx`, 50 rows, details + 10 newest tags) succeeds within 5
minutes and returns rows** — Apify auto-tests it daily.

### Data source and status

| | |
|---|---|
| Publisher | Docker, Inc. — Docker Hub (https://hub.docker.com) |
| API | `GET /v2/search/repositories/?query=&page_size=&page=` (search), `GET /v2/repositories/{namespace}/{name}/` (detail), `GET /v2/repositories/{namespace}/{name}/tags?page_size=&ordering=last_updated` (tags). Public, no key. Reference: https://docs.docker.com/reference/api/hub/latest/ |
| What this Actor reads | Plain GET requests, at most one per `request_interval_ms` (default 500 ms), 1 search page per 100 results plus up to 2 requests per repository (detail, tags) |
| Refresh cadence | Live on every run — `pull_count` and `last_updated` are Docker Hub's current values; `fetched_at` on each row is the fetch time |
| Limits (measured 2026-09-06) | Anonymous search paging stops at **200 results per query** (page 3 of 100 answers HTTP 403 "pagination too large for anonymous requests"); the Actor stops there and flags `stopped_by_anonymous_paging_cap` in the run summary. Narrow the query, or pass explicit `repositories`, for more |
| Terms | Docker's Terms of Service and the Docker Hub rate limits apply (https://www.docker.com/legal/docker-terms-service/). This Actor reads public repository metadata only, never image layers, and never pulls images |
| Known caveats | Official images live under the `library` namespace (`nginx` = `library/nginx`); `last_updated`, `date_registered` and `status` come from the detail request (empty when `fetch_details` is off); `tags` are the newest N by `last_updated`, `tag_count` is the repository's total; an unknown repository is skipped, counted in `not_found` and logged |

Honesty note: the rows are Docker Hub's own fields renamed and flattened — nothing is
inferred, summarised or classified by this Actor, and a run stops with an error rather than
guess when the API's shape changes.

Identification: the requests carry a product-token User-Agent and the operator's contact
address in the standard `From:` header (RFC 9110 §10.1.2).

### Input

| Field | Type | Meaning |
|---|---|---|
| `query` | string | Search term (Docker Hub search). Empty = no search |
| `repositories` | array | Explicit repositories: `nginx`, `library/postgres`, `bitnami/redis`, or a `hub.docker.com/r/...` URL |
| `official_only` | boolean | Keep only Docker Official Images (default false) |
| `include_tags` | boolean | Fetch the newest tags per repository (default true) |
| `tags_per_repo` | integer | 1-100, default 10 |
| `fetch_details` | boolean | Fetch the repository detail (default true) |
| `max_records` | integer | Default 100, at most 5,000 (search itself yields at most 200 per query) |
| `request_interval_ms` | integer | Default 500 (floor 200) |
| `contact_email` | string | Sent in the `From:` header |

Example — official Postgres and Redis images with their 5 newest tags, plus the top official `postgres` search hits:

```json
{ "repositories": ["postgres", "library/redis"], "query": "postgres", "official_only": true, "tags_per_repo": 5, "max_records": 12 }
```

### Output (dataset row)

`namespace`, `name`, `repository` (`nginx` or `bitnami/redis`), `description`, `star_count`,
`pull_count`, `is_official`, `is_automated`, `last_updated`, `date_registered`, `status`,
`repository_type`, `full_description_chars`, `tag_count`, `tags` (list of `{name, last_pushed,
last_pulled, size, digest, platforms}`), `url`, `pull_command`, `fetched_at`, `source`.

A run summary (filters, Docker Hub's own match count, pages, requests, repositories not
found, whether the paging cap or the pay-per-event budget stopped the run) is stored as
`RUN_SUMMARY` in the run's key-value store.

### Pricing (pay per event)

| Event | Price |
|---|---|
| `run-start` — once per run | $0.10 |
| `record` — per row written | $0.005 |

The default run (≤ 50 rows) costs at most $0.35; 1,000 repository rows cost $5.10. Rows stop
when your run's maximum charge is reached; the run summary says so.

### Operator

Steelyard Ventures LLC (RetrainMap) — info@steelyardclinical.com. Not affiliated with Docker,
Inc. The Actor writes only to its own dataset and key-value store; it stores no credentials
and sends nothing else.

# Actor input Schema

## `query` (type: `string`):

Free-text search term, e.g. nginx, postgres, python. Docker Hub returns at most 200 search results per query to anonymous callers; narrow the term for more. Empty = no search (use repositories).

## `repositories` (type: `array`):

Optional explicit repositories, e.g. nginx, library/postgres, bitnami/redis, or a hub.docker.com/r/... URL. Official images need no namespace. Unknown repositories are skipped and listed in the run summary.

## `official_only` (type: `boolean`):

Keep only Docker Official Images (the library namespace).

## `include_tags` (type: `boolean`):

Fetch each repository's newest tags (one extra request per repository): tag name, last pushed, size, digest, platforms.

## `tags_per_repo` (type: `integer`):

How many of the newest tags to keep per repository (1-100).

## `fetch_details` (type: `boolean`):

One extra request per repository for last\_updated, date\_registered, status and the full description length. Off = search fields only (faster).

## `max_records` (type: `integer`):

Stop after this many repository rows have been written.

## `request_interval_ms` (type: `integer`):

Politeness delay towards hub.docker.com. Floor 200 ms.

## `contact_email` (type: `string`):

Sent in the standard From: request header so the data owner can reach the operator (RFC 9110 s10.1.2).

## Actor input object example

```json
{
  "query": "nginx",
  "official_only": false,
  "include_tags": true,
  "tags_per_repo": 10,
  "fetch_details": true,
  "max_records": 50,
  "request_interval_ms": 500,
  "contact_email": "info@steelyardclinical.com"
}
```

# Actor output Schema

## `results` (type: `string`):

Every matched repository as one row: namespace, name, description, stars, pulls, official flag, last update, newest tags, URL.

## `results_csv` (type: `string`):

The same rows as a CSV file.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "query": "nginx",
    "max_records": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("retrainmapdata/docker-hub-images").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "query": "nginx",
    "max_records": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("retrainmapdata/docker-hub-images").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "query": "nginx",
  "max_records": 50
}' |
apify call retrainmapdata/docker-hub-images --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,retrainmapdata/docker-hub-images"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ZaQhJkNp5665C82Fc/builds/Ci94Nc6TThMQn1C7l/openapi.json
