# Curtsy Fashion Resale Scraper - Listings, Sellers & Reviews (`abotapi/curtsy-app-scraper`) Actor

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.

- **URL**: https://apify.com/abotapi/curtsy-app-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Stats:** 2 total users, 1 monthly users, 91.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.10 / 1,000 listing records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 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

1. Pick a **mode**: search (keyword, brand or category) or URL mode (paste links).
2. Fill in the fields for that mode, and switch on details, reviews and the filters you need.
3. Set **Max items** to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Browse a brand:**

```json
{
    "mode": "search",
    "brand": "Lululemon",
    "maxItems": 50
}
```

**Keyword search with detail records:**

```json
{
    "mode": "search",
    "query": "yellow dress",
    "fetchDetails": true,
    "fetchReviews": true,
    "maxItems": 50
}
```

**Category browse with price filters:**

```json
{
    "mode": "search",
    "category": "dresses",
    "priceMin": 20,
    "priceMax": 80,
    "color": "floral",
    "maxItems": 100
}
```

**Paste item, closet or collection links:**

```json
{
    "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:

```python
from apify_client import ApifyClient

client = 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:

```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:**

```json
{
    "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:

<table>
<tr><td>🏷️ <a href="https://apify.com/abotapi/poshmark-scraper"><b>Poshmark Scraper</b></a><br>Scrape Poshmark fashion-resale listings: keyword search, brand and category browse, sold...</td><td>🏷️ <a href="https://apify.com/abotapi/vinted-marketplace-scraper"><b>Vinted Multi-Country Scraper</b></a><br>Scrape Vinted across 27 country marketplaces: keyword search with brand, price and...</td></tr>
<tr><td>🏷️ <a href="https://apify.com/abotapi/thredup-scraper"><b>ThredUp Scraper</b></a><br>Scrape ThredUp resale listings by keyword, department, brand, size, condition, price or...</td><td>👗 <a href="https://apify.com/abotapi/showpo-com-scraper"><b>Showpo Scraper</b></a><br>Scrape Showpo women's fashion by keyword, collection or URL. Extract product prices...</td></tr>
<tr><td>🏷️ <a href="https://apify.com/abotapi/vinted-fr-scraper"><b>Vinted.fr</b></a><br>Scrape Vinted.fr, France's C2C second-hand fashion marketplace: search with...</td><td>👗 <a href="https://apify.com/abotapi/24s-com-scraper"><b>24S Scraper</b></a><br>Scrape 24S luxury fashion by category, filters, or URL. Extract brand, name, price...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/curtsy-app-scraper/issues/open). 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.

# Actor input Schema

## `mode` (type: `string`):

Search walks the marketplace feed by keyword, brand or category. URL mode reads the specific item, closet or collection links you paste.

## `query` (type: `string`):

Search mode: free-text search, e.g. yellow dress or scrub top. The marketplace matches titles, brands and descriptions. The keyword feed ignores the brand, category, color and price narrowing, and returns a fixed-size result set; the per-listing bounds below still apply.

## `brand` (type: `string`):

Search mode: brand name, e.g. Lululemon, Free People, Zara. Spaces and capitalization are normalized automatically.

## `category` (type: `string`):

Search mode: browse one category of the marketplace.

## `startUrls` (type: `array`):

URL mode: listing links (curtsyapp.com/item/<route>/<id>), seller closet links (curtsyapp.com/closet/<id>, every listing in the closet is read), collection links (curtsyapp.com/collection/<slug>/<id>), or a bare listing id. Entries are read in order.

## `urls` (type: `array`):

Alias for the links field above, accepted under the name other Apify actors use for URL mode. Entries are read in order.

## `priceMin` (type: `integer`):

Keep listings listed at or above this price. Applied to the browse feed.

## `priceMax` (type: `integer`):

Keep listings listed at or below this price. Applied to the browse feed.

## `color` (type: `string`):

Single color word, e.g. yellow, black, floral. Applied to the browse feed (keyword searches ignore it).

## `freeShippingOnly` (type: `boolean`):

Keep only listings the seller ships for free.

## `nwtOnly` (type: `boolean`):

Keep only listings marked New With Tags. Evaluated per listing after it is read.

## `fetchDetails` (type: `boolean`):

Read each listing's detail record: seller description, sizing note, full photo set, fees, and the seller's sales/rating stats. Turn off for a faster card-only run. Each enriched listing is billed once as detail enrichment.

## `fetchReviews` (type: `boolean`):

Attach each listing's seller review entries (rating, date, text, reviewer avatar) and listing comments, up to Max reviews per listing. Requires Read listing details. Reviews are billed per 10 entries as review enrichment; comments likewise as comment enrichment.

## `maxReviews` (type: `integer`):

Cap the seller review entries attached to each listing. 0 skips reviews entirely.

## `maxItems` (type: `integer`):

Stop after this many records. This is THE cap: the run stops when it is reached or when listings run out.

## `maxPages` (type: `integer`):

Advanced. Rarely needed: cap the listing pages read per scope. Zero means no page cap; Max items still stops the run.

## `proxyConfiguration` (type: `object`):

Connection settings. The standard pool is the default and works on every plan; Residential is recommended for the most reliable results on large or frequent runs.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large pull without returning items already collected there.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns every matching listing as NEW. Later runs compare the full listing snapshot (price, retail price, size, condition, seller stats, review and comment counts) against the stored baseline and return only NEW and UPDATED listings. Fast-moving fields that move without the listing changing (heart count, relative time labels) are excluded from the comparison by default, and Ignore fields (below) adds more. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately for each search, filter and link setup; use State key to name or deliberately share a monitoring campaign.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the search, filters and links.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return listings that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search.

## `ignoreFieldsForChanges` (type: `array`):

Incremental mode: changes to only these fields do not mark a record UPDATED. Defaults cover the free-running heart counter and relative time labels; seller review and comment entries count through their totals, so a new review still marks the listing UPDATED.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output.

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "category": "",
  "startUrls": [
    "https://curtsyapp.com/item/showpo-dress/PbFOISYB0P",
    "https://curtsyapp.com/closet/vY8q0ubhYQ"
  ],
  "freeShippingOnly": false,
  "nwtOnly": false,
  "fetchDetails": true,
  "fetchReviews": true,
  "maxReviews": 20,
  "maxItems": 20,
  "maxPages": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `reviews` (type: `string`):

No description

## `comments` (type: `string`):

No description

## `changes` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "category": "",
    "startUrls": [
        "https://curtsyapp.com/item/showpo-dress/PbFOISYB0P",
        "https://curtsyapp.com/closet/vY8q0ubhYQ"
    ],
    "freeShippingOnly": false,
    "nwtOnly": false,
    "fetchDetails": true,
    "fetchReviews": true,
    "maxReviews": 20,
    "maxItems": 20,
    "maxPages": 0,
    "proxyConfiguration": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "maxNotifyListings": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/curtsy-app-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "category": "",
    "startUrls": [
        "https://curtsyapp.com/item/showpo-dress/PbFOISYB0P",
        "https://curtsyapp.com/closet/vY8q0ubhYQ",
    ],
    "freeShippingOnly": False,
    "nwtOnly": False,
    "fetchDetails": True,
    "fetchReviews": True,
    "maxReviews": 20,
    "maxItems": 20,
    "maxPages": 0,
    "proxyConfiguration": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "maxNotifyListings": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/curtsy-app-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "category": "",
  "startUrls": [
    "https://curtsyapp.com/item/showpo-dress/PbFOISYB0P",
    "https://curtsyapp.com/closet/vY8q0ubhYQ"
  ],
  "freeShippingOnly": false,
  "nwtOnly": false,
  "fetchDetails": true,
  "fetchReviews": true,
  "maxReviews": 20,
  "maxItems": 20,
  "maxPages": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50
}' |
apify call abotapi/curtsy-app-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/curtsy-app-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/wYhXeEIMlQwkM7EQ6/builds/JRHM4ZgzKOe8oDD9y/openapi.json
