# OfferUp Scraper | US Marketplace Listings & Prices (`haketa/offerup-scraper`) Actor

OfferUp scraper & API (US classifieds): search listings by keyword and location and export title, price, condition, description, seller, location, photos, date and URL. US marketplace and resale market data plus seller lead generation — fast, no login.

- **URL**: https://apify.com/haketa/offerup-scraper.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** E-commerce, Automation, Lead generation
- **Stats:** 9 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## OfferUp Scraper — US Local Marketplace Listings, Prices, Conditions & Seller Data

> **The most complete OfferUp marketplace data extractor on Apify.** Pull live listings — price, condition, location, shipping flag, full description, image gallery, and seller reputation — from any US ZIP code or metro on demand. Built for **reseller arbitrage, used-car flipping, brand monitoring, ecommerce intelligence, dropshipping research, and second-hand price benchmarking** across America's largest peer-to-peer marketplace at [offerup.com](https://offerup.com).

[![Apify Actor](https://img.shields.io/badge/Apify-Actor-blue)](https://apify.com/haketa/offerup-scraper)
[![Live Data](https://img.shields.io/badge/Data-Live%20at%20Run%20Time-orange)]()
[![Engine](https://img.shields.io/badge/Engine-Playwright%20%2B%20API%20Intercept-green)]()
[![Pay Per Event](https://img.shields.io/badge/Pricing-Pay%20Per%20Event-yellow)]()
[![Coverage](https://img.shields.io/badge/Coverage-All%20US%20ZIPs-purple)]()
[![Region](https://img.shields.io/badge/Region-United%20States-red)]()
[![No Auth](https://img.shields.io/badge/Authentication-None%20Required-success)]()
[![Proxy](https://img.shields.io/badge/Proxy-US%20Residential-lightgrey)]()

---

### What This Actor Does

The **OfferUp Scraper** is a production-ready Apify Actor that extracts public listings from **[OfferUp](https://offerup.com)** — the United States' largest mobile-first local classifieds and peer-to-peer (C2C) marketplace, with tens of millions of monthly active users buying and selling **used phones, laptops, cars, furniture, baby gear, tools, sneakers, gaming consoles, bikes, instruments, appliances, fashion**, and just about everything else across every US state and metro.

Each run takes one or more **search keywords** plus a **city/ZIP and radius**, then returns clean structured JSON listings with the full pricing, condition, location, image, and seller-reputation payload. Optional **detail-page enrichment** dives into each listing for the long-form description, full image gallery, category, and TruYou-verified seller stats.

In a single run the actor returns structured records covering:

- **Listings** — every public OfferUp post matching your keyword and geo filters, including title, price, condition, category, post date, location, shipping availability, image gallery, and direct URL
- **Sellers** — username, star rating, review count, TruYou verified flag, account join date, and total item count
- **Search context** — every record carries the keyword and location it was harvested under, so multi-keyword and multi-metro pulls are trivially groupable downstream
- **Provenance** — `listingUrl`, `listingId`, and `scrapedAt` ISO timestamp on every record so you can audit and de-duplicate across runs

Each record is **flat JSON, schema-stable, deduplicated by listing ID, and ready for direct ingestion** into Postgres, BigQuery, Snowflake, Google Sheets, Airtable, or any BI tool — no parsing scripts, no per-listing DOM scraping, no headless-browser maintenance burden on your end.

#### Why scrape OfferUp yourself when this actor exists?

OfferUp does **not** offer a public data API. The web app is a heavily-defended Next.js single-page application with aggressive anti-bot protection. Teams who try to roll their own scraper invariably hit the same wall:

- **Datacenter IPs are blocked instantly** — OfferUp returns HTTP 403 on the first request from any AWS, GCP, Azure, OVH, Hetzner, or Linode IP range
- **Cloudflare-style JS challenge** on every cold visit — requires a real headless browser to solve, not `requests` or `axios`
- **TLS fingerprint inspection** — Python `requests` and Node `fetch` are rejected even with perfect headers
- **Dynamic listing schema** — OfferUp's internal Apollo cache and `__NEXT_DATA__` payload changes shape every few weeks
- **Infinite-scroll pagination** — no traditional page numbers in the UI; listings load on viewport scroll events
- **Per-IP rate ceilings** — 5–10 search pages from a single IP and you're shadow-blocked for hours
- **Geofencing** — non-US IPs see a stripped-down or redirected UX
- **CAPTCHA escalation** — repeat offenders get full hCaptcha challenges that DIY scrapers cannot solve
- **Detail pages require fresh session warmup** — going straight to `/item/detail/{id}` without homepage cookies returns an empty shell

This actor solves every one of those problems out of the box: **Playwright + stealth patches + US residential proxy rotation + session warmup + API response interception + multi-strategy fallback parsing + automatic 403 retry with fresh IP**. You get reliable, structured OfferUp data without owning a single Docker image.

---

### Quick Start

#### One-Click Run

1. Click **"Try for free"** on the [Apify Store page](https://apify.com/haketa/offerup-scraper)
2. Type one or more **Keywords** (`iphone 15`, `macbook pro`, `peloton bike`, `f150`) and a **Location** (`Los Angeles, CA` or a ZIP like `90001`)
3. Optionally set **Radius**, **Min/Max Price**, **Condition**, and **Delivery Type**, then hit **Start**
4. Download as **JSON, CSV, Excel, HTML, XML, or JSON Lines** directly from the Apify dataset view

#### API Run (Python)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("haketa/offerup-scraper").call(run_input={
    "keywords":      ["iphone 15", "macbook pro 14", "airpods pro"],
    "location":      "Los Angeles, CA",
    "radius":        30,
    "priceMin":      200,
    "priceMax":      1500,
    "condition":     "like_new",
    "deliveryType":  "all",
    "scrapeDetails": True,
    "maxRecords":    500,
    "maxPages":      10,
    "requestDelay":  2000,
})

for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"${listing['price']:>6} {listing['condition'] or '-':<10} "
          f"{listing['title'][:60]:<60} | {listing['location']} | {listing['sellerName']}")
````

#### API Run (Node.js / TypeScript)

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('haketa/offerup-scraper').call({
    keywords:      ['nike air max', 'jordan 1', 'yeezy 350'],
    location:      'New York, NY',
    radius:        20,
    priceMin:      50,
    priceMax:      400,
    condition:     'good',
    deliveryType:  'shipping',
    scrapeDetails: false,
    maxRecords:    1000,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} sneaker listings in NYC`);
items.slice(0, 5).forEach(i => console.log(`$${i.price} — ${i.title}`));
```

#### API Run (cURL)

```bash
curl -X POST "https://api.apify.com/v2/acts/haketa~offerup-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "keywords":     ["honda civic", "toyota camry", "ford f150"],
    "location":     "Houston, TX",
    "radius":       50,
    "priceMin":     3000,
    "priceMax":     20000,
    "deliveryType": "pickup",
    "maxRecords":   500
  }'
```

#### API Run (PHP)

```php
$ch = curl_init('https://api.apify.com/v2/acts/haketa~offerup-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'keywords' => ['couch', 'dining table', 'queen bed'],
        'location' => 'Chicago, IL',
        'radius'   => 25,
        'maxRecords' => 200,
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$listings = json_decode(curl_exec($ch), true);
```

***

### How It Works

OfferUp is a defended Next.js application that pulls listing data through a combination of server-side-rendered `__NEXT_DATA__` payloads and internal JSON API responses (Apollo / GraphQL cache). This actor uses a **layered extraction strategy** so it stays resilient when one strategy breaks.

| Source endpoint | Purpose | Extraction technique |
|---|---|---|
| `https://offerup.com/` | Cookie + JS-challenge establishment ("session warmup") | Playwright navigation, wait for stable `<title>` |
| `https://offerup.com/search?q={kw}&location={loc}&radius={R}` | Keyword + geo search results | `__NEXT_DATA__` JSON → Apollo cache (`Listing:*`, `Item:*`) + `looseTiles` array |
| Internal `/api/...` & `/graphql` calls | Live feed items + pagination payloads | `page.on('response')` interception → `findFeedItems` recursive walker |
| `https://offerup.com/item/detail/{id}` | Per-listing description, gallery, full seller stats | Optional `scrapeDetails: true` follow-up navigation |

#### Engineering details

- **Engine: Playwright (Chromium, headless)** — the only reliable way to pass OfferUp's JS challenge and TLS fingerprint check
- **Stealth patches** — `navigator.webdriver`, plugin count, languages, and `window.chrome` are normalized to defeat fingerprint-based bot detection
- **US residential proxy** required and configured by default (`RESIDENTIAL`, `country-US`) — datacenter IPs are blocked instantly
- **Per-session IP rotation** — each keyword gets a fresh `session-{sessionId}` token so consecutive runs come from different residential addresses
- **Homepage warmup flow** — visits `offerup.com` first to set anti-bot cookies before any `/search` request
- **API response interception** — every JSON response with `feed`, `graphql`, or `/api/` in the URL is captured for fallback parsing
- **Three-strategy listing extraction** — (1) Apollo cache → (2) `looseTiles` array → (3) raw HTML/Cheerio selectors
- **403 / 429 auto-recovery** — burned sessions are closed, fresh IP rotated in, exponential backoff applied, same page retried
- **Infinite-scroll-aware pagination** — `?page=N` parameter walk up to `maxPages`, deduplicated by `listingId`
- **Configurable politeness** — `requestDelay` between page requests, jittered keyword delays, hard cap on per-keyword pages
- **Schema normalization** — image arrays, prices in cents vs dollars, owner vs seller vs user keys, and ISO vs relative dates all resolved to a single flat output schema

***

### Input Parameters

```json
{
  "keywords":       ["iphone 15", "macbook pro 14"],
  "location":       "Los Angeles, CA",
  "radius":         30,
  "priceMin":       200,
  "priceMax":       1500,
  "condition":      "like_new",
  "deliveryType":   "all",
  "scrapeDetails":  true,
  "maxRecords":     500,
  "maxPages":       10,
  "requestDelay":   2000,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

#### Parameter reference

| Parameter | Type | Default | Description |
|---|---|---|---|
| `keywords` | `array<string>` | `["iphone"]` | One or more search terms. **Each keyword runs an independent search** so a 5-keyword input is effectively 5 scrapes stitched into one dataset. |
| `location` | `string` | `"Los Angeles, CA"` | City + state (e.g., `"New York, NY"`) **or** a 5-digit US ZIP (e.g., `"90001"`). Leave empty for OfferUp's default nationwide view. |
| `radius` | `integer` | `30` | Search radius in miles, 1–50. Common values: `5`, `10`, `20`, `30`, `50`. |
| `priceMin` | `integer` | `0` | Minimum item price in USD. `0` = no minimum. |
| `priceMax` | `integer` | `0` | Maximum item price in USD. `0` = no maximum. |
| `condition` | `string` | `"all"` | One of: `all`, `new`, `like_new`, `good`, `fair`, `poor`. Applied as a post-filter against the listing's reported condition. |
| `deliveryType` | `string` | `"all"` | `all` = any, `pickup` = local pickup only, `shipping` = shipping-eligible listings only. Maps to OfferUp's `delivery_param` URL flag. |
| `scrapeDetails` | `boolean` | `false` | If `true`, visits each listing's detail page for the long-form `description`, full image gallery, `category`, and complete seller reputation block. Slower but **much richer data**. |
| `maxRecords` | `integer` | `0` | Total listing cap across **all** keywords combined. `0` = unlimited. |
| `maxPages` | `integer` | `10` | Maximum search result pages **per keyword**. `0` = unlimited. |
| `requestDelay` | `integer` | `2000` | Milliseconds between requests. **Keep ≥ 1500ms** — OfferUp blocks fast scrapers. Min 1000, max 10000. |
| `proxyConfiguration` | `object` | Apify `RESIDENTIAL` US | US residential proxy is **mandatory**. Datacenter and non-US IPs are blocked. |

***

### Output Schema

Every listing record is a flat JSON object with the following fields. All fields default to `null` when OfferUp does not return a value for that listing.

#### Listing fields

| Field | Type | Description |
|---|---|---|
| `listingId` | `string` | Unique OfferUp listing ID (matches the path in `listingUrl`). |
| `title` | `string` | Item title as displayed on the listing card. |
| `price` | `number` | Asking price in USD. |
| `condition` | `string` | Reported condition: `New`, `Like New`, `Good`, `Fair`, or `Poor`. |
| `location` | `string` | "City, ST" of the seller as shown on OfferUp. |
| `postDate` | `string` | ISO-8601 listing creation date (when OfferUp exposes it). |
| `postDateAgo` | `string` | Relative time string ("2 hours ago", "3 days ago"). |
| `shippingAvailable` | `boolean` | `true` if the seller offers shipping (OfferUp `SHIPPING` flag), `false` for local-pickup-only, `null` if unknown. |
| `category` | `string` | OfferUp item category (e.g., `Electronics > Cell Phones`). Populated when `scrapeDetails: true`. |
| `description` | `string` | Full long-form item description. Populated when `scrapeDetails: true`. |
| `images` | `array<string>` | Image URLs (first thumbnail in card mode, full gallery in detail mode). |
| `listingUrl` | `string` | Direct deep link: `https://offerup.com/item/detail/{listingId}`. |

#### Seller fields

| Field | Type | Description |
|---|---|---|
| `sellerName` | `string` | Seller's display name / username. |
| `sellerRating` | `number` | Average star rating (1.0 – 5.0). |
| `sellerReviewCount` | `integer` | Total number of buyer reviews left on the seller. |
| `sellerVerified` | `boolean` | `true` if the seller passed OfferUp's **TruYou** identity verification. |
| `sellerJoinDate` | `string` | Date the seller joined OfferUp. |
| `sellerItemCount` | `integer` | Total active listings the seller currently has on OfferUp. |

#### Provenance fields

| Field | Type | Description |
|---|---|---|
| `searchKeyword` | `string` | The keyword from your input that surfaced this listing. |
| `searchLocation` | `string` | The location string from your input. |
| `scrapedAt` | `string` | ISO-8601 timestamp of extraction. |

#### Example: card-mode record (`scrapeDetails: false`)

```json
{
  "listingId": "1234567890",
  "title": "iPhone 15 Pro Max 256GB Unlocked - Like New in Box",
  "price": 899,
  "condition": "Like New",
  "location": "Los Angeles, CA",
  "postDate": null,
  "postDateAgo": "4 hours ago",
  "shippingAvailable": true,
  "category": null,
  "description": null,
  "images": ["https://offerupimage.com/listing/1234567890_1.jpg"],
  "sellerName": "alex_la",
  "sellerRating": 4.9,
  "sellerReviewCount": 87,
  "sellerVerified": true,
  "sellerJoinDate": null,
  "sellerItemCount": null,
  "listingUrl": "https://offerup.com/item/detail/1234567890",
  "searchKeyword": "iphone 15",
  "searchLocation": "Los Angeles, CA",
  "scrapedAt": "2026-05-16T18:42:11.000Z"
}
```

#### Example: detail-mode record (`scrapeDetails: true`)

```json
{
  "listingId": "9876543210",
  "title": "2018 Honda Civic LX Sedan — 62k miles, clean title",
  "price": 14500,
  "condition": "Good",
  "location": "Houston, TX",
  "postDate": "2026-05-14T09:15:00Z",
  "postDateAgo": "2 days ago",
  "shippingAvailable": false,
  "category": "Cars & Trucks > Sedan",
  "description": "Single owner, all service records included. New tires and brakes within the last 5,000 miles. Clean title, no accidents on Carfax. Cash only, pickup in Spring Branch.",
  "images": [
    "https://offerupimage.com/listing/9876543210_1.jpg",
    "https://offerupimage.com/listing/9876543210_2.jpg",
    "https://offerupimage.com/listing/9876543210_3.jpg",
    "https://offerupimage.com/listing/9876543210_4.jpg"
  ],
  "sellerName": "Marcos H.",
  "sellerRating": 5.0,
  "sellerReviewCount": 23,
  "sellerVerified": true,
  "sellerJoinDate": "2021-03-08",
  "sellerItemCount": 4,
  "listingUrl": "https://offerup.com/item/detail/9876543210",
  "searchKeyword": "honda civic",
  "searchLocation": "Houston, TX",
  "scrapedAt": "2026-05-16T18:43:55.000Z"
}
```

***

### Condition & Delivery Reference

#### Condition values

| Value | Meaning |
|---|---|
| `all` | Return every condition (default). |
| `new` | Sealed / unused with tags. |
| `like_new` | Used briefly, no visible wear. |
| `good` | Normal wear consistent with age. |
| `fair` | Noticeable wear but fully functional. |
| `poor` | Heavy wear, defects, or for-parts items. |

#### Delivery types

| Value | OfferUp URL flag | Returned listings |
|---|---|---|
| `all` | *(none)* | Pickup + shipping |
| `pickup` | `delivery_param=p` | Local pickup only |
| `shipping` | `delivery_param=s` | Nationwide shippable |

#### Popular OfferUp top-level categories

| Category | Typical sub-categories |
|---|---|
| Electronics | Phones, laptops, tablets, TVs, cameras, gaming consoles, audio |
| Cars & Trucks | Sedans, SUVs, trucks, motorcycles, boats, RVs, parts |
| Home & Garden | Furniture, appliances, tools, decor, lawn & garden, kitchen |
| Clothing & Shoes | Sneakers, streetwear, designer, kids, plus-size, accessories |
| Sports & Outdoors | Bikes, fitness, golf, camping, fishing, hunting |
| Baby & Kids | Strollers, car seats, toys, cribs, clothing, gear |
| Tools & Machinery | Power tools, hand tools, lawn equipment, construction |
| Musical Instruments | Guitars, drums, keyboards, DJ gear, amps |
| Collectibles | Sports cards, comics, vinyl, coins, antiques |
| Pet Supplies | Crates, beds, aquariums, supplies |

***

### Use Cases

#### Reseller Arbitrage & Flipping Research

Resellers, flippers, and eBay/Amazon FBA operators use this dataset to:

- **Source under-priced inventory** — pull every "good" or better iPhone under $400 in a 50-mile radius and compare to current eBay sold-comps
- **Identify motivated sellers** — listings priced 30–40% below median for the model are prime flip targets
- **Build daily watch lists** for high-velocity categories (sneakers, consoles, power tools, designer bags)
- **Detect price-drop signals** by re-running searches daily and diffing the same `listingId` across runs
- **Benchmark local vs national pricing** by combining OfferUp data with eBay sold-listings to compute spread per metro
- **Filter for TruYou sellers only** (`sellerVerified: true`) to reduce no-show and scam risk

#### Used-Car & Vehicle Flipping Intelligence

Independent dealers, mechanics, and car-flipping operators use OfferUp to:

- **Track local vehicle supply** by make/model/year across major metros
- **Compare OfferUp asking prices to KBB and Manheim auction data** for arbitrage
- **Filter clean-title cars under $15K** in Houston, Phoenix, Dallas, and Atlanta for cash-and-flip workflows
- **Monitor truck and work-vehicle markets** (F-150, Silverado, Tundra, ProMaster, Transit) for contractor demand
- **Spot mileage outliers** by feeding the description field through an LLM that extracts mileage and condition signals
- **Map seller reputation against price** — verified sellers with 5+ reviews command and accept slightly higher prices

#### Brand & Counterfeit Monitoring

Brand-protection teams, IP counsel, and trademark holders use the dataset to:

- **Scan listings for unauthorized resale** of premium brands (Nike, Lululemon, Apple, Dyson, Yeti)
- **Detect counterfeit signals** — sub-market pricing on luxury items (Louis Vuitton, Gucci, Rolex, Hermès)
- **Track MAP (Minimum Advertised Price) compliance violations** by retailers liquidating overstock
- **Document infringement evidence** with timestamped `scrapedAt`, full image gallery, seller identity, and direct listing URL
- **Issue takedown requests** to OfferUp's Brand Protection team with structured evidence packages

#### Dropshipping & Ecommerce Market Intelligence

Shopify operators, dropshippers, and DTC brand teams use OfferUp data to:

- **Validate product-market fit** by counting active listings for a SKU across the top 10 US metros
- **Quantify second-hand competition** — if 200 used Theragun units are live below $150, your new-unit MSRP needs work
- **Identify trending categories** by tracking week-over-week listing-count growth across keywords
- **Benchmark second-hand resale value** as a marketing proxy ("resells for 75% of MSRP after 18 months")
- **Run regional A/B pricing tests** by comparing OfferUp medians across Seattle, Miami, Chicago, and LA
- **Score affiliate-marketing opportunities** by identifying high-volume sub-categories with active organic demand

#### Real Estate & Local Economic Intelligence

Commercial real estate analysts, neighborhood researchers, and economic-development teams use OfferUp listings as a proxy for local consumer activity:

- **Map household-formation rates** — surges in baby gear, cribs, and stroller listings signal millennial family migration
- **Identify gentrification corridors** — spikes in furniture and decor listings precede neighborhood turnover
- **Quantify move-out activity** — moving boxes, packing supplies, "everything must go" titles trend with relocation seasons
- **Compare consumer-electronics velocity** across ZIP codes to score retail catchment areas
- **Build neighborhood affluence indices** from median asking prices of premium-brand listings

#### Market Research & Competitive Intelligence

Consultants, hedge-fund analysts, and equity researchers use OfferUp as an alt-data signal for:

- **Consumer-electronics demand modeling** — second-hand listing velocity correlates with primary sales lag
- **Auto-market signal extraction** — used-car supply on OfferUp is a leading indicator for retail and auction pricing
- **Furniture-industry tracking** — IKEA, West Elm, and Article second-hand listings track new-purchase decay curves
- **Sneaker-resale alpha** — Nike SNKRS releases drop into OfferUp inventory within 48 hours of release
- **DTC-brand survival analysis** — discontinued brands appear as inventory liquidations on OfferUp before bankruptcy filings

#### Insurance & Claims Research

P\&C insurers, claims adjusters, and SIU teams use OfferUp data to:

- **Validate claimed item values** against the live second-hand market in the claimant's ZIP
- **Detect post-loss "windfall sales"** — claimants listing the supposedly-stolen item on OfferUp within 30 days
- **Build replacement-cost matrices** for personal-property claims using condition-stratified medians
- **Investigate auto-theft rings** by matching listing photos to NICB-reported stolen vehicles
- **Adjust depreciation curves** for high-volume categories using actual sale-comparable data

#### Academic & Policy Research

Universities, think tanks, and government research bureaus use OfferUp data for:

- **Circular-economy and sustainability studies** — quantifying re-use rates across product categories
- **Consumer-behavior research** — pricing psychology, condition-discount curves, urban-rural arbitrage
- **Labor-market signal research** — gig-seller activity correlates inversely with employment indicators
- **Local-commerce policy analysis** — sales-tax-exempt P2P volume as a macro indicator
- **Digital-divide studies** — comparing OfferUp activity across rural vs urban ZIPs

#### Journalism & Data Reporting

Investigative reporters, consumer-affairs writers, and local-news data teams use the dataset to:

- **Track post-disaster inventory dumps** — used generators, sandbags, and tarps after hurricanes
- **Cover the resale economy** with quantitative metro-level supply and price stories
- **Investigate stolen-goods marketplaces** in cooperation with local PD
- **Report on inflation and used-pricing trends** with cited, reproducible data
- **Document scam patterns** — too-good-to-be-true listings, repeated phone numbers, fake TruYou sellers

***

### Sample Queries & Recipes

#### Recipe 1: iPhone 15 deal-hunter across the top 4 US metros

```json
{
  "keywords":   ["iphone 15", "iphone 15 pro", "iphone 15 pro max"],
  "location":   "Los Angeles, CA",
  "radius":     50,
  "priceMin":   400,
  "priceMax":   900,
  "condition":  "like_new",
  "maxRecords": 1000
}
```

Repeat with `location` set to `"New York, NY"`, `"Chicago, IL"`, and `"Houston, TX"` and merge results downstream.

#### Recipe 2: Used Honda Civic / Toyota Camry market in Houston

```json
{
  "keywords":     ["honda civic", "toyota camry"],
  "location":     "Houston, TX",
  "radius":       50,
  "priceMin":     5000,
  "priceMax":     20000,
  "deliveryType": "pickup",
  "scrapeDetails": true,
  "maxRecords":   500
}
```

`scrapeDetails: true` brings back full mileage and condition notes in the description field — feed to an LLM for structured extraction.

#### Recipe 3: Designer-sneaker arbitrage scan (NYC + LA + Miami)

```json
{
  "keywords":     ["jordan 1", "yeezy 350", "nike dunk", "off white"],
  "location":     "New York, NY",
  "radius":       30,
  "priceMin":     100,
  "priceMax":     500,
  "deliveryType": "shipping",
  "condition":    "like_new",
  "maxRecords":   800
}
```

#### Recipe 4: Living-room furniture pulse for a Chicago real-estate analyst

```json
{
  "keywords":   ["couch", "sectional", "dining table", "queen bed"],
  "location":   "Chicago, IL",
  "radius":     20,
  "priceMax":   1500,
  "maxRecords": 600
}
```

#### Recipe 5: Power-tool flipping watch list in Phoenix

```json
{
  "keywords":   ["dewalt drill", "milwaukee m18", "makita", "ridgid"],
  "location":   "Phoenix, AZ",
  "radius":     30,
  "priceMin":   50,
  "priceMax":   400,
  "condition":  "good",
  "maxRecords": 400
}
```

#### Recipe 6: Brand-protection scan — counterfeit luxury watches

```json
{
  "keywords":      ["rolex submariner", "rolex datejust", "rolex daytona"],
  "location":      "Miami, FL",
  "radius":        50,
  "priceMin":      500,
  "priceMax":      5000,
  "scrapeDetails": true,
  "maxRecords":    300
}
```

Listings priced 90% below market on a Rolex Submariner are near-certain counterfeits — flag for the brand's legal team.

#### Recipe 7: Baby & kids gear in Seattle (move-in season demand signal)

```json
{
  "keywords":   ["stroller", "car seat", "crib", "bassinet"],
  "location":   "Seattle, WA",
  "radius":     25,
  "condition":  "like_new",
  "maxRecords": 500
}
```

#### Recipe 8: Cheap fast sample — sanity-check 20 listings before a big run

```json
{
  "keywords":   ["airpods"],
  "location":   "Dallas, TX",
  "maxRecords": 20,
  "maxPages":   1
}
```

Costs pennies and verifies your filters before you launch a 10K-record job.

***

### Integration Examples

#### Google Sheets (via Apify Integration)

1. Create an Apify Schedule that runs the actor daily with your saved input
2. Add the **"Save to Google Sheets"** integration to the schedule
3. Receive a fresh OfferUp listings sheet every morning — auto-deduplicated by `listingId`
4. Pivot on `searchKeyword` × `location` for category × metro analytics in seconds

#### Make.com / Zapier / n8n

The **Apify** connector is supported natively on every major automation platform. Trigger downstream workflows on:

- **New listings** (current run minus previous run, joined on `listingId`)
- **Price drops** (`listingId` seen yesterday at $1,200, today at $950 → Slack alert)
- **TruYou-verified sellers only** — auto-route promising leads to a dedicated CRM list
- **Condition upgrades** (`Good` → `Like New` retag) — sign of seller re-listing

#### Power BI / Tableau / Looker

Connect Apify's REST API (`/v2/datasets/{id}/items`) as a data source and refresh on the Apify schedule cadence. Build dashboards covering:

- Median price per category per metro
- Shipping-vs-pickup mix by ZIP
- Seller-rating distribution and TruYou penetration
- Listing volume heatmaps by US metro
- Week-over-week category velocity

#### Postgres / Snowflake / BigQuery

Use the [Apify webhook integration](https://docs.apify.com/platform/integrations/webhooks) to POST run results directly to your warehouse ingestion endpoint after each scheduled run. The flat output schema maps cleanly to a single `offerup_listings` table — index on `listingId`, `searchKeyword`, `location`, and `scrapedAt`.

#### Salesforce / HubSpot CRM Enrichment

Trigger an Apify run nightly and upsert seller records into a `OfferUp_Sellers` custom object keyed on `sellerName`. Use `sellerVerified`, `sellerRating`, and `sellerItemCount` as lead-scoring signals for B2B sales teams targeting power resellers.

#### LLM-Powered Description Extraction

Set `scrapeDetails: true`, then pipe the `description` field through GPT, Claude, or Gemini to extract:

- Vehicle mileage, accident history, title status
- Phone model, storage, carrier lock status
- Furniture dimensions, brand, year
- Sneaker size, colorway, release year

The structured JSON can feed pricing models, recommendation engines, or fraud-detection pipelines.

#### Slack / Discord Alerting

Wire run-completion webhooks into Slack to push deal alerts:

> ALERT — `iphone 15 pro max 256gb` @ Phoenix, AZ — $649 (35% below median) — sellerRating 4.9 (87 reviews, TruYou) — [view listing](https://offerup.com/item/detail/...)

***

### Major US Marketplace Metros at a Glance

| Metro | State | Population | OfferUp Marketplace Notes |
|---|---|---|---|
| New York | NY | 19.5M | Highest density of designer fashion, electronics, and luxury resale listings |
| Los Angeles | CA | 13.0M | Used cars, fitness equipment, audio gear, premium streetwear hotspot |
| Chicago | IL | 9.4M | Furniture, baby gear, and home-appliance turnover from constant rental churn |
| Dallas–Fort Worth | TX | 8.1M | Trucks, ATVs, tools, ranch equipment dominant categories |
| Houston | TX | 7.3M | Used cars, energy-sector tools, electronics, oil-field gear |
| Washington | DC | 6.4M | Office furniture, electronics, designer fashion, government-relocation churn |
| Miami | FL | 6.3M | Luxury watches, designer handbags, boats, marine equipment |
| Philadelphia | PA | 6.2M | Sneakers, vintage clothing, tools, used cars |
| Atlanta | GA | 6.1M | Sneakers, music gear, fashion, electronics resale hub |
| Phoenix | AZ | 5.0M | RVs, outdoor gear, used cars, retiree estate-sale inventory |
| Boston | MA | 4.9M | College-cycle furniture flips, electronics, bikes |
| San Francisco Bay | CA | 4.7M | Apple devices, designer fashion, tech-startup furniture clear-outs |
| Seattle | WA | 4.0M | Outdoor gear, bikes, Apple electronics, baby gear |
| Detroit | MI | 4.4M | Trucks, tools, motorcycles, used cars |
| Minneapolis | MN | 3.7M | Winter sports gear, snowblowers, baby gear |
| San Diego | CA | 3.3M | Surfing, marine, fitness, sneakers |
| Tampa | FL | 3.3M | Furniture, boats, RVs, golf equipment |
| Denver | CO | 3.0M | Outdoor gear, bikes, snowboards, fitness equipment |
| San Antonio | TX | 2.6M | Trucks, tools, baby gear, military-relocation inventory |
| Portland | OR | 2.5M | Bikes, vinyl, vintage clothing, outdoor gear |
| Sacramento | CA | 2.4M | Used cars, tools, furniture, sneakers |
| Las Vegas | NV | 2.3M | Casino chairs, designer fashion, electronics |
| Austin | TX | 2.3M | Tech gear, music equipment, bikes, baby gear |
| Charlotte | NC | 2.7M | Sneakers, electronics, used cars, fishing gear |
| Orlando | FL | 2.7M | Theme-park resale, baby gear, electronics |

The actor works for **every US ZIP code** — these are simply the highest-volume marketplaces.

***

### Cost & Performance

| Metric | Value |
|---|---|
| Engine | Playwright (Chromium) + API response interception + Cheerio fallback |
| Runtime (1 keyword, 1 page, ~20 records) | 30–60 seconds |
| Runtime (1 keyword, 10 pages, ~200 records) | 4–8 minutes |
| Runtime (5 keywords × 10 pages × `scrapeDetails:true`) | 25–45 minutes |
| Pricing model | Pay-per-event (Actor start + per dataset item) |
| Data freshness | **Live at run time** — listings reflect OfferUp's current state |
| Auth required | None (no OfferUp account needed) |
| Proxy required | **Yes — Apify RESIDENTIAL (US)** is configured by default |
| Concurrency | Multiple keywords run sequentially in one actor run; launch parallel actor runs for concurrent metros |
| Memory footprint | 1024 MB minimum, 2048 MB recommended for `scrapeDetails: true` |
| Max input pages per keyword | Configurable via `maxPages` (default 10) |
| Per-request politeness | `requestDelay` (default 2000 ms, min 1000) plus jittered keyword gaps |

***

### Compliance, Privacy & Legal Notes

- **Public data only** — every field returned by this actor is publicly visible on [offerup.com](https://offerup.com) without login
- **No PII enrichment** — the actor does not attempt to resolve seller usernames to real identities, phone numbers, emails, or social-media handles
- **TruYou identity verification status** is a public boolean flag exposed by OfferUp itself — no underlying identity documents are scraped
- **No payment data, no buyer data, no message threads** — only listing-side public marketplace data
- **Image URLs** are pointers to OfferUp's CDN; the actor does not rehost or republish images
- **robots.txt and ToS** — review OfferUp's current robots.txt and Terms of Service before commercial deployment; respect rate limits via the `requestDelay` parameter
- **GDPR / CCPA** — although OfferUp is a US marketplace, downstream consumers in the EU, UK, or California must apply their own lawful-basis assessment when processing seller usernames as personal data
- **Brand & trademark use** — "OfferUp" is a trademark of OfferUp Inc.; this actor is unaffiliated, unendorsed, and provided purely as a public-data extraction utility
- **Stolen-goods reporting** — if your use case involves identifying stolen merchandise, coordinate with the relevant law-enforcement agency and respect chain-of-custody requirements

> **Important:** OfferUp data may not be used for unlawful purposes including but not limited to stalking, harassment, deceptive trade practices, or any activity that violates OfferUp's Terms of Service. The user is responsible for the lawful application of the dataset.

***

### Frequently Asked Questions

#### How fresh is the data?

**Live at run time.** The actor hits OfferUp's live search and detail endpoints, so every record reflects what's visible to a real user **at the moment the actor ran**. There is no cache between you and OfferUp.

#### How many listings can I get per run?

Configurable via `maxRecords` and `maxPages`. Typical practical limits are **200–2,000 listings per metro per keyword per run** before OfferUp starts rate-shaping that residential session. For larger pulls, split across multiple actor runs (different metros, different keywords) and merge downstream.

#### Do I need an OfferUp account or API key?

**No.** OfferUp does not offer a public API, and no login is required to view public listings. You only need an Apify account to run the actor.

#### Does it cover every US state and ZIP code?

**Yes** — OfferUp operates nationwide and the actor accepts any `"City, ST"` or 5-digit ZIP as the `location` input. Coverage density follows OfferUp's user base — top metros have tens of thousands of active listings; rural ZIPs have fewer.

#### Why is residential proxy required?

OfferUp blocks **every** datacenter IP range (AWS, GCP, Azure, OVH, Hetzner, DigitalOcean, Linode, etc.) on the first request with HTTP 403. The actor ships pre-configured with Apify's `RESIDENTIAL` proxy group restricted to `country-US` — this is non-negotiable for reliable extraction.

#### Can it solve CAPTCHAs?

The actor uses **stealth Playwright + session rotation + residential IPs** to avoid CAPTCHAs in the first place. If an individual session does get a challenge, the actor rotates to a fresh residential session automatically (`consecutiveFails` retry loop). Full hCaptcha solving is not part of this actor.

#### What's the difference between card mode and `scrapeDetails: true`?

**Card mode** (`scrapeDetails: false`, the default) returns whatever data is on the search-result tile: title, price, location, condition, first thumbnail, basic seller name. **Detail mode** visits each listing's full page for the long-form description, full image gallery, OfferUp category, complete seller stats (rating, review count, TruYou flag, join date, total listings). Detail mode is **5–10× slower** but gives you ~3× more usable data per record.

#### Can I scrape vehicle (car/truck) listings?

**Yes.** OfferUp's "Cars & Trucks" category is fully supported — use keywords like `honda civic`, `f150`, `silverado`, `tundra`, `tacoma`, `tesla model 3`, etc. The `description` field (in detail mode) is where mileage, VIN hints, accident history, and service notes typically appear — pipe it through an LLM for structured extraction.

#### Can I filter by exact OfferUp category?

The actor accepts **keywords**, not category IDs. Most use cases work better with keywords because OfferUp's category taxonomy is noisy — `dewalt drill` will surface every relevant tool whether it's filed under "Power Tools" or "Hand Tools" or "Construction Equipment". If you need pure-category scraping, run multiple keyword variants and dedupe on `listingId`.

#### Can I get seller phone numbers or emails?

**No.** OfferUp deliberately hides seller contact info — communication happens through in-app messaging, which is not accessible without authentication. The actor returns `sellerName`, rating, TruYou status, and join date — that's the full public seller surface.

#### Does the actor deduplicate listings?

**Yes.** A `Set` of `listingId` (or `listingUrl` / `title` fallback) is maintained across pages and across keywords within the same run, so a listing matching multiple keywords appears in the dataset exactly once.

#### What happens when OfferUp blocks me with a 403?

The actor automatically detects HTTP 403 and 429, closes the burned session, waits with exponential backoff (`8000ms × failCount + jitter`), creates a fresh session with a new residential IP, re-warms the homepage, and retries the same page. It gives up on a keyword after 3 consecutive blocks to avoid wasting CU.

#### Can I run this on the Apify Free Plan?

**Yes** — but you'll burn through free credits faster than CSV-based scrapers because Playwright + residential proxy is more expensive than direct HTTP. For sustained daily use, the Starter or Scale plan is recommended.

#### Can I schedule it to run automatically?

**Yes.** Apify's built-in **Scheduler** supports any cron expression — hourly deal scans, twice-daily reseller pulls, weekly market-research snapshots. Combine with webhook integrations for fully automated alerting pipelines.

#### What export formats are supported?

**JSON, CSV, Excel (XLSX), HTML, XML, RSS, JSON Lines** — all available directly from the Apify dataset view or via the `/v2/datasets/{id}/items?format=...` API endpoint.

#### Are listing images downloaded?

**No** — `images` is an array of OfferUp CDN URLs. Download them client-side if you need local copies; this keeps the actor fast and avoids re-hosting third-party content.

#### Why are some fields `null`?

OfferUp doesn't surface every field on every listing card. Common nulls in card mode: `description`, `category`, `images` beyond the first thumbnail, `sellerJoinDate`, `sellerItemCount`, `sellerReviewCount`. Set `scrapeDetails: true` to populate them.

#### Does it work for international OfferUp variants?

OfferUp is **US-only** as of this writing. For other markets, see the related-actors catalog below — we maintain dedicated scrapers for Kleinanzeigen (Germany), Marktplaats (Netherlands), Kijiji (Canada), TradeMe (New Zealand), Lelong (Malaysia marketplace), Chợ Tốt (Vietnam), and Mourjan (MENA).

#### How do I report a bug or request a feature?

Open an issue on the **Apify Store actor page** or contact the developer directly through the Apify Console.

***

### Related Apify Actors by Haketa

If you need second-hand marketplace data from other countries — or want to combine multi-market intelligence — these sibling scrapers are built to the same standard:

- **[Kleinanzeigen.de Scraper (Germany)](https://apify.com/haketa/kleinanzeigen-scraper)** — Germany's #1 used-goods classifieds, full listing + seller data
- **[Marktplaats.nl Scraper (Netherlands)](https://apify.com/haketa/marktplaats-scraper)** — Dutch peer-to-peer marketplace with prices, locations, and seller stats
- **[Kijiji.ca Scraper (Canada)](https://apify.com/haketa/kijiji-scraper)** — Canada's largest local classifieds across all major metros
- **[TradeMe Scraper (New Zealand)](https://apify.com/haketa/trademe-scraper)** — New Zealand's dominant marketplace and auction site
- **[Lelong.my Scraper (Malaysia)](https://apify.com/haketa/lelong-my-scraper)** — Malaysia's veteran C2C / SME online marketplace
- **[Chotot.com Scraper (Vietnam)](https://apify.com/haketa/chotot-scraper)** — Vietnam's leading C2C marketplace
- **[Mourjan Scraper (MENA)](https://apify.com/haketa/mourjan-scraper)** — Middle East & North Africa classifieds across 14 countries
- **[Rent.com Scraper (US)](https://apify.com/haketa/rent-com-scraper)** — US rental property listings, useful for market-correlation analyses
- **[Apartments.com Scraper (US)](https://apify.com/haketa/apartments-com-scraper)** — US apartment rental data for cross-marketplace location intelligence
- **[YallaMotor Scraper (GCC)](https://apify.com/haketa/yallamotor-scraper)** — Gulf-region used-car listings for international vehicle market work
- **[BBB Business Scraper](https://apify.com/haketa/bbb-scraper)** — Better Business Bureau data for power-seller verification cross-checks
- **[SAM.gov Federal Contractor Scraper](https://apify.com/haketa/sam-gov-federal-contractor-scraper)** — US government contractor registry

***

### Comparison vs. Alternatives

| Approach | Setup time | Data freshness | Anti-bot handling | Schema normalization | Maintenance burden |
|---|---|---|---|---|---|
| **This actor** | < 1 minute | Live | Built-in (residential + session rotation) | Flat unified JSON | Zero |
| Manual scrolling + screenshots | Hours per metro | Live | Manual | None | High |
| DIY Python + requests | Doesn't work | — | **Blocked instantly** (datacenter IPs) | DIY | N/A |
| DIY Playwright + free proxies | 2–4 weeks dev | Live | Brittle, daily breakage | DIY | Very high |
| DIY Playwright + paid residential proxy | 1–2 weeks dev + ongoing | Live | Decent | DIY | High |
| Buying a third-party OfferUp dataset | Days to procure | Stale (weekly+) | N/A | Vendor schema | Vendor lock-in |
| Hiring a scraping agency | Weeks + retainer | Variable | Agency-managed | Custom | Contract overhead |

***

### Why Pay-Per-Event Pricing?

This actor uses **pay-per-event** pricing instead of flat monthly subscriptions or unpredictable per-Compute-Unit billing:

- **You only pay when the actor runs** — no monthly minimums, no idle subscription costs
- **Charges scale with data delivered** — small test pulls cost pennies, big multi-metro pulls scale linearly and transparently
- **Line-item billing inside Apify** — every run shows event count, duration, and exact cost
- **Free to evaluate** — set `maxRecords: 20` for a sub-dollar smoke test before any big commitment
- **No proxy surcharges to manage separately** — residential proxy usage is included in the per-event price
- **Predictable budgeting** — finance teams can model cost per record × records per month

***

### Changelog

| Version | Date | Notes |
|---|---|---|
| 1.0.0 | 2026-05 | Initial public release — Playwright + US residential proxy + API response interception, multi-keyword search, ZIP/city + radius targeting, price/condition/delivery filters, optional detail-page enrichment, full seller reputation block, pay-per-event pricing |

***

### Keywords

OfferUp scraper · OfferUp data API · OfferUp price scraper · OfferUp listings extractor · OfferUp marketplace scraper · OfferUp data extraction · OfferUp web scraping · OfferUp.com scraper · US used items data · US second-hand marketplace data · second-hand marketplace data · used items API · peer-to-peer marketplace scraper · C2C marketplace scraper · OfferUp lead generation · OfferUp seller data · OfferUp reseller research · OfferUp arbitrage tool · used car scraper US · used iPhone price data · used MacBook listings · sneaker resale data · OfferUp brand monitoring · counterfeit detection OfferUp · OfferUp competitive intelligence · dropshipping product research · ecommerce market analysis · second-hand price benchmark · OfferUp price tracker · OfferUp deal finder · Apify marketplace actor · OfferUp Los Angeles listings · OfferUp New York listings · OfferUp Chicago listings · OfferUp Houston listings · OfferUp Phoenix listings · OfferUp Philadelphia listings · OfferUp San Antonio listings · OfferUp Dallas listings · OfferUp Miami listings · OfferUp Seattle listings · OfferUp Atlanta listings · OfferUp Denver listings · OfferUp ZIP code search · TruYou verified seller data · OfferUp shipping listings · OfferUp pickup listings · classifieds scraper US · local marketplace data USA

***

### Support

- **Bug reports:** Open an issue on the **[Apify Store actor page](https://apify.com/haketa/offerup-scraper)**
- **Feature requests:** Same place — please describe your use case so we can prioritize correctly
- **Direct contact:** Reach the developer through the Apify Console profile

If this actor saves you time, a **5-star rating** on the Apify Store helps other resellers, ecommerce teams, and marketplace researchers discover it. Thank you!

# Actor input Schema

## `keywords` (type: `array`):

Search terms. Each keyword runs a separate search. Examples: 'iphone 15', 'macbook pro', 'nike air max', 'couch', 'mountain bike'.

## `location` (type: `string`):

City and state or ZIP code. Examples: 'Los Angeles, CA', 'New York, NY', '90001', '10001'. Leave empty for default (nationwide).

## `radius` (type: `integer`):

Search radius in miles from location. Common values: 5, 10, 20, 30, 50.

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

Minimum price filter in USD. Leave 0 for no minimum.

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

Maximum price filter in USD. Leave 0 for no maximum.

## `condition` (type: `string`):

Filter by item condition.

## `deliveryType` (type: `string`):

'all' = any, 'pickup' = local pickup only, 'shipping' = shipping available only.

## `scrapeDetails` (type: `boolean`):

Visit each listing's detail page for full description, seller info, all images and category. Slower but much richer data.

## `maxRecords` (type: `integer`):

Maximum total listings to output across all keywords. Set 0 for unlimited.

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

Maximum pages per keyword search. Set 0 for unlimited.

## `requestDelay` (type: `integer`):

Delay between requests. OfferUp blocks fast requests — keep above 1500ms.

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

US residential proxy required. OfferUp blocks datacenter IPs.

## Actor input object example

```json
{
  "keywords": [
    "iphone"
  ],
  "location": "Los Angeles, CA",
  "radius": 30,
  "priceMin": 0,
  "priceMax": 0,
  "condition": "all",
  "deliveryType": "all",
  "scrapeDetails": false,
  "maxRecords": 0,
  "maxPages": 10,
  "requestDelay": 2000,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `listingId` (type: `string`):

Unique OfferUp listing ID

## `title` (type: `string`):

Item title

## `price` (type: `string`):

Price in USD

## `condition` (type: `string`):

New / Like New / Good / Fair / Poor

## `location` (type: `string`):

City and state

## `postDate` (type: `string`):

Listing creation date (ISO)

## `postDateAgo` (type: `string`):

Relative time (2 hours ago)

## `shippingAvailable` (type: `string`):

Shipping available (true/false)

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

Item category

## `description` (type: `string`):

Full item description (from detail)

## `images` (type: `string`):

Image URLs (JSON array)

## `sellerName` (type: `string`):

Seller username

## `sellerRating` (type: `string`):

Seller rating (1-5)

## `sellerReviewCount` (type: `string`):

Number of seller reviews

## `sellerVerified` (type: `string`):

TruYou verified seller

## `sellerJoinDate` (type: `string`):

Seller account creation date

## `sellerItemCount` (type: `string`):

Total listings by seller

## `listingUrl` (type: `string`):

Direct link to listing

## `searchKeyword` (type: `string`):

Keyword used in search

## `searchLocation` (type: `string`):

Location used in search

## `scrapedAt` (type: `string`):

ISO timestamp when scraped

# 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 = {
    "keywords": [
        "iphone"
    ],
    "location": "Los Angeles, CA",
    "scrapeDetails": false,
    "maxRecords": 0,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/offerup-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 = {
    "keywords": ["iphone"],
    "location": "Los Angeles, CA",
    "scrapeDetails": False,
    "maxRecords": 0,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

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

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

```

## CLI example

```bash
echo '{
  "keywords": [
    "iphone"
  ],
  "location": "Los Angeles, CA",
  "scrapeDetails": false,
  "maxRecords": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call haketa/offerup-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=haketa/offerup-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "OfferUp Scraper | US Marketplace Listings & Prices",
        "description": "OfferUp scraper & API (US classifieds): search listings by keyword and location and export title, price, condition, description, seller, location, photos, date and URL. US marketplace and resale market data plus seller lead generation — fast, no login.",
        "version": "0.0",
        "x-build-id": "g4cVi1aykReN0iTn1"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/haketa~offerup-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-haketa-offerup-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/haketa~offerup-scraper/runs": {
            "post": {
                "operationId": "runs-sync-haketa-offerup-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/haketa~offerup-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-haketa-offerup-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "keywords": {
                        "title": "Keywords",
                        "type": "array",
                        "description": "Search terms. Each keyword runs a separate search. Examples: 'iphone 15', 'macbook pro', 'nike air max', 'couch', 'mountain bike'.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "location": {
                        "title": "Location",
                        "type": "string",
                        "description": "City and state or ZIP code. Examples: 'Los Angeles, CA', 'New York, NY', '90001', '10001'. Leave empty for default (nationwide)."
                    },
                    "radius": {
                        "title": "Radius (miles)",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Search radius in miles from location. Common values: 5, 10, 20, 30, 50.",
                        "default": 30
                    },
                    "priceMin": {
                        "title": "Min Price ($)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Minimum price filter in USD. Leave 0 for no minimum.",
                        "default": 0
                    },
                    "priceMax": {
                        "title": "Max Price ($)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum price filter in USD. Leave 0 for no maximum.",
                        "default": 0
                    },
                    "condition": {
                        "title": "Condition",
                        "enum": [
                            "all",
                            "new",
                            "like_new",
                            "good",
                            "fair",
                            "poor"
                        ],
                        "type": "string",
                        "description": "Filter by item condition.",
                        "default": "all"
                    },
                    "deliveryType": {
                        "title": "Delivery Type",
                        "enum": [
                            "all",
                            "pickup",
                            "shipping"
                        ],
                        "type": "string",
                        "description": "'all' = any, 'pickup' = local pickup only, 'shipping' = shipping available only.",
                        "default": "all"
                    },
                    "scrapeDetails": {
                        "title": "Scrape Detail Pages",
                        "type": "boolean",
                        "description": "Visit each listing's detail page for full description, seller info, all images and category. Slower but much richer data.",
                        "default": false
                    },
                    "maxRecords": {
                        "title": "Max Records",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum total listings to output across all keywords. Set 0 for unlimited.",
                        "default": 0
                    },
                    "maxPages": {
                        "title": "Max Pages per Keyword",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum pages per keyword search. Set 0 for unlimited.",
                        "default": 10
                    },
                    "requestDelay": {
                        "title": "Request Delay (ms)",
                        "minimum": 1000,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Delay between requests. OfferUp blocks fast requests — keep above 1500ms.",
                        "default": 2000
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "US residential proxy required. OfferUp blocks datacenter IPs."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
