# Shopify Collections — Category Map of Any Store (`tidyfeed/shopify-collections`) Actor

List every collection a Shopify store publishes, with how many products sit in it and how recently it was merchandised. One row per collection, ready for a spreadsheet.

- **URL**: https://apify.com/tidyfeed/shopify-collections.md
- **Developed by:** [tidyfeed](https://apify.com/tidyfeed) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 collections

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?

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

## Shopify Collections — Category Map of Any Store

**How does this brand organise what it sells?**

Every collection a Shopify store publishes, with how big it is and how recently it was merchandised. One row each, biggest first. It is the fastest way to read a competitor's category structure without clicking through their navigation.

No API key. No login. No Shopify partner account. No proxies.

***

### The number nobody else checks

Shopify publishes a `products_count` on every collection. It is not the number of products the store actually publishes, and it is not close.

Measured 2 September 2026, cross-checked against each store's own sitemap:

| Store | "All Products" collection reports | Store actually publishes | Sitemap agrees |
|---|---|---|---|
| deathwishcoffee.com | 1,281 | **150** | 149 |
| allbirds.com | 4,143 | **293** | 293 |

Every tool that pipes `products_count` straight into a column called "products" is handing you a number that is wrong by 8x on one of those stores and 14x on the other.

So this actor does two things. It passes Shopify's figure through under the name `productsCountReported`, which says what it is. And it offers **Count the products for real** — switch it on and the actor opens every collection and counts what the public feed returns, in a separate `productsCountVerified` column.

***

### What you get

One row per collection:

| Column | What it is |
|---|---|
| `collectionTitle` | What shoppers see |
| `handle` | The address it lives at — `/collections/<handle>` |
| `collectionUrl` | Full link |
| `productsCountReported` | Shopify's own figure. Often inflated — see above |
| `productsCountVerified` | What the feed really returns. Only when you ask for it |
| `daysSinceUpdated` | How long since the store last changed this collection |
| `updatedAt`, `publishedAt` | The raw dates |
| `imageUrl` | Collection image, if any |
| `description` | Optional, as plain text |

`daysSinceUpdated` is the quiet workhorse. A store with 260 collections usually has forty that are live and two hundred that were abandoned after a campaign. This column separates them at a glance.

***

### Typical uses

- **Read a competitor's category tree in one screen** instead of crawling their menu.
- **Find the campaign collections.** Sort by most recently merchandised and their current promotional push is at the top.
- **Size an assortment honestly.** Turn on verified counts and compare real catalog depth across brands.
- **Find the collections worth scraping.** Get the handles here, then feed them to `tidyfeed/shopify-best-sellers`, which reads any collection in the store's own order.

***

### Input

| Field | What it does |
|---|---|
| `storeUrls` | Store addresses. Normal website addresses. |
| `minProductCount` | Hide small and empty collections. Filters on the reported figure. Default 1. |
| `maxCollectionsPerStore` | Upper limit per store. Large brands publish several hundred. Default 500. |
| `sortBy` | Biggest first, most recently merchandised first, or A to Z. |
| `verifyProductCounts` | Go and count what each collection really returns. Slower, and worth it. |
| `includeDescription` | Add the description as plain text. |

***

### What it costs

Billed per collection delivered. Collections filtered out by `minProductCount` are not charged. A store with no public feed returns nothing and costs nothing beyond the run start.

Verified counting adds requests and time, not price.

Platform usage is included. No proxies are needed, so there are no proxy costs.

***

### How it works

Shopify serves a public collection list at `/collections.json` on every storefront. This actor walks it 250 at a time. With verification on, it then reads `/collections/<handle>/products.json` for each one and counts distinct products.

**Headless storefronts are followed to their real shop.** Brands running a custom front end answer `/collections.json` with a web page. This actor reads the shop address the site publishes in its own markup and continues there — mejuri.com resolves this way.

No HTML parsing means a theme change cannot break it.

***

### Honest limits

- **`productsCountReported` is Shopify's number, and it is frequently wrong.** It is included because it is what the store publishes, under a name that says so. Use `productsCountVerified` when the figure matters.
- **Verified counting stops at 5,000 products per collection.** Rows that hit the ceiling are flagged with `verifiedCountCapped`.
- **Collections hidden from the storefront do not appear.** This reads what a store publishes, not its admin.
- **A collection can report products and return none.** Usually those products are not published to the online store. The verified count shows 0 rather than guessing.
- **No product-level data is returned here** — this is the map, not the territory. Use `tidyfeed/shopify-best-sellers` for a collection's contents in order, or `tidyfeed/shopify-product-scraper` for a full catalog.
- **Password-protected and pre-launch stores return nothing**, with a reason per store.

***

### Scheduling

Merchandising moves in campaigns. Schedule it monthly against a competitor list and the diffs show you exactly when a brand restructured its categories or spun up a seasonal push.

***

### Legal

This actor reads only data a Shopify store publishes publicly, at addresses the store itself serves to anyone. It collects no personal data, requires no login, and bypasses no access control. You remain responsible for how you use the exported data.

***

Questions, or a store that behaves oddly? Open an issue on the actor — issues are read and answered.

# Actor input Schema

## `storeUrls` (type: `array`):

One or more Shopify store addresses. Paste the normal website address — https://gymshark.com. No API key, login or Shopify partner account is needed. Stores running a custom front end are resolved to their Shopify shop automatically.

## `minProductCount` (type: `integer`):

Filters on the product count Shopify reports for the collection. Stores leave a lot of empty and one-off collections behind; the default of 1 hides the empty ones. Raise it to see only collections carrying real assortment.

## `maxCollectionsPerStore` (type: `integer`):

Upper limit on how many collections are read per store. Large brands publish several hundred.

## `sortBy` (type: `string`):

How to order the rows within each store.

## `verifyProductCounts` (type: `boolean`):

Shopify's reported count is often far higher than the number of products a store actually publishes — allbirds.com reports 4,143 in its All Products collection and publishes 293. Switch this on and the Actor opens every collection and counts what the public feed really returns, adding a productsCountVerified column. It costs one extra request per 250 products, so runs take longer.

## `includeDescription` (type: `boolean`):

Add the collection description as plain text. Off by default because it makes spreadsheets hard to read.

## Actor input object example

```json
{
  "storeUrls": [
    "https://gymshark.com",
    "https://allbirds.com"
  ],
  "minProductCount": 1,
  "maxCollectionsPerStore": 500,
  "sortBy": "size",
  "verifyProductCounts": false,
  "includeDescription": false
}
```

# Actor output Schema

## `collections` (type: `string`):

No description

## `collectionsCsv` (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 = {
    "storeUrls": [
        "https://gymshark.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tidyfeed/shopify-collections").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 = { "storeUrls": ["https://gymshark.com"] }

# Run the Actor and wait for it to finish
run = client.actor("tidyfeed/shopify-collections").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 '{
  "storeUrls": [
    "https://gymshark.com"
  ]
}' |
apify call tidyfeed/shopify-collections --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tidyfeed/shopify-collections"
        }
    }
}

```

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/kM8FuyRAtqhZ0fJn6/builds/WI6grdnN2TEqWR14u/openapi.json
