# Etsy Scraper - Extract Product Data, Prices & Reviews (`techforce.global/etsy-scraper`) Actor

Scrape Etsy product listings by category, collection, or search. Get price, rating, reviews, shop & stock data, export to CSV/JSON or push to Notion, Slack.

- **URL**: https://apify.com/techforce.global/etsy-scraper.md
- **Developed by:** [Techforce Global](https://apify.com/techforce.global) (community)
- **Categories:** Agents, Automation, E-commerce
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.60 / 1,000 results

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

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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 Scraper & MCP Connector

Pull **every product listing off any Etsy category page, curated collection, or search results page** — title, price, rating, reviews, shop name, image, and stock/shipping status — with **no coding and no Etsy account required**.

Built for anyone tracking competitor pricing, monitoring a niche, sourcing product data for dropshipping, or feeding a price-comparison tool or BI dashboard.

> **Paste an Etsy listing-grid URL → get every product on it, paginated → deliver it straight into Notion, Slack, Airtable, or your own tools.**

---

### ⭐ Why This Actor?

- ✅ **Just paste an Etsy URL** — category page, curated collection, or search results page. No API key, no login, no keyword-to-URL guesswork.
- ✅ **Three ways in, one grid parser** — Start URLs, Search result URLs, or Category URLs all take full URLs copied straight from your browser and are scraped the same way.
- ✅ **Auto-paginates** — follows the `page` query parameter across as many result pages as you allow, per start URL.
- ✅ **Never guesses at hidden APIs** — Etsy has no public product-search API; this Actor reads the same listing grid a shopper sees and extracts every card on it.
- ✅ **Complete product cards** — price, original price and discount %, star rating, review count, free-shipping flag, low-stock warnings, and the primary image.
- ✅ **Anti-bot resilient** — runs through **Apify Proxy** (residential group by default) with a browser-impersonating HTTP client, because Etsy blocks datacenter IPs within milliseconds.
- ✅ **Deliver anywhere via MCP connectors** — push scraped products straight into Notion, Slack, Airtable, Google Sheets, and more.
- ✅ **Export-ready** — JSON, CSV, Excel, or HTML, or consume the dataset directly via the Apify API.

---

### 📝 Use Cases & ROI

| Use Case | Time Saved | What You Get |
| --- | --- | --- |
| **Competitor price monitoring** | 2–5 hrs/category | Every competitor listing's price, discount, and stock status in one table |
| **Niche & trend research** | 3–6 hrs/niche | A full snapshot of what's selling, at what price, and how well-reviewed it is |
| **Sourcing / dropshipping leads** | 4–8 hrs/search | Shop names, prices, and ratings across hundreds of candidate products |
| **Price-comparison tools** | Ongoing | Structured JSON/CSV feed ready to plug into your own comparison engine |
| **BI dashboards & reporting** | 2–4 hrs/refresh | Clean tabular data ready for Sheets, a warehouse, or a BI tool |

---

### 🚀 How to Use

1. Open the Actor on Apify.
2. Paste one or more Etsy listing-grid URLs into any (or all) of:
   - **Start URLs** — a category, curated collection, or search results page.
   - **Search result URLs** — an Etsy `/search?q=...` results page.
   - **Category URLs** — an Etsy `/c/...` category-browse page.
   At least one of the three must be filled in — all three take **full URLs**, not keywords or category paths.
3. _(Optional)_ Set **Max products** (default `100`, `0` = unlimited) and **Max pages per start URL** (default `3`).
4. _(Optional)_ Tune **Max concurrency** for speed (default `5` — keep it low to avoid rate limits).
5. _(Optional)_ Pick an **MCP connector** to deliver each scraped product into Notion, Slack, Airtable, etc.
6. Click **Start** — results stream into the dataset as each page is parsed.
7. Download from the Dataset tab as JSON, CSV, Excel, or HTML — or let the connector push them into your tools automatically.

> 🌐 **Proxy**: requests run through **Apify Proxy** (residential group by default) because Etsy blocks datacenter IPs almost instantly (HTTP 403 within milliseconds). Don't switch this off.
> 💡 First time with a connector? Run once with a connector selected and no **Connector tool name** — the run log prints the connector's available tool names.

---

### 🧩 Input Configuration

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `startUrls` | Array | One of the three | Etsy category, curated collection, or search results page URLs. Product/listing pages are not accepted as a starting point. |
| `searchQueries` | Array | One of the three | Full Etsy search-results URLs (e.g. `https://www.etsy.com/search?q=statement+necklace`) copied directly from your browser — keywords alone are not accepted. |
| `categories` | Array | One of the three | Full Etsy category-browse URLs (e.g. `https://www.etsy.com/c/jewelry/necklaces`) copied directly from your browser — category paths alone are not accepted. |
| `maxItems` | Integer | Optional | Overall cap on products collected across all URLs. `0` = unlimited. Default: `100`. |
| `maxPagesPerStartUrl` | Integer | Optional | How many result pages to paginate through per start URL. Curated collection pages may ignore pagination. Default: `3`. |
| `maxConcurrency` | Integer | Optional | Parallel page requests (1–20). Keep low to reduce blocking risk. Default: `5`. |
| `proxyConfiguration` | Object | Optional | Apify Proxy settings. Defaults to the `RESIDENTIAL` group — required for reliable access. |
| `mcpConnector` | Connector | Optional | Deliver each scraped product into a connector you've authorized (Notion, Slack, Airtable, Google Sheets, or any MCP-compatible connector). |
| `deliveryMode` | Enum | Optional | `perItem` (one call per product), `batch` (group several products per call), `summary` (one call at the end listing everything scraped), or `none`. Default: `none`. |
| `mcpTool` | String | Optional | Tool to call on the connector (e.g. `create-pages` for Notion). |
| `mcpArguments` | Object | Optional | Fixed, top-level arguments for the call — everything except the products themselves. String values support `{placeholders}`. |
| `mcpItemTemplate` | Object | Optional | Shape of **one** product entry, rendered once per product and collected into `mcpArrayField`. |
| `mcpArrayField` | String | Optional | Key inside `mcpArguments` that receives the array of rendered product entries. Default: `pages`. |
| `mcpBatchSize` | Integer | Optional | Only used in `batch` mode: how many products go into one call. Default: `10`. |
| `mcpMessageTemplate` | String | Optional | Optional template rendered per product/run, exposed as the `{message}` placeholder. |

#### Example — Scrape a curated collection

```json
{
    "startUrls": [{ "url": "https://www.etsy.com/in-en/r/curated/statement-jewelry?sections=1483190913703" }],
    "maxItems": 100,
    "maxPagesPerStartUrl": 3
}
````

#### Example — Scrape a search page and a category page together

```json
{
    "searchQueries": ["https://www.etsy.com/search?q=statement+necklace"],
    "categories": ["https://www.etsy.com/c/jewelry/necklaces"],
    "maxItems": 200,
    "maxPagesPerStartUrl": 5,
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

#### Example — Scrape and create a Notion page per product

```json
{
    "startUrls": [{ "url": "https://www.etsy.com/in-en/r/curated/statement-jewelry" }],
    "mcpConnector": "<your-notion-connector>",
    "deliveryMode": "perItem",
    "mcpTool": "create-pages",
    "mcpArguments": {
        "parent": { "page_id": "3a0e5ea6-3f43-8060-8fce-fe7061855e75" }
    },
    "mcpItemTemplate": {
        "properties": { "title": "{title} — {shopName}" },
        "content": "Price: {currency} {price}\nRating: {rating} ({reviewsCount} reviews)\n{url}"
    },
    "mcpArrayField": "pages"
}
```

#### Example — Scrape and post batched updates to Slack

```json
{
    "categories": ["https://www.etsy.com/c/jewelry/necklaces"],
    "maxItems": 50,
    "mcpConnector": "<your-slack-connector>",
    "deliveryMode": "batch",
    "mcpBatchSize": 10,
    "mcpTool": "send_message",
    "mcpArguments": { "channel": "#etsy-deals", "text": "{message}" },
    "mcpMessageTemplate": "New batch of {reviewsCount} products scraped"
}
```

#### Placeholders available in `mcpArguments` / `mcpItemTemplate` / `mcpMessageTemplate`

`{listingId}` · `{title}` · `{shopName}` · `{price}` · `{currency}` · `{originalPrice}` · `{discountPercent}` · `{rating}` · `{reviewsCount}` · `{freeShipping}` · `{stockWarning}` · `{imageUrl}` · `{url}` · `{message}`
**Summary mode adds:** `{totalPushed}` · `{summaryText}`

***

### 📦 Output Fields

Each scraped product is stored as one dataset item:

| Field | Description |
| --- | --- |
| `listingId` | Etsy's numeric listing ID |
| `title` | Product title |
| `url` | Canonical listing URL (tracking parameters stripped) |
| `shopName` | Name of the Etsy shop selling the item |
| `price` / `currency` | Current price and its currency |
| `originalPrice` / `discountPercent` | Pre-sale price and discount %, if the item is on sale |
| `rating` / `reviewsCount` | Star rating and number of reviews |
| `freeShipping` | Whether free delivery is advertised on the card |
| `sponsored` | Whether the card is marked as an Etsy ad |
| `stockWarning` | Low-stock message (e.g. "Only 2 left"), if shown |
| `imageUrl` | Primary product image URL |
| `scrapedAt` | UTC timestamp the item was scraped |

#### Example Output

```json
{
    "listingId": "1850339988",
    "title": "Gaia Bead Necklace",
    "url": "https://www.etsy.com/in-en/listing/1850339988/gaia-bead-necklace",
    "shopName": "GemBlue",
    "price": 7854.0,
    "currency": "INR",
    "originalPrice": null,
    "discountPercent": null,
    "rating": 4.9,
    "reviewsCount": 2500,
    "freeShipping": false,
    "sponsored": false,
    "stockWarning": null,
    "imageUrl": "https://i.etsystatic.com/.../il_794xN.jpg",
    "scrapedAt": "2026-07-17T00:00:00+00:00"
}
```

> You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

***

### 🔌 Integrations & Delivery

Deliver scraped products into any MCP connector you've authorized in Apify — no glue code, no webhooks:

- **Notion** — create a page per product (or batch several into fewer calls)
- **Slack / Discord** — post new listings or price drops to a channel
- **Airtable / Google Sheets** — append a structured row per product
- …or any other MCP-compatible connector

Credentials stay private — delivery runs through the **Apify MCP Proxy**, so the Actor never sees your connector tokens. This is configured entirely from the **Delivery (optional)** section of the Input tab and never affects what's saved to the dataset. You can also consume the dataset directly via the **Apify API**, or wire it into **n8n, Zapier, and Make**.

> ⚙️ **Delivery modes:** `perItem` sends one call per product as it's found, `batch` groups several products into one call (see **Batch size**), `summary` sends a single call at the end listing everything scraped, and `none` saves to the dataset only.

***

### 🛠️ How It Works

`my_actor/main.py` reads the input, merges Start/Search/Category URLs into one list of listing-grid pages, and configures the crawler:

1. `crawlee`'s `BeautifulSoupCrawler` fetches each URL through a Firefox-impersonating HTTP client (`ImpitHttpClient`) over Apify's residential proxy group, since Etsy blocks plain datacenter clients almost instantly.
2. `my_actor/routes.py`'s default handler parses every `a[href*="/listing/"]` card on the page — title, price, rating, shop, image, stock/shipping — and pushes each as one dataset item.
3. If more pages remain (up to **Max pages per start URL**), it builds the next page's URL and re-queues it.
4. If an MCP connector is configured, each pushed product is also routed to `perItem`, `batch`, or `summary` delivery via `my_actor/connector.py`, which opens a session through the Apify MCP Proxy and calls your chosen tool.

**Built with:** [Apify SDK for Python](https://docs.apify.com/sdk/python/) · [Crawlee for Python](https://crawlee.dev/python) · [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/) · [MCP](https://modelcontextprotocol.io/)

***

### 🆘 Support

For issues, custom scraping requests, or feature suggestions:

**Email**: bhavin.shah@techforceglobal.com

***

#### Need a Custom Pipeline?

Want other marketplaces, scheduled monitoring, deeper enrichment, or a full data-warehouse integration?

#### [📅 Book a Free 15-min Consultation](https://calendly.com/techforce-infotech-pvt-ltd/intro-meeting?month=2026-01)

***

Made with ❤️ by **[Techforce](https://www.techforceglobal.com)**
Specialists in High-Performance Web Scrapers and AI Automation.

***

### Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Etsy, Inc. Etsy® is a trademark of Etsy, Inc.; all trademarks are property of their respective owners. The Actor only reads publicly visible pages on Etsy — it does not log in, bypass paywalls, or access private data. Scraping is subject to Etsy's Terms of Service; please review them and use this tool responsibly, particularly around request rate and personal-data handling. Etsy's page layout and anti-bot measures can change at any time, which may temporarily affect field extraction or require proxy adjustments.

# Actor input Schema

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

Etsy category, curated collection, or search result pages to scrape (e.g. https://www.etsy.com/in-en/r/curated/statement-jewelry?sections=...). Product/listing URLs are not supported as start URLs. Optional if Search queries or Categories are provided instead.

## `searchQueries` (type: `array`):

Full Etsy search-results URLs to scrape (e.g. https://www.etsy.com/search?q=statement+necklace). Paste the URL directly from your browser after searching on Etsy - keywords alone are not accepted here.

## `categories` (type: `array`):

Full Etsy category-browse URLs to scrape (e.g. https://www.etsy.com/c/jewelry/necklaces). Paste the URL directly from your browser after browsing a category on Etsy - category paths alone are not accepted here.

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

Maximum number of products to scrape across all start URLs. Set to 0 for unlimited.

## `maxPagesPerStartUrl` (type: `integer`):

How many result pages to follow (via the `page` query parameter) for each start URL. Set to 1 to only scrape the first page. Curated collection pages may ignore pagination.

## `maxConcurrency` (type: `integer`):

Maximum number of parallel requests. Keep this low to reduce the chance of being rate-limited or blocked by Etsy.

## `proxyConfiguration` (type: `object`):

Etsy blocks datacenter IPs almost immediately (HTTP 403 on the very first request), so this defaults to the RESIDENTIAL proxy group. Your Apify plan must include residential proxy access - if runs still fail with 403s, check your plan's proxy access on the Apify platform.

## `mcpConnector` (type: `string`):

Optionally deliver each scraped product into a connector you have authorized - Notion, Slack, Airtable, Google Sheets, or any MCP-compatible connector. Leave empty to only save results to the dataset.

## `deliveryMode` (type: `string`):

How to deliver to the connector: 'perItem' (one call per scraped product, as it's found), 'batch' (group several products into one call - see Batch size), 'summary' (a single call at the end of the run listing everything scraped), or 'none' (save to dataset only).

## `mcpTool` (type: `string`):

Name of the tool to call on the connector (e.g. 'create-pages' for Notion, 'send\_message' for Slack). If unsure, run once with a connector selected - the log lists the connector's available tools.

## `mcpArguments` (type: `object`):

The fixed, top-level arguments passed to the connector tool - everything except the list of products itself. String values support {placeholders}: {message} (summary mode also gets {totalPushed}, {summaryText}). Example for Notion's create-pages tool: {"parent": {"page\_id": "3a0e5ea6-3f43-8060-8fce-fe7061855e75"}}. The array named in 'Array field name' below is added automatically.

## `mcpItemTemplate` (type: `object`):

Shape of ONE product entry, rendered once per product and collected into the array field named below. Available placeholders: {listingId}, {title}, {shopName}, {price}, {currency}, {originalPrice}, {discountPercent}, {rating}, {reviewsCount}, {freeShipping}, {stockWarning}, {imageUrl}, {url}, {message}. Example for Notion: {"properties": {"title": "{title} — {shopName}"}, "content": "Price: {currency} {price}\nRating: {rating} ({reviewsCount} reviews)\n{url}"}.

## `mcpArrayField` (type: `string`):

Key inside 'Connector tool arguments' that should receive the list of rendered per-product entries (e.g. 'pages' for Notion's create-pages tool). In 'perItem' mode this array always has exactly one entry per call; in 'batch' mode it holds up to 'Batch size' entries per call.

## `mcpBatchSize` (type: `integer`):

Only used in 'batch' delivery mode: how many products to collect into the array field before making one connector call.

## `mcpMessageTemplate` (type: `string`):

Optional template rendered and exposed as the {message} placeholder in the tool arguments/per-product template. Example: '{title} from {shopName} - {currency} {price}'.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.etsy.com/in-en/r/curated/statement-jewelry?sections=1483190913703&anchor_listings=4366726745&ref=hp_g-2"
    }
  ],
  "searchQueries": [],
  "categories": [],
  "maxItems": 100,
  "maxPagesPerStartUrl": 3,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "deliveryMode": "none",
  "mcpTool": "",
  "mcpArguments": {},
  "mcpItemTemplate": {},
  "mcpArrayField": "pages",
  "mcpBatchSize": 10,
  "mcpMessageTemplate": ""
}
```

# 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 = {
    "startUrls": [
        {
            "url": "https://www.etsy.com/in-en/r/curated/statement-jewelry?sections=1483190913703&anchor_listings=4366726745&ref=hp_g-2"
        }
    ],
    "searchQueries": [],
    "categories": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("techforce.global/etsy-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/in-en/r/curated/statement-jewelry?sections=1483190913703&anchor_listings=4366726745&ref=hp_g-2" }],
    "searchQueries": [],
    "categories": [],
}

# Run the Actor and wait for it to finish
run = client.actor("techforce.global/etsy-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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/in-en/r/curated/statement-jewelry?sections=1483190913703&anchor_listings=4366726745&ref=hp_g-2"
    }
  ],
  "searchQueries": [],
  "categories": []
}' |
apify call techforce.global/etsy-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=techforce.global/etsy-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Etsy Scraper - Extract Product Data, Prices & Reviews",
        "description": "Scrape Etsy product listings by category, collection, or search. Get price, rating, reviews, shop & stock data, export to CSV/JSON or push to Notion, Slack.",
        "version": "0.1",
        "x-build-id": "RXkPeoI3955fa5RjV"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/techforce.global~etsy-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-techforce.global-etsy-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/techforce.global~etsy-scraper/runs": {
            "post": {
                "operationId": "runs-sync-techforce.global-etsy-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/techforce.global~etsy-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-techforce.global-etsy-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "Start URLs",
                        "type": "array",
                        "description": "Etsy category, curated collection, or search result pages to scrape (e.g. https://www.etsy.com/in-en/r/curated/statement-jewelry?sections=...). Product/listing URLs are not supported as start URLs. Optional if Search queries or Categories are provided instead.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "searchQueries": {
                        "title": "Search result URLs",
                        "type": "array",
                        "description": "Full Etsy search-results URLs to scrape (e.g. https://www.etsy.com/search?q=statement+necklace). Paste the URL directly from your browser after searching on Etsy - keywords alone are not accepted here.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "categories": {
                        "title": "Category URLs",
                        "type": "array",
                        "description": "Full Etsy category-browse URLs to scrape (e.g. https://www.etsy.com/c/jewelry/necklaces). Paste the URL directly from your browser after browsing a category on Etsy - category paths alone are not accepted here.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Max products",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum number of products to scrape across all start URLs. Set to 0 for unlimited.",
                        "default": 100
                    },
                    "maxPagesPerStartUrl": {
                        "title": "Max pages per start URL",
                        "minimum": 1,
                        "type": "integer",
                        "description": "How many result pages to follow (via the `page` query parameter) for each start URL. Set to 1 to only scrape the first page. Curated collection pages may ignore pagination.",
                        "default": 3
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum number of parallel requests. Keep this low to reduce the chance of being rate-limited or blocked by Etsy.",
                        "default": 5
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Etsy blocks datacenter IPs almost immediately (HTTP 403 on the very first request), so this defaults to the RESIDENTIAL proxy group. Your Apify plan must include residential proxy access - if runs still fail with 403s, check your plan's proxy access on the Apify platform.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    },
                    "mcpConnector": {
                        "title": "Deliver to (MCP connector)",
                        "type": "string",
                        "description": "Optionally deliver each scraped product into a connector you have authorized - Notion, Slack, Airtable, Google Sheets, or any MCP-compatible connector. Leave empty to only save results to the dataset."
                    },
                    "deliveryMode": {
                        "title": "Delivery mode",
                        "enum": [
                            "perItem",
                            "batch",
                            "summary",
                            "none"
                        ],
                        "type": "string",
                        "description": "How to deliver to the connector: 'perItem' (one call per scraped product, as it's found), 'batch' (group several products into one call - see Batch size), 'summary' (a single call at the end of the run listing everything scraped), or 'none' (save to dataset only).",
                        "default": "none"
                    },
                    "mcpTool": {
                        "title": "Connector tool name",
                        "type": "string",
                        "description": "Name of the tool to call on the connector (e.g. 'create-pages' for Notion, 'send_message' for Slack). If unsure, run once with a connector selected - the log lists the connector's available tools.",
                        "default": ""
                    },
                    "mcpArguments": {
                        "title": "Connector tool arguments (envelope)",
                        "type": "object",
                        "description": "The fixed, top-level arguments passed to the connector tool - everything except the list of products itself. String values support {placeholders}: {message} (summary mode also gets {totalPushed}, {summaryText}). Example for Notion's create-pages tool: {\"parent\": {\"page_id\": \"3a0e5ea6-3f43-8060-8fce-fe7061855e75\"}}. The array named in 'Array field name' below is added automatically.",
                        "default": {}
                    },
                    "mcpItemTemplate": {
                        "title": "Per-product template",
                        "type": "object",
                        "description": "Shape of ONE product entry, rendered once per product and collected into the array field named below. Available placeholders: {listingId}, {title}, {shopName}, {price}, {currency}, {originalPrice}, {discountPercent}, {rating}, {reviewsCount}, {freeShipping}, {stockWarning}, {imageUrl}, {url}, {message}. Example for Notion: {\"properties\": {\"title\": \"{title} — {shopName}\"}, \"content\": \"Price: {currency} {price}\\nRating: {rating} ({reviewsCount} reviews)\\n{url}\"}.",
                        "default": {}
                    },
                    "mcpArrayField": {
                        "title": "Array field name",
                        "type": "string",
                        "description": "Key inside 'Connector tool arguments' that should receive the list of rendered per-product entries (e.g. 'pages' for Notion's create-pages tool). In 'perItem' mode this array always has exactly one entry per call; in 'batch' mode it holds up to 'Batch size' entries per call.",
                        "default": "pages"
                    },
                    "mcpBatchSize": {
                        "title": "Batch size",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Only used in 'batch' delivery mode: how many products to collect into the array field before making one connector call.",
                        "default": 10
                    },
                    "mcpMessageTemplate": {
                        "title": "Message template",
                        "type": "string",
                        "description": "Optional template rendered and exposed as the {message} placeholder in the tool arguments/per-product template. Example: '{title} from {shopName} - {currency} {price}'.",
                        "default": ""
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
