Curtsy Fashion Resale Scraper - Listings, Sellers & Reviews
Pricing
from $1.10 / 1,000 listing records
Curtsy Fashion Resale Scraper - Listings, Sellers & Reviews
Scrape Curtsy, the US secondhand fashion marketplace: listings with brand, size, list vs original retail price, condition, photos and seller profile. Keyword and brand search, category browse, item and closet links, seller reviews, incremental monitoring, resume, MCP export.
Pricing
from $1.10 / 1,000 listing records
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
Curtsy Scraper: Secondhand Fashion Listings, Sellers & Reviews
Curtsy Scraper turns Curtsy (curtsyapp.com), the US secondhand fashion marketplace, into a clean product data API. Collect listings across 1000+ brands (Lululemon, Free People, Zara and more) with brand, size, list price vs original retail price, condition, photos and seller profile. Search by keyword or brand, browse a category, paste item, closet or collection links, attach seller review entries and listing comments, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.
Why This Scraper?
- Three ways in. Keyword search, brand or category browse, or paste item, closet and collection links. No need to build URLs by hand.
- List vs retail pricing. Every record carries the list price, the original retail price and the suggested price, so resale margins are computable straight from the dataset.
- Seller trust signals. Seller name, sales and purchase counts, positive rating percentage, response time, time to ship and state, plus seller review entries (rating, date, text) and listing comments.
- Detail depth on demand. Switch the detail record, seller reviews and comments on or off per run, and pay only for what you use.
- Built for schedules. Incremental mode returns only new and changed listings on recurring runs, and a refused run fails loudly instead of returning an empty dataset.
- Full photo sets. Every listing ships the complete photo gallery, not just the cover thumbnail.
Use Cases
- Resale arbitrage and sourcing: track list prices against original retail across brands and categories to find underpriced listings early.
- Market and pricing research: build price histories per brand, category or size for fashion-resale analytics.
- Inventory monitoring: watch a seller's closet or a collection and get only the new or changed listings on each scheduled run.
- Trend and demand analysis: correlate heart counts, review volume and time-on-market by brand, color and category.
- App and dashboard builders: feed clean listing records into your own tooling through the API or MCP connectors.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
id | "Ab12Cd34Ef" |
title | "Sample Midi Dress" |
brand | "Sample Brand" |
category | "Dresses" |
size / sizeCategory | "M" / "women" |
condition | "New with tags" or "Pre-owned" |
price | 35 |
retailPrice | 98 |
suggestedPrice | 40 |
priceWithFees | 37.75 |
sold / available | false / true |
loves | 12 |
freeShipping / isSteal / hot / isNew | true / false / false / true |
imageUrl / imageUrls / numImages | full gallery URLs / 4 |
sellerId / sellerName | "k8mbYd8Xuj" / "Seller Name" |
sellerPositiveRatings | "98%" |
sellerSales / sellerPurchases | 22 / 54 |
sellerResponseTime / sellerTimeToShip | "1 day" / "2.4 days" |
postedAt | "2026-01-01T00:00:00.000Z" |
description | seller description (with details on) |
userSizing | seller sizing note (with details on) |
sellerReviews | rating, date, text, reviewer avatar |
comments | author, text, date, type |
url | listing link |
Closet runs also resolve the seller profile behind the closet; collection runs walk the whole collection feed.
How to Use
- Pick a mode: search (keyword, brand or category) or URL mode (paste links).
- Fill in the fields for that mode, and switch on details, reviews and the filters you need.
- Set Max items to control run size and cost, then click Start.
- Download the dataset as JSON, CSV or Excel, or read it through the API.
Browse a brand:
{"mode": "search","brand": "Lululemon","maxItems": 50}
Keyword search with detail records:
{"mode": "search","query": "yellow dress","fetchDetails": true,"fetchReviews": true,"maxItems": 50}
Category browse with price filters:
{"mode": "search","category": "dresses","priceMin": 20,"priceMax": 80,"color": "floral","maxItems": 100}
Paste item, closet or collection links:
{"mode": "url","startUrls": ["https://curtsyapp.com/item/sample-route/Ab12Cd34Ef","https://curtsyapp.com/closet/SampleId1"],"fetchDetails": true,"maxItems": 50}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("abotapi/curtsy-app-scraper").call(run_input={"mode": "search","brand": "Lululemon","maxItems": 50,})for item in client.dataset(run["defaultDatasetId"]).iterate_dataset_items():print(item)
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('abotapi/curtsy-app-scraper').call({mode: 'search',brand: 'Lululemon',maxItems: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
You can also export the dataset to JSON, CSV, Excel, or integrate it with Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Tips
- Max items is the only cap that stops a run early. Pages walk forward until the cap is reached or listings run out; Max pages exists as an optional extra guard and defaults to no cap.
- Details and reviews cost extra reads. With Read listing details on, every listing is billed once as detail enrichment. Each delivered review and comment is billed individually. Turn them off for a leaner run.
- Resume a large pull. Paste a previous run ID into Resume from a previous run to continue where it stopped without returning the same listings.
- Schedule incremental runs. Turn on incremental mode and the actor remembers what it already delivered: the first run returns every matching listing as NEW, later runs return only NEW and UPDATED. Heart counts and relative time labels never mark a listing UPDATED; a price, retail price, status, seller-stat or review-count change does.
Send results into your apps (MCP connectors)
Results can be piped straight into the apps you already use through Apify MCP connectors. Authorize a connector under Apify, Settings, API & Integrations, then select it in the input. Notion receives a rich page-per-listing export; other connectors receive a best-effort write or digest. This is optional: leave the field empty and the run is unchanged.
| Parameter | Type | Default | Description |
|---|---|---|---|
mcpConnectors | array | empty | Select one or more authorized MCP connectors. |
notionParentPageUrl | string | empty | URL or id of the Notion page under which listing pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. |
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | Search and browse, or paste item, closet and collection links. |
query | string | empty | Free-text search across titles, brands and descriptions. |
brand | string | empty | Brand name, e.g. Lululemon or Free People; normalized to the marketplace's own brand feed. |
category | string | empty | Browse one category, e.g. dresses, tops, shoes, handbags. |
color | string | empty | Single color word applied to the browse feed. |
priceMin | integer | empty | Keep listings listed at or above this price. |
priceMax | integer | empty | Keep listings listed at or below this price. |
freeShippingOnly | boolean | false | Keep only listings the seller ships for free. |
nwtOnly | boolean | false | Keep only listings marked New With Tags (evaluated per listing). |
startUrls | array | sample | URL mode: listing links, closet links, collection links or bare listing ids. |
urls | array | empty | Alias accepted under the name other Apify actors use for URL mode. |
fetchDetails | boolean | true | Merge the detail record: description, sizing note, fees, full photos, seller stats. Billed as detail enrichment per enriched listing. |
fetchReviews | boolean | true | Attach seller review entries and listing comments. Requires Read listing details. Each delivered entry is billed individually. |
maxReviews | integer | 20 | Cap the review entries attached per listing; 0 skips reviews. |
maxItems | integer | 20 | The one cap that stops a run early. |
maxPages | integer | 0 | Optional page cap; zero means no page cap. |
proxyConfiguration | object | {'useApifyProxy': True} | Connection settings; Residential is recommended for large or frequent runs. |
resumeFromRunId | string | empty | Continue one specific interrupted run from its run or dataset ID. |
incrementalMode | boolean | false | Return only NEW and UPDATED listings on recurring runs. |
stateKey | string | empty | Name a monitoring campaign to keep its state stable across config edits. |
emitUnchanged | boolean | false | Also return, and bill, unchanged listings. |
emitExpired | boolean | false | Also return, and bill, listings no longer found once a run fully scanned the search. |
ignoreFieldsForChanges | array | empty | Extra fields excluded from change detection on top of the defaults. |
mcpConnectors | array | empty | MCP connectors; see the section above. |
notionParentPageUrl | string | empty | Notion parent page for the page-per-listing export. |
maxNotifyListings | integer | 50 | Connector write cap per run. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
One listing record with details and reviews:
{"id": "Ab12Cd34Ef","title": "Sample Midi Dress","brand": "Sample Brand","category": "Dresses","size": "M","sizeCategory": "women","condition": "Pre-owned","price": 35,"retailPrice": 98,"suggestedPrice": 40,"priceWithFees": 37.75,"sold": false,"loves": 12,"isNWT": false,"freeShipping": false,"imageUrl": "https://assets.example.com/tr:f-webp,w-180/sample-photo.jpg","imageUrls": ["https://assets.example.com/tr:f-webp,w-180/sample-photo.jpg"],"numImages": 4,"description": "Full seller description text appears here when details are on.","userSizing": "Seller is 5'6\", 130lbs","sellerId": "SampleId2","sellerName": "Seller Name","sellerPositiveRatings": "98%","sellerSales": 22,"sellerPurchases": 54,"sellerTimeToShip": "2.4 days","postedAt": "2026-01-01T00:00:00.000Z","sellerReviews": [{"reviewRating": 5,"reviewText": "Great seller, fast shipping!","reviewDate": "2026-07-02","reviewerAvatar": "https://assets.example.com/sample-avatar.jpg"}],"sellerReviewsCount": 27,"comments": [],"commentsCount": 0,"url": "https://curtsyapp.com/item/sample-route/Ab12Cd34Ef","detailUrl": "https://curtsyapp.com/item/sample-route/Ab12Cd34Ef","changeType": "NEW","changedFields": [],"firstSeenAt": "2026-01-01T00:00:00.000Z","lastSeenAt": "2026-01-01T00:00:00.000Z"}
Plan Requirement
This actor uses Apify's pay-per-event pricing: each listing record, each detail-enriched listing, each delivered review entry and each delivered comment entry is billed per the Pricing tab. Connection usage is billed by Apify as usual.
FAQ
How much does it cost?
You pay per event: one charge per listing record, one per detail-enriched listing, one per delivered review entry and one per delivered comment entry, plus the usual Apify compute and connection usage. See the Pricing tab for the exact per-event prices; Max items bounds a run's size and cost.
Is it legal to scrape Curtsy?
This actor collects only publicly available listing data. You are responsible for using it in line with the site's terms of use, applicable privacy law (GDPR, CCPA) and your own regulations; listings carry personal data (seller names, review authors), so have a lawful basis before processing it.
Can I get only new or changed listings on a schedule?
Yes. Turn on Incremental changes for scheduled runs: the first run returns everything as NEW, later runs return only NEW and UPDATED listings, and optionally EXPIRED ones with Emit expired records. Use State key to keep a monitoring campaign stable across configuration edits.
Why did a run return fewer results than Max items?
Searches and filters can legitimately match fewer listings than the cap, and keyword searches return a fixed-size result set (the marketplace caps them), so a keyword run stops once that set is delivered. Raise Max items or widen the filters to collect more.
Why did my run fail instead of returning an empty dataset?
If the marketplace refuses every read (a connection problem rather than an empty search), the run fails loudly with a message instead of pretending nothing matched. Re-run it shortly; transient connection problems usually clear on their own.
Can I use it with AI agents or MCP?
Yes. The actor ships an MCP connector surface: authorize a connector under Apify, Settings, API & Integrations, select it in the input, and results are written to your app after every run. The dataset is also readable through the API for any agent framework.
🔗 Want more classifieds data?
Pair this actor with these related scrapers from the same team:
| 🏷️ Poshmark Scraper Scrape Poshmark fashion-resale listings: keyword search, brand and category browse, sold... | 🏷️ Vinted Multi-Country Scraper Scrape Vinted across 27 country marketplaces: keyword search with brand, price and... |
| 🏷️ ThredUp Scraper Scrape ThredUp resale listings by keyword, department, brand, size, condition, price or... | 👗 Showpo Scraper Scrape Showpo women's fashion by keyword, collection or URL. Extract product prices... |
| 🏷️ Vinted.fr Scrape Vinted.fr, France's C2C second-hand fashion marketplace: search with... | 👗 24S Scraper Scrape 24S luxury fashion by category, filters, or URL. Extract brand, name, price... |
💬 Support
- 🐞 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 contact@abotapi.com.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.