# Quay.io Container Tags Scraper (`acquistion-automation/quay-io-tags-scraper`) Actor

Scrapes Quay.io container tags by repository slug and returns each tag as a flat row with name, manifest digest, size, and last modified date.

- **URL**: https://apify.com/acquistion-automation/quay-io-tags-scraper.md
- **Developed by:** [Acquisition Automation Co.](https://apify.com/acquistion-automation) (community)
- **Categories:** Developer tools, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

![Acquisition Automation Co. Search less. Close more.](https://api.apify.com/v2/key-value-stores/AOdPHdOpeDpzEPS5f/records/banner.jpg)

## 📦 Quay.io Container Tags Scraper

> **List every tag in a Quay.io repository as a row: tag name, manifest digest, size, last modified date and whether it is still current.** Give it a `namespace/name` slug and it pages the tag list for you. No login, no API token.

Quay.io hosts the container images a great deal of infrastructure runs on, including `coreos/etcd` and `prometheus/prometheus`. The tag list is shown a page at a time in a web console, and the digests, timestamps and expiry flags that matter live behind it. If you keep a record of what you deploy, audit which tags are still live, or want release history for an image, you end up clicking through pages. This Actor reads the tag list and writes each tag into a dataset.

| Who uses it | What they use the tag list for |
|---|---|
| 🛠 Platform and DevOps engineers | Keeping an inventory of the image tags in use, with digests pinned |
| 🔐 Security and supply chain teams | Auditing which tags are still current and which have expired |
| 🧪 Release engineers | Reading an image's release cadence from `lastModified` across tags |
| 🔍 Technical diligence teams | Checking what a target company ships publicly and how often it ships it |

### 📋 What it does

> 💡 **Why it matters:** a tag moves, a digest does not. Pulling both in one row is what turns "we run `v3.7.1`" into something you can verify later.

- 🏷 **Pages the full tag list** for any public `namespace/name` repository.
- 🔐 **Returns the manifest digest** alongside the tag name, so a pin is reproducible.
- 📅 **Keeps the last modified date** as a readable string and as a Unix timestamp.
- 🎯 **Single tag mode.** Pass `specificTag` for an exact name and skip the pagination entirely.
- 🧹 **Active only, by default.** Expired and hidden tags are excluded unless you ask for them.
- 📦 **One row per tag**, the same 14 fields every run, exportable as CSV, Excel, JSON or XML.

### 📊 Output

Every tag is one flat row. `null` means Quay publishes no value for that field on that tag.

| Field | Type | Description |
|---|---|---|
| 📚 `repository` | string | The repository slug the row came from, for example `coreos/etcd` |
| 🏷 `name` | string | Tag name, for example `v3.7.1` |
| 🔐 `manifestDigest` | string | The `sha256:` digest the tag points at |
| 📏 `size` | integer | Compressed size in bytes. `null` on multi architecture tags, where size lives on each child manifest |
| 📅 `lastModified` | string | Last modification date as Quay formats it, for example `Thu, 23 Jul 2026 19:36:01 -0000` |
| 🕐 `startTs` | integer | Unix timestamp the tag became current |
| 🕔 `endTs` | integer | Unix timestamp the tag stopped being current. `null` while it is still current |
| ⏳ `expiration` | string | Expiry set on the tag, `null` when none is set |
| 🆔 `dockerImageId` | string | Legacy Docker v1 image id, `null` for images built without it |
| 🔁 `reversion` | boolean | `true` when the tag was restored to an earlier manifest |
| 🧩 `isManifestList` | boolean | `true` when the tag points at a multi architecture manifest list |
| ✅ `isCurrent` | boolean | `true` when this is the live version of the tag |
| 🕒 `scrapedAt` | string | ISO timestamp of collection |
| ⚠️ `error` | string | `null` on a normal row |

#### Example rows

```json
{
  "repository": "coreos/etcd",
  "name": "v3.7.1",
  "manifestDigest": "sha256:3c66a5191d37a11af19f50ad49beed162a988bd1752eabc9fe6b164f7ee443e5",
  "size": null,
  "lastModified": "Thu, 23 Jul 2026 19:36:01 -0000",
  "startTs": 1784835361,
  "endTs": null,
  "expiration": null,
  "dockerImageId": null,
  "reversion": false,
  "isManifestList": true,
  "isCurrent": true,
  "scrapedAt": "2026-09-14T16:21:20.610Z",
  "error": null
}
```

```json
{
  "repository": "coreos/etcd",
  "name": "v3.7.1-s390x",
  "manifestDigest": "sha256:ea087ea6d67ae1eb9637c180aeebed86dd5e9e0f5d658eda230f767b03447a61",
  "size": 21655013,
  "lastModified": "Thu, 23 Jul 2026 19:35:42 -0000",
  "startTs": 1784835342,
  "endTs": null,
  "expiration": null,
  "dockerImageId": null,
  "reversion": false,
  "isManifestList": false,
  "isCurrent": true,
  "scrapedAt": "2026-09-14T16:21:20.714Z",
  "error": null
}
```

### ✨ Why choose this Actor

| | What you get |
|---|---|
| **Digest and tag on one row** | Pin by digest without a second lookup per tag. |
| **Timestamps in both forms** | `lastModified` for reading, `startTs` for sorting and differencing. |
| **The lifecycle flags** | `isCurrent`, `endTs`, `expiration` and `reversion` say whether a tag is still real. |
| **No credentials** | Public repositories are read without a Quay account or token. |
| **$0.0085 a row** | A thousand tags costs $8.50, and a repository with no tags costs nothing. |

### 🚀 How to use it

1. [Create a free Apify account](https://console.apify.com/sign-up). New accounts start with $5 of credit.
2. Open the Actor and select **Try for free**.
3. Put the repository slug in `repository`, in `namespace/name` form.
4. Set `maxItems` to cap the run. Leave `onlyActiveTags` on `true` unless you want expired tags too.
5. Select **Start**, then export from the **Dataset** tab as CSV, Excel, JSON or XML.

A first run:

```json
{
  "repository": "coreos/etcd",
  "maxItems": 10,
  "onlyActiveTags": true
}
```

One exact tag:

```json
{
  "repository": "prometheus/prometheus",
  "specificTag": "v2.53.0"
}
```

Everything, including expired tags:

```json
{
  "repository": "coreos/etcd",
  "maxItems": 1000,
  "onlyActiveTags": false
}
```

### ⚙️ Input

| Field | Required | Description |
|---|---|---|
| `repository` | No | Repository slug in `namespace/name` form, for example `coreos/etcd`. Defaults to `coreos/etcd` |
| `maxItems` | No | Maximum tags to collect in a run |
| `onlyActiveTags` | No | `true` excludes expired and hidden tags. Defaults to `true` |
| `specificTag` | No | Exact tag name. Set it and the Actor returns that tag only, ignoring pagination |

### 💰 Pricing

Pay per result. No subscription, and no Apify platform usage on top.

| Apify plan | Free | Bronze | Silver | Gold | Platinum | Diamond |
|---|---|---|---|---|---|---|
| Per tag row | $0.0085 | $0.00817 | $0.00783 | $0.0075 | $0.0075 | $0.0075 |

| Rows collected | Cost on the Free plan |
|---|---|
| 100 | $0.85 |
| 1,000 | $8.50 |
| 10,000 | $85.00 |

**Free plan runs** return a small preview. Any paid Apify plan lifts the cap.

### 🔌 Integrate with any app

The dataset is available through the Apify API as soon as the run finishes. Use `run-sync-get-dataset-items` for a one-shot call, webhooks to trigger what happens next, or the Make, Zapier, Airbyte and LangChain integrations listed on the Actor page. On a schedule, it becomes a tag history for the repositories you depend on.

### 🤖 Use with an AI agent

Give an agent live access to Quay.io tag lists over the Model Context Protocol:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=acquistion-automation/quay-io-tags-scraper"
```

Then ask it in plain language for the newest tag of an image and read the digest back.

### ❓ Frequently asked questions

**Why is `size` null on some tags?**
Multi architecture tags point at a manifest list rather than a single image, and Quay reports no single size for them. Those rows have `isManifestList` set to `true`. The per architecture tags beside them carry a size.

**Can it read a private repository?**
No. It reads public repositories only, with no token.

**How do I get just one tag?**
Set `specificTag` to the exact name. Pagination is skipped and the run returns that tag.

**What does `reversion` mean?**
Quay sets it when a tag has been moved back to an earlier manifest, so the current digest is one the tag pointed at before.

**Why is `dockerImageId` empty?**
It is a legacy Docker v1 identifier. Images built with modern tooling do not carry one, and Quay returns nothing for it.

**What can I export?**
CSV, Excel, JSON and XML from the run page, or JSON straight from the API.

### 🔗 More from Acquisition Automation Co.

- [RAWG Scraper](https://apify.com/acquistion-automation/rawg-scraper)
- [DrugBank Open Scraper](https://apify.com/acquistion-automation/drugbank-open-scraper)
- [Clutch Agencies Scraper](https://apify.com/acquistion-automation/clutch-agencies-scraper)
- [404 Media Articles Scraper](https://apify.com/acquistion-automation/404media-articles-scraper)
- [SAM.gov Contract Opportunities Scraper](https://apify.com/acquistion-automation/sam-gov-contracts-scraper)

### About Acquisition Automation Co.

We build automation for people buying businesses. The repetitive part of an acquisition search, checking listings, pulling public records, tracking owners and assets, is work a machine should do, so the buyer's time goes into judging deals instead of collecting them.

We add new Actors regularly. If there is a source you need and do not see here, tell us.

### 🆘 Support

Open an issue in the **Issues** tab of this Actor with your run ID, the input you used, and what you expected to get back.

### ⚠️ Disclaimer

This Actor is independent and is not affiliated with, endorsed by, or sponsored by Quay.io or Red Hat, Inc. It collects only publicly available data. You are responsible for using that data in compliance with the source's terms of service and applicable law.

# Actor input Schema

## `repository` (type: `string`):

Repository slug in `namespace/name` form (e.g. `coreos/etcd`, `prometheus/prometheus`).

## `maxItems` (type: `integer`):

Maximum number of tags to collect per run.

## `onlyActiveTags` (type: `boolean`):

If true, expired or hidden tags are excluded.

## `specificTag` (type: `string`):

Optional exact tag name (overrides pagination, returns only that tag).

## Actor input object example

```json
{
  "repository": "coreos/etcd",
  "maxItems": 10,
  "onlyActiveTags": true
}
```

# Actor output Schema

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

No description

# 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 = {
    "repository": "coreos/etcd",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("acquistion-automation/quay-io-tags-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 = {
    "repository": "coreos/etcd",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("acquistion-automation/quay-io-tags-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 '{
  "repository": "coreos/etcd",
  "maxItems": 10
}' |
apify call acquistion-automation/quay-io-tags-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,acquistion-automation/quay-io-tags-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/tHwz7vUe5jkhWBD7b/builds/iMMcBcCfdU0SaClbo/openapi.json
