# Poshmark Scraper & Price Monitor - Brand Listings, Prices (`neverempty/poshmark-listings-monitor`) Actor

Poshmark listings by brand, department and category: price, original retail price, first listed price, size, condition (NWT, Like New), likes and listed date. Monitor mode returns only new listings and price drops. No seller names. No login. Export as JSON, CSV or Excel. Unofficial.

- **URL**: https://apify.com/neverempty/poshmark-listings-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.99 / 1,000 listing returneds

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

## Poshmark Scraper & Price Monitor - Brand Listings, Prices

Get **Poshmark** listings by **brand**, optionally narrowed to a **department and category** (for example Nike / Women / Shoes): title, **price in USD, original retail price, first listed price and how much it dropped since**, size, condition (**NWT, Like New, Good, Fair**), colors, likes, comments, availability, **listed date**, photo and link. **Monitor mode** returns only listings that are **new** on the list and **price drops** since the last check, so it can run on a schedule and send a reseller only what changed.

Unofficial. Reads public brand pages only, without logging in. Not affiliated with Poshmark.

### What makes this one different

- **Built for resellers watching a brand.** Sort by *Just in* (the default) and turn on monitor mode: every run returns the listings that appeared since the last run, and the listings whose price dropped. A Nike list gets dozens of new listings an hour; narrow it with a department and category (Nike / Women / Shoes) to watch a niche.
- **Price history on every row, even without monitor mode.** `firstListedPrice` is the price the listing was first posted at, and `changeSinceListed` is the difference to today's price. A negative number means the seller already cut the price.
- **No wrong lists.** If you ask for a category Poshmark does not know (a typo such as *Sheos*), Poshmark quietly answers with the whole department. This Actor checks which department and category Poshmark actually applied, and if it is not what you asked for it returns a **free** `unknown-department-or-category` row that lists the categories Poshmark does know, instead of charging you for the wrong list.
- **No seller names.** Poshmark sellers are mostly private people. This Actor does not return seller names, usernames or profile links, and it removes e-mail addresses, phone numbers and @usernames from titles and descriptions.
- **Condition in plain words.** `condition` keeps Poshmark's own code (`nwt`, `uln`, `ug`, `uf`) and `conditionLabel` gives the name Poshmark's own page uses for it (New With Tags (NWT), Like New, Good, Fair). Codes Poshmark's page does not name are left as the code, not guessed.
- **The count you ask for is the count you get**, up to 240 per brand (48 per page, up to 5 pages). If there were more listings than you got, a free row says so.

### Output fields

| Field | What it is |
|---|---|
| `listingId`, `url` | Poshmark listing ID and listing page |
| `title`, `brand` | Listing title and the brand Poshmark has on it |
| `price`, `currency` | Price now (USD) |
| `originalRetailPrice` | The original retail price the seller entered (empty when the seller left it out) |
| `firstListedPrice`, `changeSinceListed` | Price when first listed and the change to today's price (negative = cheaper now) |
| `previousPrice`, `priceChange`, `priceChangePercent` | Monitor mode: the price this watch saw last time and the change |
| `size`, `sizeSystem` | Size as Poshmark shows it, and the size system (for example `us`) |
| `condition`, `conditionLabel` | Poshmark's condition code and its name |
| `department`, `category`, `subcategories` | For example Women / Shoes / Sneakers |
| `colors`, `styleTags` | Colors and style tags the seller chose |
| `likeCount`, `commentCount`, `shareCount` | Counts on the listing |
| `availability`, `multiSize`, `shippingDiscount` | Poshmark's availability status, whether the listing sells several sizes, and the shipping discount type Poshmark shows |
| `listedAt`, `updatedAt` | When the listing was first published and last updated (UTC) |
| `description` | The seller's description (contacts removed); empty when `includeDescription` is off |
| `imageUrl` | Cover photo |
| `page`, `positionOnPage`, `listingsInBrandList` | Where it was on the list, and the list size Poshmark reports (Poshmark caps this at 5,000) |
| `changeType` | Monitor mode: `first-check`, `new-in-results` or `price-change` |
| `charged` | `true` on listing rows (charged), `false` on the free rows that explain something |
| `searchBrand`, `searchDepartment`, `searchCategory`, `searchSort`, `searchUrl` | Which list the row came from |
| `status`, `note` | `ok` for a listing; otherwise why nothing was returned (free) |

### Input

- **Brands** (`brands`): brand names as Poshmark writes them, for example `Nike`, `Free People`, `Lululemon Athletica`, `Off-White`. Empty Brands and Brand URLs runs the example brand Nike.
- **Department** and **Category** (`department`, `category`, optional): for example `Women` and `Shoes`. Category needs a department.
- **Brand URLs** (`brandUrls`, optional): Poshmark brand pages copied from your browser, such as `https://poshmark.com/brand/Nike-Women-Shoes?sort_by=added_desc`. The brand, department, category and sort are used; other URL filters are not (the log says which were ignored). Search, closet and single listing pages are not accepted (Poshmark's robots.txt does not allow search pages).
- **Sort order** (`sort`): Just in (newest first, default), price low to high, price high to low, most liked, or Poshmark's relevance order.
- **Max listings per brand** (`maxResultsPerSearch`, default 48, up to 240) and **Pages per brand** (`maxPages`, 1 to 5).
- **Include the listing description** (`includeDescription`, default on).
- **Monitor mode** settings: `onlyNew`, `priceChangeAlerts` (drops, any, off), `watchName`, `resetMonitoringState`.

Up to 10 brand lists per run.

### Monitor mode

1. First run: returns up to `maxResultsPerSearch` listings (`first-check`) and remembers the list.
2. Next runs: read the same pages and return only
   - `new-in-results`: a listing this watch has not seen on this list before. With the default *Just in* sort, these are listings newly posted to Poshmark (`listedAt` says when).
   - `price-change`: a price drop (or any change, with `priceChangeAlerts: any`) on a listing still on the pages this watch reads, with `previousPrice`, `priceChange` and `priceChangePercent`.
3. If a page cannot be read, the watch judges nothing for that list: nothing is returned, remembered or charged, and the next run checks again.
4. If a run reaches your maximum charge, the listings it could not return are returned by the next run.

Watch the **Just in** order (the default). Poshmark's other orders are not stable between requests: on 2026-10-09, two requests of the same *most liked* list a minute apart shared only 21 to 43 of about 46 listings, and the price orders put many equal prices in a different order every time. A watch on those orders would report reshuffled listings as new. Prices of the listings seen in both requests matched in every case.

How often to run it: on 2026-10-09 the Nike list (all departments) got about 48 new listings in 3 minutes, while Nike / Women / Shoes got far fewer. A busy brand needs a narrower list or more pages per run, or new listings can scroll past the pages read between two runs.

### Pricing

Pay per event:

- **Run start**: one small fee per run (not per page and not per GB of memory).
- **Listing returned**: per listing row.

Explanation rows are free. A run that finds nothing is not charged at all. In monitor mode, the run start fee is the price of the check itself, so it is charged even when nothing changed. Set a maximum charge per run and the Actor will not start a run that cannot return at least one listing.

### Reliability

- Reads the plain brand page; no browser, no login, no cookies. Measured 2026-10-09 from Apify's datacenter network: every brand page request answered (14 of 14), no check page.
- If Poshmark refuses an IP address (403, 429, 5xx), the Actor asks again from other datacenter IPs.
- If Poshmark shows a check page, the Actor **does not solve or bypass it**: it stops, returns a free row and remembers nothing.
- Poshmark's robots.txt is checked on every run and every URL is checked against it before it is requested. Only brand pages (`/brand/…`) are read; search, listing and closet pages are not opened.
- Sold listings are not included: Poshmark shows only available listings to visitors who are not logged in (the sold filter sends them back to the available list).

### Example output

```json
{
  "status": "ok",
  "charged": true,
  "listingId": "6ac80000a1b2c3d4e5f60718",
  "title": "Nike Air Max 90 White Grey",
  "brand": "Nike",
  "price": 45,
  "currency": "USD",
  "originalRetailPrice": 130,
  "firstListedPrice": 60,
  "changeSinceListed": -15,
  "size": "8.5",
  "sizeSystem": "us",
  "condition": "uln",
  "conditionLabel": "Like New",
  "department": "Women",
  "category": "Shoes",
  "subcategories": ["Sneakers"],
  "colors": ["White", "Gray"],
  "likeCount": 12,
  "availability": "available",
  "listedAt": "2026-10-08T21:14:05.000Z",
  "url": "https://poshmark.com/listing/Nike-Air-Max-90-White-Grey-6ac80000a1b2c3d4e5f60718",
  "searchBrand": "Nike",
  "searchDepartment": "Women",
  "searchCategory": "Shoes",
  "searchSort": "newest"
}
```

(Shortened. Values are illustrative.)

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `brands` (type: `array`):

Brand names as Poshmark writes them, for example Nike, Free People, Lululemon Athletica, Off-White. Each brand is one list. Leave Brands and Brand URLs both empty to run the example brand Nike.

## `department` (type: `string`):

Optional. Only listings in this Poshmark department, applied to every brand in Brands. Empty = all departments.

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

Optional, needs a Department. A Poshmark category inside that department, for example Shoes, Jackets & Coats, Bags, Dresses, Pants & Jumpsuits. If Poshmark does not know it, that brand returns a free row listing the categories it does know. Empty = all categories.

## `brandUrls` (type: `array`):

Optional. Poshmark brand pages copied from your browser, for example https://poshmark.com/brand/Nike-Women-Shoes?sort_by=added_desc. The brand, department, category and sort order are used; other filters in the URL are not (the run log says which were ignored). Search, closet and single listing pages are not accepted.

## `sort` (type: `string`):

Sort order for every list (overrides the order in a pasted URL). Empty = Just in (newest first), which is also the list monitor mode watches for new listings.

## `maxResultsPerSearch` (type: `integer`):

Most listings returned for one brand list (Poshmark shows 48 per page). Empty = 48. In monitor mode it limits the listings returned per brand in one run; the rest come in the next run.

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

How many pages (48 listings each) to read for each brand list, 1 to 5. Empty = just enough pages for Max listings per brand. In monitor mode every run reads this many pages and compares them.

## `includeDescription` (type: `boolean`):

On (default): return the seller's description text, with e-mail addresses, phone numbers and @usernames removed. Off: leave the description empty.

## `onlyNew` (type: `boolean`):

On: every run reads the same pages of each brand list and returns only listings that appear in that list for the first time (changeType new-in-results) and listings whose price changed as set in Price change alerts (changeType price-change, with previousPrice). The first run returns up to Max listings per brand (changeType first-check) and remembers them as the starting point. Each run that reads the list is charged the run start fee; runs where nothing changed return a free row saying so.

## `priceChangeAlerts` (type: `string`):

Which price changes monitor mode returns, compared with the price this watch saw last time. Only listings still on the pages this watch reads can be compared. Empty = price drops only.

## `watchName` (type: `string`):

Optional. Keeps separate memories for monitor mode, for example one per client (letters, digits, dot, dash, underscore; up to 40). Runs with the same watch name and brand list share what has already been returned.

## `resetMonitoringState` (type: `boolean`):

On: forget what this watch has seen for these brand lists before running, so this run is a first check again. Off or empty: keep the memory.

## Actor input object example

```json
{
  "brands": [
    "Nike"
  ],
  "maxResultsPerSearch": 48,
  "includeDescription": true,
  "priceChangeAlerts": "drops"
}
```

# Actor output Schema

## `results` (type: `string`):

One row per Poshmark listing on the brand list: listing ID, title, brand, price in USD, original retail price, first listed price and the change since then, size, condition, department, category, colors, likes, availability, listed date, photo and link. Monitor mode marks rows first-check, new-in-results or price-change (with the previous price). A brand with no listings, an unknown department or category, nothing changed, a check page, a refused request or a run that hit its maximum charge comes back as a free row that says why.

# 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 = {
    "brands": [
        "Nike"
    ],
    "maxResultsPerSearch": 48
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/poshmark-listings-monitor").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 = {
    "brands": ["Nike"],
    "maxResultsPerSearch": 48,
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/poshmark-listings-monitor").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 '{
  "brands": [
    "Nike"
  ],
  "maxResultsPerSearch": 48
}' |
apify call neverempty/poshmark-listings-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/poshmark-listings-monitor"
        }
    }
}
```

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/iPJdru9ZkB9z9BjI2/builds/TY1IR6jhVWfNobBOx/openapi.json
