$npx -y skills add browser-act/skills --skill etsy-shop-catalogEtsy shop catalog scraper: given an Etsy shop URL (e.g. https://www.etsy.com/shop/{shop-name}) and optional page number, returns paginated product listings from that shop's own storefront with listingId, shopId, title, url, image, salePrice, originalPrice, currency, rating, revie
| 1 | # Etsy — Shop Catalog |
| 2 | |
| 3 | > Input an Etsy shop URL (and optional page number) → output paginated product listings from that shop's storefront. |
| 4 | |
| 5 | ## Language |
| 6 | |
| 7 | All process output to user (progress updates, process notifications) follows the user's language. |
| 8 | |
| 9 | ## Objective |
| 10 | |
| 11 | Collect a shop's own storefront listings, one page at a time, with core fields per item. |
| 12 | |
| 13 | ## Prerequisites |
| 14 | |
| 15 | - Target page is already open in the browser: `https://www.etsy.com/shop/{shop-name}` (or navigate to it during execution) |
| 16 | - No login required — shop pages are public |
| 17 | - Browser session must survive anti-bot verification (DataDome). Best practice: navigate to `https://www.etsy.com/` first, then to the shop URL |
| 18 | |
| 19 | ## Pre-execution Checks |
| 20 | |
| 21 | ### 1. Tool Readiness |
| 22 | |
| 23 | If browser-act has been confirmed available in the current session → skip this step. |
| 24 | |
| 25 | Invoke `browser-act` via Skill tool to load usage. If installation or configuration issues arise, follow its guidance to resolve then retry. |
| 26 | |
| 27 | ### 2. Anti-bot Warm-up |
| 28 | |
| 29 | If a fresh browser session was just created: |
| 30 | |
| 31 | 1. `navigate https://www.etsy.com/` → `wait stable` |
| 32 | 2. Then `navigate https://www.etsy.com/shop/{shop-name}` → `wait stable` |
| 33 | |
| 34 | On `blocked by anti-bot verification page` errors, switch to a stealth browser with a different fingerprint / proxy and retry. |
| 35 | |
| 36 | ## Capability Components |
| 37 | |
| 38 | > This Skill's operational boundary = what the user can manually do in their browser. It only reads data already displayed to the user on the page, never bypassing authentication or access controls. Its role is equivalent to copy-pasting on the user's behalf — the data is already on screen, automation merely saves time. JS code is encapsulated in Python files under the `scripts/` directory, invoked via `eval "$(python scripts/xxx.py {params})"`. `$(...)` is bash syntax; it is recommended to use the bash tool for execution. |
| 39 | |
| 40 | ### DOM: extract product listings from shop storefront page |
| 41 | |
| 42 | Prerequisite: current page is an Etsy shop page (`https://www.etsy.com/shop/{shop-name}`) after `wait stable`. Works on both the default first tab and paginated tabs. |
| 43 | |
| 44 | Extract: `eval "$(python scripts/extract-listings.py)"` |
| 45 | |
| 46 | Output example: |
| 47 | ```json |
| 48 | { |
| 49 | "error": false, |
| 50 | "url": "https://www.etsy.com/shop/Xcraftsman?ref=items-pagination&page=2&sort_order=custom", // page URL |
| 51 | "currentPage": 2, // current page number parsed from URL, defaults 1 |
| 52 | "count": 44, // number of unique listings on the page |
| 53 | "nextPageUrl": "https://www.etsy.com/shop/Xcraftsman?ref=items-pagination&page=3&sort_order=custom", // URL of next page, null on last page |
| 54 | "listings": [ |
| 55 | { |
| 56 | "listingId": "4332558944", // Etsy listing id |
| 57 | "shopId": "13350861", // Etsy shop id (same across the whole shop) |
| 58 | "title": "Handmade Leather Bifold Wallet", // product title |
| 59 | "url": "https://www.etsy.com/listing/4332558944/…", // canonical listing URL, tracking params stripped |
| 60 | "image": "https://i.etsystatic.com/…/il_794xN.….jpg", // primary product image |
| 61 | "salePrice": "$120.00", // current display price |
| 62 | "originalPrice": null, // original / crossed-out price, null when no discount |
| 63 | "currency": "$", // currency symbol as shown to user |
| 64 | "rating": 4.8, // average star rating on the shop card, null when card shows none |
| 65 | "reviewCount": "455", // review count as displayed |
| 66 | "shopName": "Xcraftsman", // shop / seller display name (same for all cards) |
| 67 | "isAd": false, // typically false on shop pages |
| 68 | "freeShipping": true, // true when "Free shipping" badge shown |
| 69 | "badge": null, // ranked badge text or null |
| 70 | "positionIndex": 0 // 0-based position within the page |
| 71 | } |
| 72 | ] |
| 73 | } |
| 74 | ``` |
| 75 | |
| 76 | Error handling: |
| 77 | - `{"error": true, "message": "blocked by anti-bot verification page"}` — DataDome interstitial |