Etsy Best Sellers Scraper
Pricing
from $2.99 / 1,000 best sellers
Etsy Best Sellers Scraper
Scrape best-selling product listings from Etsy search or category pages. Extracts title, price, rating, review count, shop name, and listing URL.
Pricing
from $2.99 / 1,000 best sellers
Rating
0.0
(0)
Developer
w3crawler
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 hours ago
Last modified
Categories
Share
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
- Open the Actor Store page and select Try for free, or open the Input tab.
- Choose a source: add up to five
startUrls, or supplycategoryUrlorsearchQuery. If all three are empty, the Actor readshttps://www.etsy.com/market/best_sellers. - Set
maxItemsand keepmaxPagesat1for the first run. LeaveincludeDetailsoff until you need description, shipping, or seller fields. - 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:
{"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:
{"searchQuery": "handmade mug","maxItems": 5,"sortBy": "rating_desc"}
{"categoryUrl": "https://www.etsy.com/market/home_and_living","maxItems": 10,"minPrice": 10,"maxPrice": 100,"minRating": 4}
{"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.
{"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.
{"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:
{"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 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.