Etsy Products
Research a niche before you open a shop, price your products against the market, or track the tags and best sellers of competing shops. Give it keywords, Etsy category links or listing URLs and it returns one JSON row per listing: price and sale price, favorites, the listing's own rating and review count, tags, materials, variations, shipping and delivery estimate, and the shop's sales count and rating. Review text is optional.
Sample output
One row as the API returns it. Long text is shortened here; names inside text read [name].
| Field | Value |
|---|---|
| rowType | listing |
| platform | etsy |
| listingId | 962939986 |
| title | Leather Envelope Wallet for Women, Personalized Mini Card Wallet, Full Grain Crazy Horse |
| url | https://www.etsy.com/listing/962939986 |
| price | 64 |
| currency | USD |
| salePrice | 57.6 |
| discountPercent | 10 |
| onSale | true |
| favorites | 4,979 |
| rating | 4.95 |
Call it from code or from your agent
This is the request. Small runs answer in the same call; large ones return a run ID.
curl -X POST https://scrapers-api.arcadiumdata.io/v1/scrapers/etsy-products/runs \
-H "Authorization: Bearer $ARCADIUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"searchTerms": [
"ceramic mug"
],
"maxResultsPerSearch": 20
}
}'What each row holds
Every row says what it is in rowType: listing rows are charged, coverage and error rows are free.
The listing 46 fields
| Field | Type | What it holds |
|---|---|---|
| platform | string | Always 'etsy'. |
| listingId | string | Etsy listing id (the number in the listing URL). Listing and review rows. |
| url | string | Listing page URL. |
| title | string | Listing title as the seller wrote it. |
| description | Listing description (first 300 characters by default, full or none on request). Emails and phone numbers removed. | |
| price | number | Price before any sale, in 'currency' (the seller's currency). Lowest variation price when prices vary. |
| currency | string | Currency code of price and salePrice, e.g. USD, EUR, GBP. |
| salePrice | number | Price during a running sale, in 'currency'; null when not on sale. |
| discountPercent | number | Sale discount in percent; null when not on sale. |
| onSale | boolean | True when a sale discount is running. |
| priceUsd | The price converted by Etsy to US dollars. | |
| quantity | Items in stock as the listing states. | |
| isAvailable | True when the listing can be bought now. | |
| isSoldOut | True when the listing is sold out. | |
| favorites | number | How many shoppers saved the listing as a favorite. |
| rating | number | Average star rating of this listing (not the shop), 1 to 5; null without reviews. |
| reviewCount | number | Number of reviews of this listing. |
| ratingCounts | Reviews of this listing per star, e.g. {'5': 236, '4': 6, '3': 2, '2': 0, '1': 1}. | |
| tags | array | The seller's search tags (up to 13). |
| materials | array | Materials the seller lists. |
| category | string | Etsy category of the listing, e.g. Wallets. |
| categoryPath | Full category path, e.g. Bags and purses > Wallets and money clips > Wallets. | |
| taxonomyId | Etsy taxonomy id of the category. | |
| variations | array | Buyer options, e.g. [{name: 'Primary color', options: [{value: 'Tan', price: 64, available: true}]}]. Option price is null when the option does not change the price. |
| hasVariationPricing | True when the price depends on the chosen option. | |
| images | Full-size image URLs, main image first. | |
| whenMade | string | When the item was made as Etsy states it, e.g. 'made_to_order', '2020_2026', 'before_2006'. |
| isDigital | True for digital downloads (no shipping). | |
| isCustomizable | True when the item can be personalized. | |
| isMadeToOrder | True when the item is made after the order. | |
| isBestseller | True when the listing carries Etsy's Bestseller badge. | |
| shipsFromCountry | string | Country code the item ships from, e.g. US, TR. |
| shipping | object | Shipping as Etsy shows it to a US shopper: {shipsFrom, freeShipping, cost, costText, deliveryEstimate, deliverTo, returns}. Null for digital items or when 'includeShipping' is off. |
| shopSection | The shop's own section the listing is in. | |
| shop | object | The shop as a business: {shopId, shopName, url, sales, rating, reviewCount, location, country, activeListings, favorites, openedAt, isStarSeller}. No owner names. |
| createdAt | Listing date Etsy keeps (ISO). A renewal resets it. | |
| updatedAt | Last change of the listing (ISO). | |
| isAd | boolean | True for a paid placement (only with includeAds; no searchRank). |
| searchInput | string | The search term or URL that found the listing; null for a listing URL input. |
| searchRank | number | 1-based organic position in the results of searchInput. |
| reviewId | Review rows: Etsy's transaction id of the reviewed purchase, unique per review. | |
| text | Review rows: the review text with personal names, emails and phone numbers removed; null for a rating without text. | |
| date | Review rows: review date (YYYY-MM-DD). | |
| sellerResponse | Review rows: the shop's public reply, if any. | |
| hasPhoto | Review rows: true when the buyer attached a photo (not exported). | |
| scrapedAt | When the row was collected (ISO). |
Error rows, free 3 fields
| Field | Type | What it holds |
|---|---|---|
| input | Error rows: the input (term, URL or id) that failed. | |
| code | Error rows: invalid_input, not_found, blocked, unavailable, filter_unsupported or no_match. | |
| message | Error rows: what went wrong, in plain words. |
What it can't do
- It does not return seller contact details such as names, emails or phone numbers.
- Prices are what the site shows at run time, in the currency the site shows.
- It reads only what the site shows to a visitor without an account.
What you send
Every field is optional. The example request above fills the ones shown here.
| Field | Type | What it does |
|---|---|---|
| searchTerms | array | Keywords to search Etsy for, for example "ceramic mug" or "personalized necklace". Each term is searched on its own; every listing keeps the term and its position in the results. Also read from queries, searchQueries, searchQuery, search or keywords (other Etsy actors' names). |
| maxResultsPerSearch | integer | Listings per search term or search/category URL, e.g. 50 (the default). Each page holds 40 to 64 results; Etsy pages up to about 250 pages deep. Also read from maxResults, maxResultsPerTerm, maxListings or maxPages (x 36). |
More options (14)
| Field | Type | What it does |
|---|---|---|
| startUrls | array | Listing URLs or ids (e.g. https://www.etsy.com/listing/962939986 or 962939986) for full details, and search or category URLs (e.g. https://www.etsy.com/c/jewelry/necklaces) to read their results. Also read from listingUrls, urls or listingIds; objects with a url field work too. |
| maxItems | integer | Optional cap on charged rows (listings plus reviews) for the whole run, e.g. 500. Empty means no cap beyond the per-search limit. |
| sortBy | string (one of 5) | Order of search results: relevance (Etsy's default), newest, price_asc, price_desc or top_reviews, for example newest. Also read from sort, sortOrder or sortOn (other Etsy actors' names and values). |
| minPrice | number | Only listings priced at or above this amount, in the shopper currency (US dollars for the default US storefront), e.g. 20. |
| maxPrice | number | Only listings priced at or below this amount, in US dollars, e.g. 60. |
| shipTo | string | Two-letter country code the items must ship to, e.g. US, GB or DE. Empty means any. |
| freeShipping | boolean | Only listings that ship for free (to the US storefront). |
| onSale | boolean | Only listings with a running discount (salePrice and discountPercent are filled). |
| includeAds | boolean | Also return the sponsored listings shown among the results (isAd: true, no rank). Off by default; they do not count towards the per-search limit.Default false |
| maxReviewsPerListing | integer | Newest reviews to return per listing as separate review rows (text, rating, date, shop reply; no reviewer names), e.g. 20. 0 = none (the default); the rating summary is always on the listing. |
| reviewSort | string (one of 4) | Which reviews come first when reviews are requested: newest, relevance, highest or lowest rating.Default "newest" |
| description | string (one of 3) | Listing description in the output: short (first 300 characters, the default), full, or none. Emails and phone numbers are removed. |
| includeShipping | boolean | Adds the shipping block per listing: ships from, free or cost, delivery estimate to the US and the returns policy.Default true |
| includeErrorRows | boolean | Adds a free row for every input that returned nothing or could not be read, so a failure is never silent.Default true |
Questions people ask before they top up
What does a run cost?
Each listing costs $0.0035, which is $3.50 per 1,000. A run that delivers rows also pays a $0.002 start fee.
Listing reviews: $1.00 per 1,000.
A run that returns rows costs at least $0.005, start fee included. Failed runs, empty runs and duplicate rows cost $0. You set the most a run may cost, and it stops there.
Do you ever return personal data?
Not about reviewers or users. Reviewer names, profile links, photos, emails and phone numbers are not collected. When a name appears inside a review or a reply, it is replaced with [name].
Job titles and company sizes stay where a site shows them, because they describe a role rather than a person. On YouTube, channel names and URLs are the publisher labels YouTube shows publicly.
How fresh is the data?
Each run reads the live site when you start it, so rows are as current as the site itself.
More from E-commerce sourcing
Price tiers, minimum order, units sold, repurchase rate, supplier scores
$1.50per 1,000 products
Price, discount, units sold, rating, ships from, search rank
$1.25per 1,000 products