Etsy Scraper - Listings, Prices, Variations & Reviews avatar

Etsy Scraper - Listings, Prices, Variations & Reviews

Pricing

from $1.00 / 1,000 listing results

Go to Apify Store
Etsy Scraper - Listings, Prices, Variations & Reviews

Etsy Scraper - Listings, Prices, Variations & Reviews

Scrape Etsy listings by keyword, category, or URL. Extract titles, shops, prices, discounts, availability, images, categories, and variations. Optional detail mode adds descriptions, materials, shipping origin, and item-level reviews. Supports incremental monitoring.

Pricing

from $1.00 / 1,000 listing results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

8

Total users

4

Monthly active users

10 days ago

Last modified

Share

Etsy Scraper: Listings, Prices, Shops & Reviews

Etsy Scraper turns Etsy into a clean marketplace data feed. Search by keyword and/or category, or paste listing, shop, category and search links directly, and get back one flat record per listing: title, shop, price, was-price, discount and images, plus, when detail fetching is on, availability, category, variations, the full description, materials, shipping origin, rating breakdown and item-level reviews. Run it once for a snapshot, or turn on Incremental mode for scheduled runs that return only new and changed listings, then export to JSON, CSV or Excel, or pull results straight into your app through the API.

Why This Scraper?

  • Two ways to find listings. Search by keyword and/or category with Etsy's own price, sale, shipping and personalizable filters, or paste links directly. No need to build search URLs by hand.
  • One flat record per listing. Title, shop, price, was-price/discount and images come back on every listing straight from the search results.
  • Full detail on demand. Switch on listing detail to add availability, category, variations, description, materials, shipping origin, rating breakdown and item-level reviews, or leave it off for a lighter, faster run.
  • Mixed link input. Drop listing links, bare listing ids, category/search links and shop links into the same list; the actor routes each one automatically.
  • Built for schedules. Incremental mode returns only new and updated listings on recurring runs (unchanged ones are suppressed), and a refused run fails loudly instead of returning an empty dataset.
  • Resume large crawls. Continue one interrupted run without re-collecting or double-charging listings already gathered, and long runs survive a platform migration without losing progress.
  • Send results into your apps. Pipe listings straight into Notion, Linear or Airtable through MCP connectors, on top of the Apify dataset.

Use Cases

  • Price monitoring and repricing: track a set of listings or a whole category for price drops, new sales and stock changes.
  • Competitive research: compare shops, pricing and review scores across a niche or category.
  • Marketplace analytics: build historical datasets of prices, discounts and ratings for trend analysis.
  • Sourcing research: shortlist suppliers by category, price range, shipping origin and rating.
  • Content and SEO teams: pull titles, categories and reviews to power gift guides or product roundups.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
listingId"4530068104"
title"Personalized initial keychain, custom letter charm"
url"https://www.etsy.com/listing/4530068104/personalized-initial-keychain"
shopId"14528878"
shopName"ExampleCraftStudio"
shopUrl"https://www.etsy.com/shop/ExampleCraftStudio"
categoryPath["Accessories", "Keychains & Lanyards", "Keychains"] ([] unless detail fetching is on)
price16.0
currency"USD"
originalPricenull full price, or the pre-sale price when the seller marked it down
discountPercentagenull full price, or the percentage off when on sale
onSalefalse
availability"in_stock" (also "out_of_stock", "sold_out"; null unless detail fetching is on)
quantityAvailable38 (when detail fetching is on)
images["https://i.etsystatic.com/example/il_fullxfull.example.jpg"]
videoUrlnull when the listing has no video
descriptionfull listing description text (when detail fetching is on)
materials["Cotton", "Felt"] (when detail fetching is on)
shippingOrigin{"addressCountry": "US", "addressRegion": "MI"} (when detail fetching is on)
rating5.0 (when detail fetching is on)
reviewCount2 (when detail fetching is on)
ratingBreakdownitem quality, shipping, customer service and buyers-recommend scores (when detail fetching is on)
reviewsitem-level reviews nested under the listing, each with reviewAuthor, reviewRating, reviewDate, reviewBody, reviewPhotos (when detail fetching is on)
variationsoption groups such as color or size, each option with an id and label (when detail fetching is on)
searchMode"search", or "browse" (a pasted category/search/shop link), or "listing" (a pasted listing link or id)

When Incremental mode is on, every returned record also carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields (the top-level fields that changed, populated only for UPDATED), and firstSeenAt/lastSeenAt timestamps.

How to Use

  1. Pick a mode: search (keyword and/or category path, with filters), url (paste Etsy links), or reviews (collect item-level reviews for the listings your sources point at).
  2. For search mode, fill in Search keywords and/or Category path and any filters; for url mode, paste listing, category, search or shop links into Etsy links.
  3. Turn Fetch listing details on or off, and set Max listings to control run size and cost.
  4. Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.

Search by keyword with filters:

{
"mode": "search",
"queries": ["handmade necklace"],
"onSaleOnly": true,
"maxPrice": 50,
"maxItems": 20
}

Paste links (mixing a listing and a shop):

{
"mode": "url",
"urls": [
"https://www.etsy.com/listing/4530068104/monogram-punch-needle-bag-charm",
"https://www.etsy.com/shop/ExampleCraftStudio"
]
}

Collect item reviews for specific listings:

{
"mode": "reviews",
"urls": [
"https://www.etsy.com/listing/4530068104/monogram-punch-needle-bag-charm"
]
}

Scheduled monitoring of the same search:

{
"mode": "search",
"queries": ["vintage lamp"],
"incrementalMode": true,
"maxItems": 0
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/etsy-marketplace-scraper").call(run_input={"mode": "search", "queries": ["handmade necklace"]})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
print(listing["title"], listing["price"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/etsy-marketplace-scraper').call({ mode: 'search', queries: ['handmade necklace'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Max listings and Max pages

Search and category result pages are walked forward one page at a time until Max listings is reached, Etsy runs out of pages, or a page returns only listings already collected earlier in the same run. Max pages additionally caps how many pages are walked per keyword, category or pasted link before moving to the next one; the default 0 means unlimited, so a run then stops only at Max listings or a repeated page. Max listings is the cap for the whole run; 0 means unlimited.

Resume and recurring updates

There are two different things here, pick the one that matches what you are doing:

  • Resume (resumeFromRunId) continues one specific interrupted or previous large crawl: paste a run id or dataset id and this run skips listings already collected there, returning only the remaining new listings. An automatic same-run checkpoint also protects against a platform migration without any input needed.
  • Incremental mode (incrementalMode) is for a schedule, for example daily: the actor remembers the previous run of the same search by itself, so you never paste a run id. The first run returns everything as NEW. Later runs classify every listing as NEW (first time seen), UPDATED (changed since last run, with changedFields listing what changed) or UNCHANGED (suppressed and not billed unless Emit unchanged listings is on). EXPIRED (no longer found) is only produced once a run has fully scanned the tracked search, meaning Max listings did not cap it and it was not a resume, and only when Emit expired listings is on. A listing only classifies as REAPPEARED if the stored state had already marked it absent from one of those EXPIRED runs; a listing that has simply never been scanned before comes back as NEW, not REAPPEARED. Leave State key empty and the actor derives one automatically from the keywords/links, filters, sort and detail setting; set it yourself to give a monitoring campaign a memorable name. Note that the automatic key does not account for a Category path filter, so two otherwise-identical searches that differ only by category can share state; set a State key to keep them separate.

Send results into your apps (MCP connectors)

Optionally pipe results into the apps you already use through Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each listing, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. If the picker is empty, you have not authorized a connector yet.
  3. For Notion, also set notionParentPageUrl to the page where item pages should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip; it never changes the dataset output.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch for keyword/category plus filters, url to scrape pasted Etsy links directly, or reviews to collect item-level reviews.
queriesarrayno default (prefill: ["handmade necklace"])Keywords to search (search mode). Leave empty and set only Category path to browse a whole category.
categoryPathstringno defaultOptional Etsy category path to scope the search or browse to, e.g. jewelry/necklaces (search mode).
urlsarrayno default (prefill: a sample search link and a sample listing link)Etsy links to scrape directly (url mode): listing links, bare listing ids, category/search links, or shop links, mixed freely.
sortBystringmost_relevantHow Etsy orders the results: relevancy, price ascending/descending, newest first, or highest reviews first.
onSaleOnlybooleanfalseKeep only listings currently on sale.
freeShippingOnlybooleanfalseKeep only listings with free shipping.
personalizableOnlybooleanfalseKeep only listings that can be personalized.
minPriceintegerno defaultKeep only listings priced at or above this amount (USD).
maxPriceintegerno defaultKeep only listings priced at or below this amount (USD).
shipToCountrystringno defaultTwo-letter country code to only show listings that ship there.
fetchDetailsbooleantrueCollect each listing's full detail: description, materials, category breadcrumbs, extra images, shipping origin, variations, rating breakdown and item-level reviews.
includeReviewsbooleantrueNest each listing's item-level reviews under its row (each collected review is billed as a Review event). Turn off to return listing fields only. Always on in Reviews mode.
maxItemsinteger20Maximum number of listings to return across the whole run. 0 means unlimited.
maxPagesinteger0Maximum result pages walked per keyword, category or pasted link. 0 means unlimited.
resumeFromRunIdstringno defaultContinue one specific previous run or dataset without returning or charging for listings already collected there.
incrementalModebooleanfalseTurn on for daily or recurring monitoring: later runs return only new, updated and reappeared listings by default.
stateKeystringno defaultName or share one incremental-mode monitoring campaign's state.
emitUnchangedbooleanfalseIncremental mode only. Also return, and bill, listings unchanged since the last run.
emitExpiredbooleanfalseIncremental mode only. Also return, and bill, listings no longer found, once a run has fully scanned the tracked search.
proxyobjectresidential connection, USApify Proxy connection settings; a residential exit is used by default.
mcpConnectorsarrayno defaultOptional: send a summary of each listing to apps you authorized under Integrations.
notionParentPageUrlstringno defaultNotion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap on items exported to each connector per run. Does not affect the dataset.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"listingId": "4530068104",
"title": "Personalized initial keychain, custom letter charm",
"url": "https://www.etsy.com/listing/4530068104/personalized-initial-keychain",
"shopId": "14528878",
"shopName": "ExampleCraftStudio",
"shopUrl": "https://www.etsy.com/shop/ExampleCraftStudio",
"categoryPath": ["Accessories", "Keychains & Lanyards", "Keychains"],
"price": 16.0,
"currency": "USD",
"originalPrice": null,
"discountPercentage": null,
"onSale": false,
"availability": "in_stock",
"quantityAvailable": 38,
"images": ["https://i.etsystatic.com/example/il_fullxfull.example.jpg"],
"videoUrl": null,
"description": "Full listing description...",
"materials": ["Cotton", "Felt"],
"shippingOrigin": { "addressCountry": "US", "addressRegion": "MI" },
"rating": 5.0,
"reviewCount": 2,
"ratingBreakdown": { "itemQuality": 5.0, "shipping": 5.0, "customerService": 5.0, "buyersRecommend": 100.0 },
"reviews": [
{
"reviewId": "5150597893",
"author": "exampleBuyer1",
"rating": 5,
"date": "Jul 27, 2026",
"body": "Great quality, exactly as described!",
"photos": [],
"helpfulCount": null,
"variantContext": null
},
{
"reviewId": "5150597894",
"author": "exampleBuyer2",
"rating": 5,
"date": "Jul 20, 2026",
"body": "Fast shipping and beautiful packaging.",
"photos": [],
"helpfulCount": null,
"variantContext": null
}
],
"variations": [
{ "name": "Primary color", "options": [{ "variationId": "6788604158", "label": "citron/blue" }] }
],
"searchMode": "search"
}

Plan Requirement

The default proxy setting already selects a residential connection and works out of the box, and the actor automatically falls back to a backup connection and retries when one is refused. For the most reliable results at any volume, keep the residential proxy group selected under Connection.

FAQ

How much does it cost?

You pay per listing returned, plus a detail-enrichment surcharge on each listing whose full detail page was actually fetched, plus a Review event for each item-level review collected (they are nested under their listing, not returned as separate rows). That happens whenever Fetch listing details is on, and it also happens for a pasted listing link regardless of that toggle, since a link you paste directly has no search-card fallback. The surcharge is only ever charged for a listing that is actually returned; a failed or suppressed fetch is never billed. The Pricing tab shows the current rates. Use Max listings to cap the cost of any run.

This actor collects only publicly available marketplace data. You are responsible for how you use it: follow Etsy's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing text, prices and availability are generally facts, but photos, videos and shop branding may be subject to third-party rights.

Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only listings that are new or have changed since the last run; unchanged listings are suppressed and not billed unless you turn on Emit unchanged listings. See "Resume and recurring updates" above for exactly how REAPPEARED and EXPIRED are classified.

What is the difference between Resume and Incremental mode?

Resume (resumeFromRunId) continues one specific previous run: paste its run or dataset id and this run skips listings already collected there, returning only the remaining new ones. It is a one-time continuation. Incremental mode is for running the exact same search again and again, for example daily: the actor remembers its own state and classifies every listing against what it saw last time, without you ever pasting a run id.

Why did my run fail instead of returning an empty dataset?

If every request this run made was refused and not one page could be read, the run fails with a clear connection message instead of quietly returning an empty dataset, so "no listings matched" is never confused with "nothing could be read". Try again in a few minutes, or check your proxy settings. If only some pages failed, you still get what was found, and the run completes normally with a "no listings matched" status when the search is genuinely empty.

How many reviews do I get per listing?

Etsy's listing page renders its most recent review block, typically the latest few reviews and not the listing's full history, and that is exactly what the actor returns under reviews, together with the listing's aggregate rating, review count and rating breakdown. Reviews mode applies the same collection to every listing your sources point at, and the dataset's Reviews view unwinds them to one row per review.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

๐Ÿ”— Want more e-commerce data?

Pair this actor with these related scrapers from the same team:

๐Ÿท Carrefour Spain Scraper
Scrape Carrefour Spain (carrefour.es) products. Search by keyword, browse a category, or...
๐Ÿ›’ Depop Scraper
From $1/1K. Scrape Depop search results, listings, shops, and reviews to JSON, CSV, or...
๐Ÿ›’ Castorama.fr
Scrape Castorama.fr DIY and home-improvement products by keyword, category, or URL...
๐Ÿ›’ Kmart Scraper
Scrape products and customer reviews from Kmart.com.au. Search by keyword or use...
๐Ÿ›’ Nitori Japan Furniture & Home Goods Scraper
Scrape Nitori Japan (nitori-net.jp) furniture and home goods by keyword, category or...
๐Ÿ‘— Mango Scraper
Scrape Mango (shop.mango.com) fashion products: current price plus strike-through Rebajas...

๐Ÿ‘‰ Browse all abotapi scrapers

๐Ÿ’ฌ Support & custom scrapers

  • ๐Ÿž Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • ๐Ÿ› ๏ธ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
  • โญ Enjoying it? A quick review on the actor page helps other users find it.