# Etsy Best Sellers Scraper (`w3crawler/etsy-best-sellers-scraper`) Actor

Scrape best-selling product listings from Etsy search or category pages. Extracts title, price, rating, review count, shop name, and listing URL.

- **URL**: https://apify.com/w3crawler/etsy-best-sellers-scraper.md
- **Developed by:** [w3crawler](https://apify.com/w3crawler) (community)
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 best sellers

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Etsy Best Sellers Scraper

Collect listing cards from public Etsy best-seller, search, and category pages. Each saved row describes one listing as the page displayed it: identity and URL, title, displayed and parsed price, currency, image, rating and review count, shop details when the card exposes them, visible ad and merchandising badges, and optional detail-page fields such as materials, shipping, seller history, and review snippets.

### Get started

1. Open the [Actor Store page](https://apify.com/w3crawler/etsy-best-sellers-scraper) and select **Try for free**, or open the **Input** tab.
2. Choose a source: add up to five `startUrls`, or supply `categoryUrl` or `searchQuery`. If all three are empty, the Actor reads `https://www.etsy.com/market/best_sellers`.
3. Set `maxItems` and keep `maxPages` at `1` for the first run. Leave `includeDetails` off until you need description, shipping, or seller fields.
4. Start the Actor, open the dataset, and export rows as JSON, CSV, or Excel. Open **Run summary** (`OUTPUT`) to check the row count, filters, duplicates, and detail-page results.

### Input

All fields are optional, and the defaults below are ready to use. Unsupported field names and out-of-range values are rejected before requests start. `startUrls` are used first; otherwise `categoryUrl`, then `searchQuery`, then the default best-sellers page.

| Field | Type | Required? | Default | Meaning |
| --- | --- | --- | --- | --- |
| `startUrls` | object array | Optional | `[]` | Public Etsy search, market, category, or best-sellers URLs, up to five entries. Each entry is an object with a `url` string. When present, these replace `categoryUrl` and `searchQuery`. |
| `searchQuery` | string | Optional | Not supplied | Public Etsy search phrase, up to 200 characters. Ignored when `startUrls` or `categoryUrl` is supplied. |
| `categoryUrl` | string | Optional | Not supplied | Public HTTPS Etsy marketplace or category URL. Used when `startUrls` is empty and takes precedence over `searchQuery`. |
| `maxItems` | integer | Optional | `20` | Maximum listing rows saved across all sources, from 1 to 200. |
| `maxPages` | integer | Optional | `1` | Maximum result pages visited per source URL, from 1 to 5. |
| `deduplicate` | boolean | Optional | `true` | Skip cards whose Etsy listing ID was already saved from another page or source. |
| `keyword` | string | Optional | Not supplied | Case-insensitive filter applied to the listing title and shop name, up to 200 characters. |
| `minPrice` | number | Optional | Not supplied | Lower bound for the parsed numeric price. Cards without a parsed price are filtered out when a price bound is set. |
| `maxPrice` | number | Optional | Not supplied | Upper bound for the parsed numeric price. Cards without a parsed price are filtered out when a price bound is set. |
| `minRating` | number | Optional | Not supplied | Minimum public rating, from 0 to 5. Cards without a rating are filtered out when this is set. |
| `minReviewCount` | integer | Optional | Not supplied | Minimum public review count, zero or greater. Cards without a review count are filtered out when this is set. |
| `sortBy` | string enum | Optional | `recommended` | Final order after filtering and deduplication: `recommended`, `price_asc`, `price_desc`, `rating_desc`, or `review_count_desc`. |
| `includeDetails` | boolean | Optional | `false` | Open up to `maxDetailItems` listing pages to add description, category path, materials, shipping, seller, and popularity fields. |
| `maxDetailItems` | integer | Optional | `0` | Maximum listing pages opened for detail enrichment, from 0 to 20. Has no effect unless `includeDetails` is `true`. |
| `includeReviews` | boolean | Optional | `false` | Keep a bounded sample of visible reviews from opened detail pages. |
| `maxReviews` | integer | Optional | `5` | Maximum visible reviews retained per opened detail page, from 0 to 20. |
| `requestDelayMs` | integer | Optional | `250` | Polite pause before page extraction, from 0 to 5,000 ms. |
| `maxConcurrency` | integer | Optional | `1` | Maximum simultaneous browser pages, from 1 to 2. |
| `maxRequestRetries` | integer | Optional | `1` | Retries for ordinary request failures, from 0 to 2. |
| `requestTimeoutSecs` | integer | Optional | `45` | Maximum navigation time per page, from 10 to 90 seconds. |

Example input used for the saved run:

```json
{
  "startUrls": [
    {
      "url": "https://www.etsy.com/market/best_sellers"
    }
  ],
  "maxItems": 3,
  "maxPages": 1,
  "deduplicate": true,
  "sortBy": "recommended",
  "includeDetails": false,
  "maxDetailItems": 0,
  "includeReviews": false,
  "maxReviews": 5,
  "requestDelayMs": 250,
  "maxConcurrency": 1,
  "maxRequestRetries": 1,
  "requestTimeoutSecs": 45
}
```

The saved run capped the result at three rows and did not request detail enrichment. The schema defaults are 20 rows, one page per source, and detail enrichment off. The Actor uses ordinary public browser navigation to load each source page and, when enabled, individual listing pages. It does not sign in, call private endpoints, solve CAPTCHAs, spoof a device, or bypass an Etsy access decision. Filters and sorting are applied locally after extraction, so they do not change what Etsy returns.

Other input variations use the same fields:

```json
{
  "searchQuery": "handmade mug",
  "maxItems": 5,
  "sortBy": "rating_desc"
}
```

```json
{
  "categoryUrl": "https://www.etsy.com/market/home_and_living",
  "maxItems": 10,
  "minPrice": 10,
  "maxPrice": 100,
  "minRating": 4
}
```

```json
{
  "startUrls": [
    {
      "url": "https://www.etsy.com/search?q=ceramic+planter"
    }
  ],
  "maxPages": 2,
  "includeDetails": true,
  "maxDetailItems": 2
}
```

### Output

The dataset contains one row per unique listing card saved, in final sorted order. With `deduplicate: true`, a listing that appears on several pages is kept once. Values that the page did not display are `null`; optional detail fields stay `null` when `includeDetails` is off or the page is not opened. No diagnostic or placeholder rows are written.

| Field | Type | Availability | Meaning |
| --- | --- | --- | --- |
| `source` | string | null | Always | Source platform; `Etsy`. |
| `sourceHost` | string | null | Always | Hostname of the public source. |
| `pageType` | string | null | Always | Kind of page that produced the card, such as `search_results` or `category`. |
| `sourceUrl` | string | null | Always | Source URL submitted or generated by the Actor. |
| `pageUrl` | string | null | Always | Final public page URL after navigation. When the row comes from a public Internet Archive capture, this is the Wayback replay URL that served the archived HTML. |
| `pageNum` | integer | null | Always | One-based result page number within its source URL. |
| `position` | integer | null | Always | One-based card position on that result page. |
| `rank` | integer | null | Always | One-based position in the final dataset after sorting. |
| `listingId` | string | null | Always | Etsy listing identifier. |
| `listingUrl` | string | null | Always | Canonical public listing URL. |
| `title` | string | null | Always | Listing title as displayed on the card. |
| `description` | string | null | When detail enrichment succeeds | Public listing description from the opened listing page. |
| `category` | string | null | When published | Category label shown by the listing page. |
| `categoryPath` | string array | null | When detail enrichment succeeds | Breadcrumb labels from the public listing page. |
| `price` | string | null | When a price is displayed | Price text shown on the card, including its currency symbol. |
| `priceValue` | number | null | When a price can be parsed | Numeric value parsed from `price`. |
| `originalPrice` | string | null | When a struck-through price is displayed | Original price text shown beside the current price. |
| `originalPriceValue` | number | null | When an original price can be parsed | Numeric value parsed from `originalPrice`. |
| `discountPercent` | number | null | When the page exposes a discount | Discount percentage for the card. |
| `currency` | string | null | When a price is displayed | Normalized currency code such as `USD`, `EUR`, `GBP`, or `INR`. |
| `currencySymbol` | string | null | When a price is displayed | Currency symbol or code exactly as displayed. |
| `rating` | number | null | When the card displays a rating | Public listing rating from 0 to 5. |
| `reviewCount` | integer | null | When the card displays reviews | Public listing review count. |
| `shopName` | string | null | When the card displays a shop | Public Etsy shop name. |
| `shopUrl` | string | null | When the card displays a shop | Public Etsy shop URL. |
| `imageUrl` | string | null | Always | Primary public listing image URL. |
| `images` | string array | null | When images are displayed | Bounded list of public listing image URLs. |
| `badges` | string array | null | When the card shows badges | Visible merchandising labels, such as free shipping. |
| `isBestseller` | boolean | null | When the card shows an explicit marker | Whether a bestseller marker is visible on the card. `null` when the page only calls itself a best-seller collection. |
| `isEtsyChoice` | boolean | null | When Etsy Choice state is observable | Whether an Etsy Choice marker is present. |
| `isAd` | boolean | null | When ad state is observable | Whether the card carries Etsy's promoted or ad label. |
| `adPosition` | integer | null | When the card is promoted | One-based position of the promoted slot; `null` for organic cards. |
| `searchQuery` | string | null | When a search phrase was used | Search phrase behind the source page. |
| `categoryUrl` | string | null | When a category URL was supplied | Category URL used as the source. |
| `materials` | string array | null | When detail enrichment succeeds | Materials listed on the public listing page. |
| `shipping` | string | null | When detail enrichment succeeds | Shipping text shown on the listing page. |
| `deliveryEstimate` | string | null | When detail enrichment succeeds | Delivery estimate shown on the listing page. |
| `returnsPolicy` | string | null | When detail enrichment succeeds | Returns text shown on the listing page. |
| `sellerLocation` | string | null | When detail enrichment succeeds | Public seller location. |
| `sellerSalesCount` | integer | null | When detail enrichment succeeds | Public number of shop sales. |
| `sellerYearsOnEtsy` | integer | null | When detail enrichment succeeds | Years on Etsy derived from the public seller history date. |
| `sellerRating` | number | null | When detail enrichment succeeds | Public seller rating. |
| `sellerReviewCount` | integer | null | When detail enrichment succeeds | Public seller review count. |
| `sellerResponseTime` | string | null | When detail enrichment succeeds | Public seller response-time text. |
| `favoritesCount` | integer | null | When detail enrichment succeeds | Public favorites count for the listing. |
| `listedAt` | string | null | When detail enrichment succeeds | Listing date as displayed publicly. |
| `reviews` | object array | null | When detail enrichment and `includeReviews` are enabled | Bounded visible review snippets; each entry has a `text` string. |
| `detailEnriched` | boolean | null | When detail enrichment was requested | Whether the optional listing page was opened successfully. `null` when no detail page was requested for the row. |
| `detailErrorCode` | string | null | When detail enrichment fails | Stable short code for the failure. |
| `detailError` | string | null | When detail enrichment fails | Bounded explanation of the failure. |
| `scrapedAt` | string | null | Always | Time the row was saved, in ISO UTC. |

`categoryPath`, `images`, `badges`, and `materials` are string arrays. `reviews` is an array of objects with a `text` field. Detail fields are populated only for the first `maxDetailItems` cards when `includeDetails` is enabled; the remaining rows keep `detailEnriched: null` and null detail fields.

The example below is a real saved row from the 2026-10-25 run.

```json
{
  "source": "Etsy",
  "sourceHost": "www.etsy.com",
  "pageType": "search_results",
  "sourceUrl": "https://www.etsy.com/market/best_sellers",
  "pageUrl": "https://www.etsy.com/market/best_sellers",
  "pageNum": 1,
  "position": 1,
  "rank": 1,
  "listingId": "1391093641",
  "listingUrl": "https://www.etsy.com/listing/1391093641/personalised-leather-wallet-with-rfid",
  "title": "PERSONALISED Leather Wallet With RFID Blocking Technology For Men - Chocolate Brown - HT13 - Gift Boxed - Best Seller - Embossed Wallet",
  "description": null,
  "category": null,
  "categoryPath": null,
  "price": "$ 41.97",
  "priceValue": 41.97,
  "originalPrice": null,
  "originalPriceValue": null,
  "discountPercent": null,
  "currency": "USD",
  "currencySymbol": "$",
  "rating": null,
  "reviewCount": null,
  "shopName": null,
  "shopUrl": null,
  "imageUrl": "https://i.etsystatic.com/13272288/r/il/22cdd2/4558866501/il_600x600.4558866501_kjcm.jpg",
  "images": [
    "https://i.etsystatic.com/13272288/r/il/22cdd2/4558866501/il_600x600.4558866501_kjcm.jpg"
  ],
  "badges": null,
  "isBestseller": null,
  "isEtsyChoice": false,
  "isAd": true,
  "adPosition": 1,
  "searchQuery": null,
  "categoryUrl": null,
  "materials": null,
  "shipping": null,
  "deliveryEstimate": null,
  "returnsPolicy": null,
  "sellerLocation": null,
  "sellerSalesCount": null,
  "sellerYearsOnEtsy": null,
  "sellerRating": null,
  "sellerReviewCount": null,
  "sellerResponseTime": null,
  "favoritesCount": null,
  "listedAt": null,
  "reviews": null,
  "detailEnriched": null,
  "detailErrorCode": null,
  "detailError": null,
  "scrapedAt": "2026-10-25T20:41:08.053Z"
}
```

This row came from a promoted slot on the best-sellers page. Etsy did not expose a shop name, shop URL, rating, review count, badges, or an explicit bestseller marker for that card, so those fields are `null`; `isAd` is `true` and `adPosition` is `1`. Title, price text, parsed price, currency, and image are the values the card displayed. The other two saved rows have the same shape: all three are promoted cards, and only the second and third include a `FREE shipping` badge.

The row below is a real organic card read from the public Internet Archive capture `20251129182826` of the same best-sellers page when the live page was blocked. The archived card exposed no shop link, so the shop fields are `null`, and `pageUrl` is the Wayback replay address that carries the capture timestamp.

```json
{
  "source": "Etsy",
  "sourceHost": "www.etsy.com",
  "pageType": "search_results",
  "sourceUrl": "https://www.etsy.com/market/best_sellers",
  "pageUrl": "https://web.archive.org/web/20251129182826id_/https://www.etsy.com/market/best_sellers",
  "pageNum": 1,
  "position": 2,
  "rank": 1,
  "listingId": "1461506381",
  "listingUrl": "https://www.etsy.com/listing/1461506381",
  "title": "24 day Elf Kit 2025, Best Seller Christmas Elf Activities Kit, Elf Props, Pre-planned Elf Ideas, 24 Days Elf Scenes, Christmas Elves",
  "description": null,
  "category": null,
  "categoryPath": null,
  "price": "75.00",
  "priceValue": 75,
  "originalPrice": null,
  "originalPriceValue": null,
  "discountPercent": null,
  "currency": "USD",
  "currencySymbol": "$",
  "rating": 4.8097,
  "reviewCount": 3800,
  "shopName": null,
  "shopUrl": null,
  "imageUrl": "https://i.etsystatic.com/31074479/r/il/41ec5d/7401277038/il_300x300.7401277038_84lz.jpg",
  "images": [
    "https://i.etsystatic.com/31074479/r/il/41ec5d/7401277038/il_300x300.7401277038_84lz.jpg"
  ],
  "badges": null,
  "isBestseller": null,
  "isEtsyChoice": false,
  "isAd": null,
  "adPosition": null,
  "searchQuery": null,
  "categoryUrl": "https://www.etsy.com/market/best_sellers",
  "materials": null,
  "shipping": null,
  "deliveryEstimate": null,
  "returnsPolicy": null,
  "sellerLocation": null,
  "sellerSalesCount": null,
  "sellerYearsOnEtsy": null,
  "sellerRating": null,
  "sellerReviewCount": null,
  "sellerResponseTime": null,
  "favoritesCount": null,
  "listedAt": null,
  "reviews": null,
  "detailEnriched": null,
  "detailErrorCode": null,
  "detailError": null,
  "scrapedAt": "2026-10-31T19:03:54.935Z"
}
```

### Run summary

**Run summary** is stored separately from the dataset in the run's key-value store under `OUTPUT`.

| Field | Meaning |
| --- | --- |
| `status` | Actor process outcome: `SUCCEEDED` or `FAILED`. |
| `runStatus` | Canonical run status; matches `status`. |
| `dataStatus` | Completeness of the saved listing rows: `COMPLETE`, `PARTIAL`, `NO_RESULTS`, or `FAILED`. |
| `sourceUrls` | Public source URLs used for the run, in the order they were scheduled. |
| `sourceCount` | Number of distinct source URLs. |
| `pagesProcessed` | Result pages loaded and processed. |
| `scheduledRequests` | Page requests queued at the start of the run, before deduplication. |
| `normalRowsWritten` | Listing rows saved to the dataset. |
| `diagnosticCount` | Operational issues recorded, such as an access block, empty page, or failed detail request. |
| `diagnosticRowsWritten` | Diagnostic dataset rows; always `0`. |
| `filteredOutCount` | Cards removed by `keyword`, `minPrice`, `maxPrice`, `minRating`, or `minReviewCount`. |
| `duplicateCount` | Repeated listing IDs skipped after the first occurrence. |
| `detailRequested` | Number of listing pages the run attempted to open. |
| `detailSucceeded` | Detail pages opened and parsed successfully. |
| `detailFailed` | Detail pages that could not be opened or parsed. |
| `maxItems` | Row limit used for the run. |
| `maxPages` | Page-per-source limit used for the run. |
| `sortBy` | Final sort order applied to the rows. |
| `scrapedAt` | Time the summary was written, in ISO UTC. |

| Status | Data status | Meaning |
| --- | --- | --- |
| `SUCCEEDED` | `COMPLETE` | At least one listing row was saved and no operational issue was recorded. |
| `SUCCEEDED` | `PARTIAL` | Listing rows were saved, but a source page or detail request failed afterward. Saved rows remain available. |
| `SUCCEEDED` | `NO_RESULTS` | The page loaded cleanly but no card survived extraction and filtering. |
| `FAILED` | `FAILED` | A fatal error occurred before any usable listing was saved. |

Example `OUTPUT` from the 2026-10-25 run:

```json
{
  "status": "SUCCEEDED",
  "runStatus": "SUCCEEDED",
  "dataStatus": "COMPLETE",
  "sourceUrls": [
    "https://www.etsy.com/market/best_sellers"
  ],
  "sourceCount": 1,
  "pagesProcessed": 1,
  "scheduledRequests": 1,
  "normalRowsWritten": 3,
  "diagnosticCount": 0,
  "diagnosticRowsWritten": 0,
  "filteredOutCount": 0,
  "duplicateCount": 0,
  "detailRequested": 0,
  "detailSucceeded": 0,
  "detailFailed": 0,
  "maxItems": 3,
  "maxPages": 1,
  "sortBy": "recommended",
  "scrapedAt": "2026-10-25T20:41:08.946Z"
}
```

### Coverage and limitations

The Actor reports what the public result page rendered during the run. Etsy mixes organic and promoted cards, and a promoted card often omits the shop, rating, review count, and badges that an organic card shows; those gaps stay `null` instead of being filled from another page. The saved best-sellers run is an example: all three rows came from promoted slots, so shop and rating fields are absent.

`priceValue`, `rating`, and `reviewCount` come from the visible card, and price filters compare only parsed numeric values. A card whose price cannot be parsed is excluded when a price bound is set. Sorting is local and does not change the source order used for pagination. Detail fields such as description, materials, shipping, seller history, and reviews require `includeDetails` and a positive `maxDetailItems`; those pages add requests and run time, and a failed detail page yields `detailEnriched: false` with a bounded error code rather than invented data.

Best-seller and search result sets vary by country, locale, session, and time, so the same input can return a different mix. The Actor does not sign in, use private endpoints, solve CAPTCHAs, or bypass access boundaries. Blocked, empty, and partial pages are counted in `OUTPUT` and logs rather than written as rows.

When Etsy answers both the browser crawl and a plain HTTP read with a bot-check, the Actor looks for a public Internet Archive capture of the same source URL through the Wayback CDX and availability APIs and reads its raw `id_` HTML. Archived HTML goes through the same card and JSON-LD readers, so a row can only contain listings that the archived page displayed. One capture is read per source URL, and pagination links inside an archived page are not followed. That row's `pageUrl` is the Wayback replay address, which carries the capture timestamp; captures can be old, and a URL with no public capture stays a diagnostic instead of a row.

### Usage and support

Cost is driven by browser page loads, page count, concurrency, retries, timeouts, and optional detail enrichment. Start with one source, `maxItems` of 3 to 20, and details off; then increase pages or enable details after inspecting the dataset and run summary. See the Actor's Pricing tab for current account rates.

Use the [Actor Issues page](https://apify.com/w3crawler/etsy-best-sellers-scraper/issues) to report a problem. Include the run ID, the input used, and the run summary; do not include tokens, cookies, or private data. This Actor is an independent community tool and is not affiliated with, endorsed by, or sponsored by Etsy, Inc. Use it only for public data and in accordance with Etsy's terms, robots guidance, and applicable law.

# Changelog

This Actor's version history is a separate document: https://apify.com/w3crawler/etsy-best-sellers-scraper/changelog.md

# Actor input Schema

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

Optional public Etsy search, category, or best-sellers URLs. Up to five URLs; these take precedence over categoryUrl and searchQuery.

## `searchQuery` (type: `string`):

Public Etsy search phrase. Leave empty to use best sellers.

## `categoryUrl` (type: `string`):

Optional HTTPS Etsy marketplace/category URL.

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

Maximum normal listing rows, from 1 to 200.

## `maxPages` (type: `integer`):

Maximum result pages to visit for each source URL.

## `deduplicate` (type: `boolean`):

Deduplicate by Etsy listing ID across source pages.

## `keyword` (type: `string`):

Optional case-insensitive filter applied to listing title and shop name.

## `minPrice` (type: `number`):

Optional lower bound for the parsed public price.

## `maxPrice` (type: `number`):

Optional upper bound for the parsed public price.

## `minRating` (type: `number`):

Optional minimum public rating from 0 to 5.

## `minReviewCount` (type: `integer`):

Optional minimum public review count.

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

Order applied after filtering and deduplication.

## `includeDetails` (type: `boolean`):

Open up to maxDetailItems public listing pages for additional fields.

## `maxDetailItems` (type: `integer`):

Detail-page cap; effective only when includeDetails is enabled.

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

Keep a bounded sample of reviews found on opened public detail pages.

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

Maximum visible reviews per detail page.

## `requestDelayMs` (type: `integer`):

Polite pause in milliseconds before extraction.

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

Bounded browser-page concurrency.

## `maxRequestRetries` (type: `integer`):

Bounded retry count for ordinary request failures.

## `requestTimeoutSecs` (type: `integer`):

Maximum navigation time in seconds.

## Actor input object example

```json
{
  "startUrls": [],
  "maxItems": 20,
  "maxPages": 1,
  "deduplicate": true,
  "sortBy": "recommended",
  "includeDetails": false,
  "maxDetailItems": 0,
  "includeReviews": false,
  "maxReviews": 5,
  "requestDelayMs": 250,
  "maxConcurrency": 1,
  "maxRequestRetries": 1,
  "requestTimeoutSecs": 45
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `runSummary` (type: `string`):

Run status and counters stored by the Actor.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("w3crawler/etsy-best-sellers-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("w3crawler/etsy-best-sellers-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 '{}' |
apify call w3crawler/etsy-best-sellers-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,w3crawler/etsy-best-sellers-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/uuBVfjlmyuZQGNkGr/builds/5GMzm7iHp6swBMLFs/openapi.json
