# Docker Hub Images & Tags Scraper (`devilscrapes/docker-hub-images-scraper`) Actor

Give us repository names or a search term; we page through Docker Hub's public API, retry on rate limits, and return typed rows per image tag -- digest, size, architectures, and freshness. No auth token needed.

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

## Pricing

Pay per event

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

<p align="center">
  <img src=".actor/icon.svg" width="160" alt="Docker Hub Images & Tags Scraper icon" />
</p>

## Docker Hub Images & Tags Scraper

**$2.20 / 1 000 results** — pay only for results, no credit card to try.

### 🐳 What this scrapes

Docker Hub Images & Tags Scraper pulls structured rows from Docker Hub's
public `/v2` REST API — one row per repository + tag pair. Give it a list of
repository names (`nginx`, `bitnami/redis`) or a free-text search term, and
it returns each tag's digest, size, supported architectures, and freshness
(`last_pushed` / `last_pulled`), plus a resolvable Docker Hub URL. No Docker
Hub account or auth token required.

### 🔥 Features

- **Repository or search input** — feed exact `namespace/name` repositories,
  or a search term we resolve to the top matching repositories first.
- **Full tag pagination** — we follow Docker Hub's `next` cursor across
  pages so you get every tag up to your configured cap, not just page one.
- **Per-tag architecture list** — deduplicated `amd64` / `arm64` / `arm`
  (and friends) for every tag, so you can filter multi-arch images without
  a second lookup.
- **Optional repository details** — opt in to one extra call per unique
  repository for star count, pull count, official-image flag, and a short
  description.
- **Fault-isolated batches** — one unknown or renamed repository in your
  list never stops the rest of the batch from completing.

### 🎯 Use cases

- **SBOM & supply-chain tooling** — build an inventory of image digests and
  architectures across your organization's repositories.
- **DevRel competitive intel** — track how often a vendor's official images
  are pushed and which architectures they support.
- **Security teams** — spot stale tags (old `last_pushed`) worth flagging
  for a rebuild, without hand-browsing the Hub UI.
- **Devtool vendors** — power a "search Docker Hub" feature in your own
  product without building pagination and rate-limit handling yourself.

### ⚙️ How to use it

1. Click **Try for free** on the Apify Store page (or **Start** in Console).
2. Enter one or more **Repositories** (e.g. `library/nginx`,
   `bitnami/redis`), or leave it empty and set a **Search query** instead.
3. Optionally raise **Max tags per repository** or turn on **Include
   repository details**.
4. Run the Actor. Rows land in the run's default dataset as they're found.
5. Export via the **Results (JSON)** / **Results (CSV)** links, or pull
   them over the API.

We rotate browser fingerprints and retry with exponential backoff on
`408` / `429` / `503` responses, honouring `Retry-After` when Docker Hub
sends it — you don't have to build any of that yourself.

### 📥 Input

| Field | Type | Default | Description |
|---|---|---|---|
| `repositories` | array of string | `[]` | Repository names, one per line. Bare names imply `library/name`. Wins over `search_query` when both are set. |
| `search_query` | string | null | `null` | Free-text search term, used only when `repositories` is empty. |
| `max_repositories` | integer | `10` | Search-mode fan-out cap (1-25). |
| `max_tags_per_repository` | integer | `25` | Per-repository tag cap (1-100). |
| `include_repository_details` | boolean | `false` | Fetch star/pull count, official flag, and description per unique repository. |
| `proxy_configuration` | object | `{"useApifyProxy": true}` | Standard Apify Proxy configuration. |

```json
{
  "repositories": ["library/nginx", "bitnami/redis"],
  "max_tags_per_repository": 5,
  "include_repository_details": false,
  "proxy_configuration": { "useApifyProxy": true }
}
```

### 📤 Output

| Field | Type | Description |
|---|---|---|
| `namespace` | string | Repository namespace (`library` for official images). |
| `repository_name` | string | Repository name component. |
| `tag` | string | Tag name. |
| `repository_url` | string | Resolvable Docker Hub URL for the repository. |
| `digest` | string | Tag manifest digest. |
| `tag_status` | string | Docker Hub tag status. |
| `full_size_bytes` | integer | Tag size in bytes. |
| `architectures` | array of string | Deduplicated supported architectures. |
| `media_type` | string | null | Tag manifest media type. |
| `last_pushed` / `last_pulled` | string | null | ISO-8601 freshness timestamps. |
| `star_count` / `pull_count` / `is_official` / `description` | mixed | null | Only populated with **Include repository details** on. |
| `scraped_at` | string | ISO-8601 UTC fetch timestamp. |

```json
{
  "namespace": "library",
  "repository_name": "nginx",
  "tag": "1.27.3",
  "repository_url": "https://hub.docker.com/_/nginx",
  "digest": "sha256:abc123...",
  "tag_status": "active",
  "full_size_bytes": 44271616,
  "architectures": ["amd64", "arm64", "arm"],
  "media_type": "application/vnd.docker.distribution.manifest.list.v2+json",
  "last_pushed": "2026-08-20T10:03:11Z",
  "last_pulled": "2026-09-01T06:55:02Z",
  "star_count": null,
  "pull_count": null,
  "is_official": null,
  "description": null,
  "scraped_at": "2026-09-01T07:00:00Z"
}
```

### 💰 Pricing

Pay-per-event. No subscription, no minimum spend.

| Event | Price | Trigger |
|---|---:|---|
| Actor start | $0.20 | Once per run (warm-up) |
| Result | $0.002 | Per repository+tag row written |

**Example**: 1,000 rows ≈ **$2.20**.

### 🚧 Limitations

- Public repositories only — private/authenticated Docker Hub content is
  out of scope for this Actor.
- Repository metadata is scoped to the short `description` field; the
  long-form `full_description` markdown is never fetched.
- Image *content* (layers, `docker pull`) is out of scope — this Actor
  returns metadata only.

### ❓ FAQ

**Does this need a Docker Hub account or token?**
No — it uses Docker Hub's public, unauthenticated `/v2` API.

**What happens if a repository doesn't exist?**
We skip it, log a warning, and keep processing the rest of your batch.

**What if my search term matches nothing?**
The run finishes successfully with zero rows and a status message naming
what was searched — you're not charged for rows that don't exist.

**Can I get every tag for a huge repository?**
Set **Max tags per repository** up to 100 per repository per run; we follow
Docker Hub's pagination cursor until that cap or the repository's real tag
count, whichever comes first.

### Your feedback

Found a bug, or need a field we don't scrape yet? Message us through the
Apify Store page — we read every note and ship fixes fast.

# Actor input Schema

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

Docker Hub repository names to scrape, one per line. Bare names (e.g. <code>nginx</code>) resolve to the official <code>library/nginx</code> repository; use <code>namespace/name</code> (e.g. <code>bitnami/redis</code>) otherwise. Takes precedence over <b>Search query</b> when both are set.

## `search_query` (type: `string`):

Free-text Docker Hub search term, used only when <b>Repositories</b> is empty. We resolve the top matches (see <b>Max repositories</b>) and fetch tags for each.

## `max_repositories` (type: `integer`):

Search-mode fan-out cap -- how many repositories to resolve from a search query before fetching tags. Ignored when <b>Repositories</b> is set.

## `max_tags_per_repository` (type: `integer`):

Stop paging one repository's tags after this many rows. Docker Hub caps a single page at 100 regardless of the value requested.

## `include_repository_details` (type: `boolean`):

Fetch one extra request per unique repository for star count, pull count, official flag, and short description. Off by default to keep egress low.

## `proxy_configuration` (type: `object`):

Apify Proxy spec. Docker Hub's public API has no anti-bot wall, but Apify Proxy still absorbs any per-IP throttling under concurrent runs.

## Actor input object example

```json
{
  "repositories": [
    "library/nginx",
    "bitnami/redis"
  ],
  "search_query": null,
  "max_repositories": 10,
  "max_tags_per_repository": 5,
  "include_repository_details": true,
  "proxy_configuration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "repositories": [
        "library/nginx",
        "bitnami/redis"
    ],
    "max_repositories": 10,
    "max_tags_per_repository": 5,
    "include_repository_details": true,
    "proxy_configuration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/docker-hub-images-scraper").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 = {
    "repositories": [
        "library/nginx",
        "bitnami/redis",
    ],
    "max_repositories": 10,
    "max_tags_per_repository": 5,
    "include_repository_details": True,
    "proxy_configuration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/docker-hub-images-scraper").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 '{
  "repositories": [
    "library/nginx",
    "bitnami/redis"
  ],
  "max_repositories": 10,
  "max_tags_per_repository": 5,
  "include_repository_details": true,
  "proxy_configuration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/docker-hub-images-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/ahcZedXhrwn45CNcf/builds/8p68Y0TpZJFQh3jKI/openapi.json
