# 🛍️ Etsy Product & Reviews Scraper (`dz_omar/etsy-product-reviews-scraper`) Actor

🆓 Free for now —🛍️ Scrape full Etsy product & listing data from any URL pricing, shop, variations, shipping, policies, ratings & media plus optional ⭐ buyer reviews with rating, media & sort filters. Public data, no login.

- **URL**: https://apify.com/dz\_omar/etsy-product-reviews-scraper.md
- **Developed by:** [FlowExtract API](https://apify.com/dz_omar) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 13 total users, 10 monthly users, 77.5% runs succeeded, 3 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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 Product & Reviews Scraper  Full Listing Data + Buyer Reviews

**[Etsy Product & Reviews Scraper](https://apify.com/dz_omar/etsy-product-reviews-scraper?fpr=smcx63)** extracts complete **Etsy listing/product data** from any listing URL  product info, shop, pricing, variations, shipping, policies, ratings and media  and, optionally, the listing's **buyer reviews** with the same filters you have in the Etsy app. Paste a URL, run, and get clean, structured JSON.

Perfect for **e-commerce sellers**, **market researchers**, and **developers** who need full Etsy product and review data without maintaining a scraper or reverse-engineering Etsy's app API.

***

### Why scrape Etsy?

Etsy hosts millions of handmade, vintage, and custom listings, and every listing page carries a rich, structured payload  pricing, variations, shipping, shop reputation, and buyer reviews. That data powers competitor analysis, pricing strategy, product research, and review-sentiment work.

Common use cases:

- **Competitor & pricing research**  track prices, variations, quantities, and shop ratings across listings.
- **Product sourcing & trends**  analyze what's selling, how it's made, and how it's priced.
- **Review analysis**  pull buyer reviews (with sub-ratings and seller responses) for sentiment and quality insights.
- **Catalog enrichment**  hydrate your own product database with full Etsy listing details.
- **Shop monitoring**  watch a competitor's listings, ratings, and review trends over time.

***

### What data can the Etsy Product & Reviews Scraper extract?

Every input URL always returns one **listing-details** record (the full product payload). When **Include reviews** is on, you also get one **review** record per review.

#### 🏷️ Product / Listing

- Listing ID, title, full description, listing URL
- Price and currency, quantity available, when-made / made-to-order
- Category, tags, personalization options, "how it's made"

#### 🎨 Variations & Offerings

- Variation options (size, color, style, …) and per-variation pricing
- Offerings, inventory, and images by variation

#### 🏪 Shop & Seller

- Shop name, shop rating and review counts, shop policies
- Seller details, production partners, manufacturers, FAQs

#### 🚚 Shipping & Policies

- Shipping options and costs, free-shipping info
- Structured return and shop policies

#### ⭐ Ratings & Reviews (optional)

- Overall listing rating, star breakdown, photo/video review counts
- Per review: `rating`, `review` text, `date`, buyer name/login, `language`
- `subratings` (item quality, shipping, customer service), seller `response`, `is_recommended`, `upvotes_count`
- Order references: `transaction_id`, `receipt_id`

#### 🖼️ Media

- Listing images and video, review images/videos, buyer avatars

> **Data preservation:** the full Etsy response is preserved on each `listing_details` record  nothing is stripped  so even fields not listed above are available.

***

### ⚙️ How to use the Etsy Product & Reviews Scraper

#### Input options

##### 🔗 Etsy listing URLs (`startUrls`, array  required)

One or more Etsy listing URLs. Any locale prefix or query string is fine.

| Input value | What it does |
|---|---|
| `https://www.etsy.com/listing/1667678858/...` | Fetches that listing's full details (+ reviews if enabled) |
| `https://www.etsy.com/ca/listing/1861242992/...` | Locale prefixes work too |

```json
{
  "startUrls": [
    { "url": "https://www.etsy.com/listing/1667678858/personalised-engraved-groomsmen-groom" },
    { "url": "https://www.etsy.com/listing/1861242992/embroidered-crown-for-kids-and-childrens" }
  ],
  "includeReviews": true,
  "maxReviews": 100
}
```

##### 💬 `includeReviews` (boolean)  default `true`

Listing details are **always** fetched. When `true`, reviews are fetched too. When `false`, only the listing-details record is returned and **no** review requests are made.

##### 🔢 `maxReviews` (integer)  default `10`

Maximum reviews to collect **per listing** (each URL independently  not a global total). `0` = all matching reviews. Ignored when `includeReviews` is off. It never limits listing-details records  there is always exactly one per URL.

##### ↕️ `sort`  `Suggested` · `Most recent` · `Highest rated` · `Lowest rated`

##### ⭐ `rating`  only reviews with a chosen star rating (1–5), or all

##### 📷 `reviewMedia`  `Any review` · `With photos` · `With videos` (mutually exclusive, as in the Etsy app)

```json
{
  "startUrls": [{ "url": "https://www.etsy.com/listing/1667678858/x" }],
  "includeReviews": true,
  "maxReviews": 500,
  "sort": "Most recent",
  "rating": "5",
  "reviewMedia": "With photos"
}
```

**How the limit works:** with two URLs and `maxReviews: 1000`, you get **2 listing-details records + up to 1,000 reviews for each listing** (2,002 records total). With `includeReviews: false` and one URL, you get exactly **1** record regardless of `maxReviews`.

#### 🔐 Authentication

None. No Etsy account or login is required  the actor reads public listing and review data.

***

### 💰 Pricing

🎉 **Free for now** — full listing details and reviews, no charge, while the actor is in its launch period. Tiered pay-per-event pricing (shown below) is ready to go and will be announced here before it's ever turned on.

***

### 📊 Sample output

#### Listing details (`_type: "listing_details"`, one per URL  abridged; full payload is preserved)

```json
{
  "_type": "listing_details",
  "scraped_listing_id": 1667678858,
  "includeReviews": true,
  "listing": {
    "listing_id": 1667678858,
    "title": "Personalised Engraved Groomsmen Groom Best man Cufflinks",
    "price": "31.10",
    "currency_code": "USD",
    "quantity": 556,
    "when_made": "made_to_order",
    "url": "https://www.etsy.com/listing/1667678858/personalised-engraved-groomsmen-groom"
  },
  "shop": { "shop_name": "MarHappiness" },
  "variations": [ "…" ],
  "shipping": { "…": "…" },
  "listing_rating": { "…": "…" },
  "source_url": "https://www.etsy.com/listing/1667678858",
  "_source": "etsy-product-reviews-scraper"
}
```

#### Review (`_type: "review"`, one per review)

```json
{
  "_type": "review",
  "scraped_listing_id": 1667678858,
  "rating": 5,
  "review": "Great cufflinks. Looked just as described",
  "date": 1786608327,
  "buyer_real_name": "Beth Belger",
  "buyer_login_name": "bethbelger",
  "language": "en",
  "is_recommended": true,
  "upvotes_count": 0,
  "subratings": { "item_quality": 5, "shipping": 5, "seller_customer_service": 5 },
  "response": null,
  "transaction_id": 5099392452,
  "receipt_id": 4087440613,
  "source_url": "https://www.etsy.com/listing/1667678858",
  "_source": "etsy-product-reviews-scraper"
}
```

Use the **Listing details** and **Reviews** dataset views, or filter on `_type`, to separate the two.

#### Listings that no longer exist

If a URL points to a listing that has been removed or never existed, you get a clear, self-describing record instead of a failure — and the rest of your URLs keep processing:

```json
{
  "_type": "listing_details",
  "_status": "not_found",
  "scraped_listing_id": 18336688391,
  "includeReviews": true,
  "error": "Etsy listing 18336688391 does not exist or is no longer available.",
  "etsy_error": "ListingMap with PK listing_id = 18336688391 does not exist",
  "source_url": "https://www.etsy.com/listing/18336688391"
}
```

***

### ❓ Frequently Asked Questions

**Do I need an Etsy account to use this actor?**
No. It only reads publicly available listing and review data.

**How many reviews can I extract for free?**
All of them  the actor is free to use during its launch period, no per-event charges apply yet.

**Can I get product details without reviews?**
Yes  set `includeReviews: false`. You get one listing-details record per URL and no review charges.

**Can I scrape multiple listings in one run?**
Yes. Add multiple URLs to `startUrls`; `maxReviews` applies to each listing independently.

**Does `maxReviews` limit the product data?**
No. There is always exactly one listing-details record per URL. `maxReviews` only caps reviews per listing.

**What happens if the run crashes or is aborted mid-way?**
It resumes exactly where it left off  see Resumability below  without re-delivering completed work.

***

### 🔄 Resumability

The actor delivers results progressively and checkpoints its progress continuously. If it crashes, is migrated, or is aborted, a resurrected run resumes from the last safe point  details and reviews are tracked as independent phases per listing, so completed work is never repeated.

| Trigger | What gets saved |
|---|---|
| After each delivered review page | Listing offset + delivered count (encrypted) |
| After listing details delivered | Details-done marker per listing |
| Apify `aborting` event | Full state snapshot |

***

### 🌐 Proxy support

Proxy is automatic  no setup required.

| User tier | Proxy used |
|---|---|
| 💎 Paying | Premium dedicated proxy with automatic failover to Apify Proxy |
| 🆓 Free | Apify datacenter proxy  built-in, automatic |

***

### 🚫 Error handling

| Situation | What you see | What to do |
|---|---|---|
| URL isn't an Etsy listing | Skipped with a warning | Provide a valid `/listing/<id>/…` URL |
| Listing not found / removed | `listing not found  skipping` | Verify the listing still exists |
| No reviews on a listing | `no public reviews for this listing` | Expected for new/low-volume listings |

***

### ⚖️ Legal & ethical use

This actor extracts **publicly visible data** from Etsy  the same product and review information any visitor sees in their browser.

**Please use this tool responsibly:**

- Only extract data you are authorized to access.
- Comply with [Etsy's Terms of Use](https://www.etsy.com/legal/terms-of-use) and applicable data-protection regulations (GDPR, CCPA, etc.).
- Do not use extracted data for spam, harassment, or unsolicited outreach.
- Respect rate limits and do not overload the source.

***

### 🤝 Support & Resources

- 🌐 **Website**: [flowextractapi.com](https://flowextractapi.com)
- 📧 **Email**: <flowextractapi@outlook.com>
- 🙋 **Apify Profile**: [FlowExtract API](https://apify.com/dz_omar?fpr=smcx63)
- 💬 **GitHub Issues**: [FlowExtractAPI](https://github.com/FlowExtractAPI)

#### 🌟 Related Actors by FlowExtract API

- **[Idealista Scraper API](https://apify.com/dz_omar/idealista-scraper-api?fpr=smcx63)**  Property data across Spain, Portugal, and Italy
- **[YouTube Scraper Pro](https://apify.com/dz_omar/Youtube-Scraper-Pro?fpr=smcx63)**  Channel and playlist extraction
- **[Facebook Ads Scraper Pro](https://apify.com/dz_omar/facebook-ads-scraper-pro?fpr=smcx63)**  Facebook ad-library data

# Actor input Schema

## `startUrls` (type: `array`):

One or more Etsy listing URLs to scrape reviews from. Any locale prefix and query string is fine.

Example: https://www.etsy.com/listing/1667678858/personalised-engraved-groomsmen-groom

## `includeReviews` (type: `boolean`):

Listing/product details are always fetched for each URL. When ON, reviews are also fetched (using the options below). When OFF, only listing details are returned and no review requests are made. Each listing-details record records which mode was used.

## `maxReviews` (type: `integer`):

Maximum reviews to collect per listing (applies to each URL separately, not a global total). Set 0 to fetch every matching review. Ignored when 'Include reviews' is off. Never limits listing-details records — there is always one per URL.

## `sort` (type: `string`):

Order reviews are returned in, matching the Etsy app.

## `rating` (type: `string`):

Return only reviews with this star rating. Leave empty for all ratings.

## `reviewMedia` (type: `string`):

Limit to reviews that include buyer photos or videos. Only one can be chosen (as in the Etsy app).

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.etsy.com/listing/1667678858/personalised-engraved-groomsmen-groom"
    },
    {
      "url": "https://www.etsy.com/listing/1574793663/1st-baby-birthday-crown-party-hats"
    },
    {
      "url": "https://www.etsy.com/listing/1861242992/embroidered-crown-for-kids-and-childrens"
    }
  ],
  "includeReviews": true,
  "maxReviews": 10,
  "sort": "Suggested",
  "reviewMedia": "Any"
}
```

# Actor output Schema

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

Every delivered record: listing\_details (full product data), review, and not\_found status records.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.etsy.com/listing/1667678858/personalised-engraved-groomsmen-groom"
        },
        {
            "url": "https://www.etsy.com/listing/1574793663/1st-baby-birthday-crown-party-hats"
        },
        {
            "url": "https://www.etsy.com/listing/1861242992/embroidered-crown-for-kids-and-childrens"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dz_omar/etsy-product-reviews-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 = { "startUrls": [
        { "url": "https://www.etsy.com/listing/1667678858/personalised-engraved-groomsmen-groom" },
        { "url": "https://www.etsy.com/listing/1574793663/1st-baby-birthday-crown-party-hats" },
        { "url": "https://www.etsy.com/listing/1861242992/embroidered-crown-for-kids-and-childrens" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("dz_omar/etsy-product-reviews-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 '{
  "startUrls": [
    {
      "url": "https://www.etsy.com/listing/1667678858/personalised-engraved-groomsmen-groom"
    },
    {
      "url": "https://www.etsy.com/listing/1574793663/1st-baby-birthday-crown-party-hats"
    },
    {
      "url": "https://www.etsy.com/listing/1861242992/embroidered-crown-for-kids-and-childrens"
    }
  ]
}' |
apify call dz_omar/etsy-product-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dz_omar/etsy-product-reviews-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/0MxDII43AO9efVmmD/builds/HqoF8JX4IxaIOwTUL/openapi.json
