Etsy Products Scraper — robots-allowed, no CAPTCHA
Pricing
from $1.50 / 1,000 etsy listings
Etsy Products Scraper — robots-allowed, no CAPTCHA
Drop-in compatible with crawlerbros/etsy-scraper — cheaper and reliable. Etsy keyword results as JSON: listing id, title, price, sale price, discount, rating, reviews, image, shop id, ad flag, position. Reads only the routes Etsy's own robots.txt allows, never the search URLs it disallows.
Pricing
from $1.50 / 1,000 etsy listings
Rating
0.0
(0)
Developer
DIOPSIDE AI
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
14 days ago
Last modified
Categories
Security
Limited permissionsShare
Etsy Products Scraper
Drop-in compatible with crawlerbros/etsy-scraper — cheaper, and it only touches the Etsy routes
Etsy's own robots.txt allows. Give it keywords, get back Etsy product listings as JSON: listing
id, title, price, sale price, discount, rating, review count, image, shop id, sponsored flag,
position and page. No login, no CAPTCHA solver, no browser.
Why this one
1. It uses the surface Etsy sanctions. Etsy's robots.txt disallows the keyword search path
outright for every user agent:
Disallow: /search?*q=Disallow: /search/?*q=Disallow: /*?order=* Disallow: /*min=* Disallow: /*max=*
and in the same file explicitly allows the two routes this actor reads:
Allow: /api/v3/ajax/bespoke/public/neu/specs/Allow: /api/v3/ajax/bespoke/member/neu/specs/
/market/<keyword> — Etsy's own keyword results page — carries no Disallow rule at all. This
actor fetches /market/<keyword> and replays Etsy's own market_async_listings call to load the
rest of the grid. It paginates with ?page=N and nothing else, so it never constructs a URL
robots.txt forbids. That is also why there is no sort or price-filter input: every one of those
query parameters is on Etsy's disallow list.
2. The proxy requirement is measured, not guessed. Etsy is behind DataDome. We probed it on the platform, 2 attempts × 6 surfaces per IP tier:
| Surface | No proxy (Apify IP) | Apify datacenter US | Apify RESIDENTIAL US |
|---|---|---|---|
/ (homepage) | 200 | 200 | 200 |
/market/<keyword> | 403 DataDome | 403 DataDome | 200 OK |
/search?q= | 403 DataDome | 403 DataDome | 403 DataDome |
/c/<category> | 403 DataDome | 403 DataDome | 403 DataDome |
/shop/<name> | 403 DataDome | 403 DataDome | 403 DataDome |
/listing/<id> | 403 DataDome | 403 DataDome | 403 DataDome |
Residential is the entry fee, not an escalation, so it is the default here and the actor says so up
front instead of failing halfway through your run. TLS fingerprint matters on top of the IP: plain
curl/httpx are challenged even on the homepage, so every request goes out with a real Chrome
fingerprint.
3. ~48 listings per page request. A market page server-renders only ~8 cards and defers the rest to an async call. This actor makes that call, so one page request yields ~48 records instead of 8.
4. Sponsored listings are flagged from Etsy's own ad list, not guessed from the card label, so
isAd is right even when Etsy drops the visible "Ad from Etsy seller" text.
Input
| Field | Type | Default | Description |
|---|---|---|---|
searchQueries | string[] | — | Keywords to look up, e.g. ["leather wallet"]. Same name as crawlerbros/etsy-scraper. |
startUrls | URL[] | — | Etsy market / search / category URLs. The keyword is read out and fetched from /market/. |
maxItems | integer | 100 | Max listings per keyword. 0 = everything Etsy will paginate through. |
maxPages | integer | 25 | Max market pages per keyword (~48 listings each). |
includeAds | boolean | true | Keep Etsy's promoted listings (flagged with isAd) or drop them. |
dedupeAcrossQueries | boolean | true | Return each listing id at most once for the whole run. You are billed per pushed listing, so this also stops overlapping keywords billing twice. |
country | string | US | Residential exit country. |
proxyConfiguration | object | RESIDENTIAL / US | See the table above — anything else returns nothing. |
queries, maxResults | Aliases accepted for yumitori/etsy-listings-scraper inputs. | ||
includeDetails | boolean | false | Accepted for compatibility, no effect — see Limits. |
{"searchQueries": ["leather wallet", "ceramic mug"],"maxItems": 120,"maxPages": 3,"includeAds": false}
Output
{"listingId": "733018869","shopId": "20986259","url": "https://www.etsy.com/listing/733018869/slim-leather-wallet-date-night","title": "Slim Leather Wallet, DATE NIGHT, Personalized Bifold Wallet, Handmade Wallet for Men","price": "16.33","originalPrice": "49.49","currency": "$","discountPercent": "67","imageUrl": "https://i.etsystatic.com/20986259/r/il/efbe9e/1992954590/il_300x300.1992954590_gjtc.jpg","shopName": "LifetimeLeatherCo","shopUrl": "https://www.etsy.com/shop/LifetimeLeatherCo","rating": "4.87","reviewCount": 15200,"badges": {"starSeller": false,"freeShipping": true,"bestseller": false,"etsyChoice": false,"ad": false},"scrapedAt": "2026-09-20T05:47:27+00:00","isAd": false,"priceValue": 16.33,"originalPriceValue": 49.49,"onSale": true,"searchQuery": "leather wallet","page": 1,"position": 5,"marketUrl": "https://www.etsy.com/market/leather_wallet","totalResults": 279429}
Every field above the blank line has the same name and shape as crawlerbros/etsy-scraper. The
fields below it are additions — your existing code ignores them.
Sizes and cost
Measured on the platform, residential US:
| Run | Records | Pages | Time | Platform cost |
|---|---|---|---|---|
| 1 keyword, 1 page | 40 | 1 | 12 s | $0.0030 |
| 2 keywords, 3 pages each | 222 | 6 | 31 s | $0.0105 |
Billing is $0.00005 per run start + $0.0015 per listing. A 100-listing run costs $0.15;
the same run on crawlerbros/etsy-scraper ($0.01 start + $0.002/result) costs $0.21, and on
yumitori/etsy-listings-scraper ($0.008/listing) $0.80.
Limits — what this actor does not do
Stated up front so you can tell before you spend anything:
- No product-detail fields. No description, materials, variations, tags, stock or shipping
estimate. Etsy's
/listing/<id>pages are 403 DataDome on every IP tier we measured, residential included.includeDetailsis accepted socrawlerbrosinputs run unchanged, but it logs a warning and changes nothing. - No shop-page or category-page mode.
/shop/<name>and/c/<category>are 403 on every tier too. Category URLs instartUrlsare converted to their keyword and run through/market/. shopName/shopUrlare partial (~7 per page). Etsy's grid cards carry only the numericshopId; the shop name appears solely in the page's structured data, which covers the handful of server-rendered listings.shopIdis on every record.- No sort or price filters. Every one of those query parameters is on Etsy's robots disallow list, so this actor will not emit them.
rating/reviewCountare the seller's, as Etsy shows them on the card. Etsy abbreviates the count (15.2k), so it is expanded to15200— Etsy's own precision, not ours.
Switching from crawlerbros/etsy-scraper
Change the actor id. Your searchQueries, startUrls, maxItems and country work as-is and the
output field names are unchanged. Two things to know: includeDetails has no effect (see Limits),
and shopName is populated for fewer records.
Use cases
- Price and discount tracking across a keyword, on a schedule.
- Competitive research: who ranks for a keyword, at what price, with what rating.
- Sponsored-vs-organic share of a keyword's first pages (
isAdplusposition). - Feeding an agent or a dashboard with Etsy pricing without running a browser.