# Etsy Shop Scraper: Full Catalog, Views & Sections (`wheaten_steelpan/etsy-shop-scraper`) Actor

Scrape any Etsy shop's COMPLETE catalog through Etsy's official Open API. Every active listing with views, favourites, price and tags, plus shop sections, sales and rating. No scraping, so no DataDome blocks. Returns Etsy's own listing count so you can verify the pull.

- **URL**: https://apify.com/wheaten\_steelpan/etsy-shop-scraper.md
- **Developed by:** [Vanja V](https://apify.com/wheaten_steelpan) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$250.00 / 1,000 shop reports

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

## Etsy Shop Scraper: Full Catalog, Views & Sections

Pulls a shop's entire active catalog from Etsy's official API. Every listing comes back with its
views, favourites, price, stock, tags, materials and section, along with the shop's own sales,
rating and section list.

One flat price per shop, however many listings it has.

![Example Etsy shop catalog report](https://api.apify.com/v2/key-value-stores/BwyGthGjtzz1zsevC/records/report-preview.png)

### Why other shop scrapers come back empty

Most Etsy shop scrapers read the storefront, which is bot-protected. You get the shop's profile
(name, location, star-seller badge) and none of its products. Sometimes you get nothing at all,
because the request was blocked.

This one calls Etsy's official Open API with our own commercial key. You do not need an Etsy
developer account, an API key, or a proxy. There is nothing to get blocked by.

It also returns `views` and `num_favorers` for every listing. Those are not on the public shop page
at all. Etsy publishes them through the API.

### Check the pull yourself

Etsy reports two different active-listing counts, and they often disagree. The shop record and the
catalog endpoint are computed at different moments, so a listing that sells out or expires between
them lands in the gap. On a 168-listing shop the difference was 1. On an 1,800-listing shop it was
31\.

Rather than pick whichever number flatters the run, every report shows both:

```
Complete: all 167 active listings the catalog endpoint offered were returned.
Etsy's shop record separately reports 168, so Etsy's own two counts disagree by 1,
usually a listing that changed state between the calls. Nothing was dropped by this run.
```

So when the number here does not match the number on the shop page, you can see exactly why.

Each shop ends in one of three states:

| verdict | meaning |
|---|---|
| `complete` | you have every active listing, and Etsy's two counts agree |
| `complete-with-count-mismatch` | you have every listing the catalog endpoint offered, and Etsy's own counts differ |
| `incomplete` | the pull stopped short, and this shop was **not charged** |

### Pricing

**$0.25 per shop.** No start fee, no per-listing fee, no cap.

A 30-listing shop and a 3,000-listing shop cost the same. The median Etsy shop has about 170 active
listings. The largest in our sample had over 18,000.

A shop we cannot deliver in full is not charged. That covers a shop name that turns out not to
exist, a shop we could not read, and a pull that stopped short. Whatever rows did arrive are still
in your dataset. You are simply not billed for them.

### What you get

**The report** (first output tab) shows the completeness verdict, both of Etsy's counts, the shop's
totals, the 50 most-viewed listings and every section.

**The dataset** gives you one row per active listing:

| field | |
|---|---|
| `title` `description` `url` `tags` `materials` | listing content |
| `views` `numFavorers` | traffic and interest, available only through the API |
| `priceValue` `currencyCode` `quantity` | price and stock |
| `sectionTitle` `sectionId` | which shop section it sits in |
| `createdAt` `listedAt` `endingAt` `lastModifiedAt` | first listed, renewed, expiring |
| `whoMade` `whenMade` `isSupply` `isCustomizable` `isPersonalizable` `hasVariations` | Etsy attributes |
| `shopName` `shopSoldCount` `shopReviewCount` `shopReviewAverage` | the shop it belongs to |
| `catalogVerdict` `reportUrl` | completeness state, and a link to the report |

The report also carries three rates per shop:

- **views per listing-day**, total views over total listing-days
- **favourites per view**, which is buyer interest rather than a guess
- **reviews per sale**, the shop's own review count over its own sales count

None of these is a sales estimate. Etsy publishes a shop's lifetime sales count directly, and it is
in the report as itself.

### Input

Paste a shop name, a shop URL, or a numeric shop ID, one per line:

```
TheMugVaultLtd
https://www.etsy.com/shop/FreedomMockups
50434417
```

The name is the one in the web address. It never contains spaces, and it is often different from the
large title at the top of the shop page.

Spelling has to match, because this Actor refuses to guess between similar shops rather than bill
you for a different seller's catalog. If a name does not match, the run says so and lists the
closest real shop names.

A short name that is also a common word is the one case that needs care. `Art` matches over 300,000
shops as a name prefix. When that happens the run tells you, and asks for the shop URL or the
numeric shop ID instead.

### Limits

- **Active listings only.** Sold-out, expired and draft listings are not returned. Etsy's active
  catalog endpoint does not carry them.
- **No live cart counts.** "In 12 carts" is a storefront-only signal and is not in the API.
- **No search rank.** The API's listing index is not Etsy's search order, so this cannot tell you
  where a listing ranks for a keyword.
- **Etsy text in the report expires after 6 hours**, as Etsy's API terms require. Listing titles,
  tags and section names are withheld from the report past that point. The counts, views, prices and
  verdict do not expire, and your dataset is unaffected. Re-run for current text.

# Actor input Schema

## `shopNames` (type: `array`):

One or more Etsy shops. You can paste any of three things: the shop name exactly as Etsy spells it (FreedomMockups), the shop's web address (etsy.com/shop/FreedomMockups), or its numeric shop ID. The name is the one in the web address. It never contains spaces, and it is often different from the large title at the top of the shop page. Upper and lower case do not matter, but the spelling has to match: this Actor refuses to guess between similar shops rather than bill you for the wrong seller's catalog. If a name does not match, the run stops and lists the closest real shop names. Every active listing is returned, with its views and favourites. There is no cap and no per-listing charge.

## Actor input object example

```json
{
  "shopNames": [
    "TheMugVaultLtd"
  ]
}
```

# Actor output Schema

## `report` (type: `string`):

The readable report: whether the catalog came back complete, the shop's totals, views per listing-day, favourites per view, reviews per sale, the 50 most-viewed listings and every shop section. Start here.

## `data` (type: `string`):

One row per active listing: title, price, quantity, views, favourites, tags, materials, section, and when it was first listed. Download it as CSV, JSON or Excel from the Export button.

## `summary` (type: `string`):

Per shop: how many listings came back against BOTH of the counts Etsy publishes, which is which, and the reason for any pull that stopped short. Etsy's own two counts often disagree by a few listings; this says so plainly instead of hiding it. A shop we could not deliver is not charged.

# 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 = {
    "shopNames": [
        "TheMugVaultLtd"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("wheaten_steelpan/etsy-shop-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 = { "shopNames": ["TheMugVaultLtd"] }

# Run the Actor and wait for it to finish
run = client.actor("wheaten_steelpan/etsy-shop-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 '{
  "shopNames": [
    "TheMugVaultLtd"
  ]
}' |
apify call wheaten_steelpan/etsy-shop-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,wheaten_steelpan/etsy-shop-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/zasNl44QqpgnfQ0Ci/builds/4kV9hCf5PqKZnZvCe/openapi.json
