# 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
- **Features:** Limited permissions
- **Stats:** 31 total users, 0 monthly users, 100.0% runs succeeded, 1 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/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

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

> **Turn the live OfferUp marketplace into a clean, structured dataset.** Search [OfferUp.com](https://offerup.com) by keyword, US city/ZIP, radius, price range, condition, and delivery mode — and extract **item title, asking price in USD, city & state location, shipping availability, listing ID, high-resolution photo URLs, and direct listing links** (plus optional detail-page enrichment for description, category, and seller profile data).

Export to **JSON, CSV, Excel, XML, or the Apify API** — no login, no coding, no browser maintenance required.

[![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)]()
[![Scale](https://img.shields.io/badge/Scale-1%2C000%2B%20Results%20Pagination-green)]()
[![Pay Per Event](https://img.shields.io/badge/Pricing-Pay%20Per%20Event-yellow)]()
[![Region](https://img.shields.io/badge/Region-United%20States%20%F0%9F%87%BA%F0%9F%87%B8-red)]()
[![No Auth](https://img.shields.io/badge/Authentication-None%20Required-success)]()
[![Proxy](https://img.shields.io/badge/Proxy-US%20Residential-lightgrey)]()
[![Export](https://img.shields.io/badge/Export-JSON%20%C2%B7%20CSV%20%C2%B7%20Excel-purple)]()

***

### ⚡ At a glance

| Feature | Details |
|---|---|
| 🎯 **Target marketplace** | **[OfferUp.com](https://offerup.com)** — Leading US mobile-first local buy-and-sell marketplace |
| 🔍 **Search & Filters** | Multi-keyword search (`keywords`), 20 built-in US metros + custom City/ZIP (`locationCustom`), `radius` (5–50 miles), `priceMin` / `priceMax`, `condition`, and `deliveryType` (`pickup` / `shipping`) |
| 🏷️ **Core listing data** | `listingId` (100%), `title` (100%), `price` in USD (100%), `location` (`City, ST`, 100%), `shippingAvailable` (100%), `images` array (100%), and `listingUrl` (100%) |
| 📝 **Detail enrichment** | Optional `scrapeDetails: true` visits individual `/item/detail/{id}` pages to enrich `description`, `category`, `condition`, and seller fields when exposed |
| 🔁 **Pagination & Scale** | Unlocked **1,000+ results pagination** (`maxPages: 0` auto-paginates until `maxRecords` is reached) with 100% `listingId` deduplication |
| 🛡️ **Session resilience** | Built-in US residential proxy rotation, automatic homepage session warmup, and 403/429 retry recovery |
| 📦 **Bulk export** | JSON, JSONL, CSV, Excel (XLSX), HTML, XML, and direct REST API endpoints |

***

### 🔎 Why scrape OfferUp?

**[OfferUp](https://offerup.com)** (which absorbed Letgo in the US) is one of the largest local C2C and recommerce marketplaces in North America, where millions of buyers and sellers trade **smartphones, laptops, gaming consoles, used cars & trucks, furniture, power tools, sneakers, musical instruments, bicycles, and appliances** every single day. For resellers, pricing analysts, DTC brands, and alternative-data researchers, OfferUp is a primary real-time barometer of **US second-hand supply and asking prices**.

However, OfferUp does not provide a public developer API, and extracting data from `offerup.com` on your own is notoriously tough:

- **Strict edge protection:** OfferUp blocks datacenter IP addresses immediately and challenges non-browser requests.
- **Multi-keyword & multi-page aggregation:** Monitoring dozens of SKUs across pages requires automated session management, pagination, and cross-search deduplication.
- **Unstructured layout:** Turning infinite-scroll listing tiles into a clean table with normalized numeric prices, shipping flags, and city/state strings takes dedicated parsing logic.

This **OfferUp scraper** manages browser sessions, US residential proxy rotation, multi-page traversal, and `listingId` deduplication automatically — returning a clean, flat dataset in minutes.

#### Common reasons teams use this OfferUp data extractor

- 💸 **Reseller & Flip Sourcing** — Monitor underpriced iPhones, MacBooks, PS5s, cameras, power tools, and sneakers to flip on eBay, Mercari, Swappa, or Amazon.
- 📊 **Second-Hand Price Benchmarking** — Track the live USD asking-price distribution (min, median, p25/p75) for specific consumer electronics, musical instruments, or tool models.
- 🚗 **Used Auto & Truck Market Research** — Scrape local used-car and pickup-truck supply (`honda civic`, `toyota tacoma`, `ford f150`, `chevy silverado`) across US metros.
- 🛍️ **E-Commerce & DTC Brand Intelligence** — Measure secondary-market resale volume and price retention for your brand's products.
- 📈 **Alternative Data & Circular Economy Research** — Quantify consumer resale velocity and local inventory trends across US cities.
- 🔔 **Automated Deal Alerts** — Schedule hourly or daily runs and diff against previously seen `listingId` values to alert Slack, Discord, or Telegram on new bargains.

***

### ✨ What this OfferUp scraper does

- ✅ **Multi-keyword batch execution** — Pass as many search terms as you want in `keywords` (e.g., `["iphone 15", "macbook air m2", "ps5", "dewalt"]`). Each keyword runs in its own isolated session and all results merge into one deduplicated dataset.
- ✅ **Unlocked 1,000+ results pagination** — With `maxPages: 0` (the default), the scraper automatically walks `?page=1, 2, 3 …` for each keyword until `maxRecords` is reached or no new unique listings appear.
- ✅ **100% deduplicated output** — Every listing is keyed on its unique OfferUp `listingId`, guaranteeing zero duplicates across pages and overlapping keywords.
- ✅ **Complete core marketplace fields** — Populates `listingId`, `title`, numeric `price` (USD), item `location` (`"City, ST"`), `shippingAvailable` (`true`/`false`), `images` array, `listingUrl`, `searchKeyword`, `searchLocation`, and `scrapedAt` on ~100% of records.
- ✅ **Rich search filters** — Supports US city dropdown (`location`), custom City/State or 5-digit ZIP code (`locationCustom`), `radius` (`5` to `50` miles), `priceMin` / `priceMax`, `condition`, and `deliveryType` (`all`, `pickup`, `shipping`).
- ✅ **Optional detail-page enrichment (`scrapeDetails: true`)** — Visits individual listing URLs to capture `description`, `category`, `condition`, and seller attributes whenever OfferUp exposes them on the detail page.
- ✅ **Zero-config fallback** — Launch with empty `keywords` and the actor automatically samples 10 popular marketplace categories (`iphone`, `macbook`, `sofa`, `bike`, `ps5`, `nike`, `tv`, `dresser`, `guitar`, `stroller`).

***

### 🎯 Use cases

#### 1. Electronics, Console & Sneaker Flippers

- **Multi-SKU deal radar:** Run a single job with `keywords: ["iphone 15 pro", "ps5 disc", "nintendo switch oled", "ipad pro"]`, `priceMin: 100`, `priceMax: 650`, and `deliveryType: "shipping"` to surface shippable bargains nationwide.

#### 2. Recommerce & Trade-In Pricing Engines

- **Live trade-in valuation comps:** Pull 500–1,000 active listings per device model weekly, strip outliers, and compute live resale medians to calibrate trade-in offers and buyback pricing tables.

#### 3. Local Dealerships, Auto Wholesalers & Parts Buyers

- **Private-party vehicle sourcing:** Search `["honda civic", "toyota camry", "ford f150", "utility trailer"]` around target US metros (`Houston, TX`, `Phoenix, AZ`, `Los Angeles, CA`, `Miami, FL`, `Atlanta, GA`) to spot newly listed vehicles.

#### 4. Retail & Consumer Goods Analysts

- **Secondary-market saturation tracking:** Track how many active second-hand listings exist for power tools (Milwaukee, DeWalt, Makita), strollers (UPPAbaby, Bugaboo), or fitness gear (Peloton, Concept2) and how their asking prices compare to MSRP.

***

### 📥 Input parameters

Configure the actor via the Apify Console dropdowns or pass JSON via the API. All parameters are optional.

| Parameter | Type | Default | Prefill | Description |
|---|---|---|---|---|
| `keywords` | `array<string>` | `[]` | `["iphone"]` | One or more search keywords. Each keyword runs an independent paginated search. Leave empty to pull a diverse 10-keyword sample. |
| `location` | `string` | `"Los Angeles, CA"` | `"Los Angeles, CA"` | Pick from 20 major US metro areas or `""` (`Nationwide`). |
| `locationCustom` | `string` | `""` | — | Optional: Any US `"City, ST"` or 5-digit ZIP code (e.g., `"Nashville, TN"` or `"37201"`). Overrides the `location` dropdown when set. |
| `radius` | `string` | `"30"` | `"30"` | Search radius in miles: `"5"`, `"10"`, `"20"`, `"30"`, or `"50"`. |
| `condition` | `string` | `"all"` | `"all"` | Filter by reported item condition: `"all"`, `"new"`, `"like_new"`, `"good"`, `"fair"`, `"poor"`. |
| `deliveryType` | `string` | `"all"` | `"all"` | Filter by fulfillment method: `"all"` (pickup or shipping), `"pickup"` (local pickup only), or `"shipping"` (nationwide shipping available). |
| `priceMin` | `integer` | `0` | `0` | Minimum price in USD (`0` = no minimum). |
| `priceMax` | `integer` | `0` | `0` | Maximum price in USD (`0` = no maximum). |
| `scrapeDetails` | `boolean` | `false` | `false` | Visit each individual `/item/detail/{id}` page to enrich `description`, `category`, and seller fields when available. Leave `false` for fast feed scraping. |
| `maxRecords` | `integer` | `0` | `60` | Maximum total listings to collect across all keywords (`0` = unlimited; empty-keyword demo runs default to `100`). Set to `1000`+ for large pulls. |
| `maxPages` | `integer` | `0` | — | Maximum result pages per keyword. **`0` = unlimited (auto-governed by `maxRecords`)**. |
| `requestDelay` | `integer` | `2000` | `2000` | Delay between page loads in milliseconds (`1000`–`10000`). Keep at `2000`+ for smooth session longevity. |
| `proxyConfiguration` | `object` | Residential `US` | Residential `US` | Proxy configuration. **US Residential proxies** are pre-configured by default and required for OfferUp. |

#### Sample Input Recipes

##### Recipe 1: Fast single-keyword run (60 listings in ~35 seconds)

```json
{
  "keywords": ["iphone"],
  "location": "Los Angeles, CA",
  "radius": "30",
  "scrapeDetails": false,
  "maxRecords": 60,
  "maxPages": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

##### Recipe 2: Deep 1,000+ listing multi-keyword electronics & gaming sweep

```json
{
  "keywords": [
    "iphone 14",
    "iphone 15",
    "macbook pro",
    "ps5",
    "xbox series x",
    "nintendo switch",
    "ipad air",
    "airpods max"
  ],
  "location": "Los Angeles, CA",
  "radius": "50",
  "priceMin": 80,
  "priceMax": 1500,
  "scrapeDetails": false,
  "maxRecords": 1000,
  "maxPages": 0,
  "requestDelay": 2000
}
```

##### Recipe 3: Used trucks & cars search with price floor

```json
{
  "keywords": ["toyota tacoma", "ford f150", "honda civic"],
  "location": "Houston, TX",
  "radius": "50",
  "priceMin": 3000,
  "priceMax": 25000,
  "deliveryType": "pickup",
  "maxRecords": 300
}
```

***

### 📤 Output schema & field reference

Every OfferUp listing is emitted as a flat, consistent JSON object. Below is a real record from a verified run:

```json
{
  "listingId": "8344d3f3-5061-30d4-8076-24844ece1093",
  "title": "iPhone 15 Pro Max 256GB Unlocked",
  "price": 650,
  "condition": null,
  "location": "Los Angeles, CA",
  "postDate": null,
  "postDateAgo": null,
  "shippingAvailable": false,
  "category": null,
  "description": null,
  "images": [
    "https://images.offerup.com/2lFDUEBsfohWNozJH27qJoBWX7E=/250x542/ef18/ef183441661946179e0ea8a3a73aec68.jpg"
  ],
  "sellerName": null,
  "sellerRating": null,
  "sellerReviewCount": null,
  "sellerVerified": null,
  "sellerJoinDate": null,
  "sellerItemCount": null,
  "listingUrl": "https://offerup.com/item/detail/8344d3f3-5061-30d4-8076-24844ece1093",
  "searchKeyword": "iphone",
  "searchLocation": "Los Angeles, CA",
  "scrapedAt": "2026-11-02T00:22:23.911Z"
}
```

#### 🏷️ Core Listing, Price & Location Fields (Always Populated)

| Field | Type | Coverage | Description |
|---|---|---|---|
| `listingId` | `string` | 🟢 High (100%) | Unique OfferUp listing ID (UUID or numeric ID matching `listingUrl`) |
| `title` | `string` | 🟢 High (100%) | Listing headline as published by the seller |
| `price` | `number` | 🟢 High (~100%) | Asking price in US Dollars (USD) |
| `location` | `string` | 🟢 High (100%) | Item's reported `"City, ST"` location on OfferUp |
| `shippingAvailable` | `boolean` | 🟢 High (100%) | `true` if nationwide shipping is offered, `false` for local pickup only |
| `images` | `array<string>` | 🟢 High (100%) | Array of photo URLs hosted on OfferUp's CDN |
| `listingUrl` | `string` | 🟢 High (100%) | Direct link to the OfferUp item (`https://offerup.com/item/detail/{listingId}`) |
| `searchKeyword` | `string` | 🟢 High (100%) | The keyword from your input that produced this listing |
| `searchLocation` | `string` | 🟢 High (100%) | The target location string configured for the run |
| `scrapedAt` | `string` | 🟢 High (100%) | ISO-8601 UTC extraction timestamp |

#### 📝 Optional & Detail-Enriched Fields (`scrapeDetails: true`)

OfferUp's search feed omits extended item and seller metadata on most cards; these fields populate whenever OfferUp exposes them in the feed or when `scrapeDetails: true` is enabled:

| Field | Type | Coverage | Description |
|---|---|---|---|
| `condition` | `string \| null` | 🟡 Conditional | Item condition (`New`, `Like New`, `Good`, `Fair`, `Poor`) when exposed |
| `postDate` | `string \| null` | 🟡 Conditional | ISO creation timestamp when exposed by OfferUp |
| `postDateAgo` | `string \| null` | 🟡 Conditional | Relative posting time (e.g., `"2 hours ago"`) when exposed |
| `category` | `string \| null` | 🟡 Conditional (`scrapeDetails`) | OfferUp product category |
| `description` | `string \| null` | 🟡 Conditional (`scrapeDetails`) | Full text item description from the detail page |
| `sellerName` | `string \| null` | 🟡 Conditional (`scrapeDetails`) | Seller display name |
| `sellerRating` | `number \| null` | 🟡 Conditional (`scrapeDetails`) | Average seller rating (`1.0`–`5.0`) |
| `sellerReviewCount` | `integer \| null` | 🟡 Conditional (`scrapeDetails`) | Number of buyer reviews on the seller's profile |
| `sellerVerified` | `boolean \| null` | 🟡 Conditional (`scrapeDetails`) | OfferUp TruYou verification badge |
| `sellerJoinDate` | `string \| null` | 🟡 Conditional (`scrapeDetails`) | Seller account registration date |
| `sellerItemCount` | `integer \| null` | 🟡 Conditional (`scrapeDetails`) | Total items listed by the seller |

***

### 🏙️ Built-in US Metro Areas (`location` Dropdown)

Pick any of these 20 major US metropolitan areas directly from the `location` dropdown, or enter any US city/state or 5-digit ZIP code in `locationCustom`:

| West & Southwest | Midwest & South | Northeast & Southeast |
|---|---|---|
| `Los Angeles, CA` | `Chicago, IL` | `New York, NY` |
| `San Diego, CA` | `Detroit, MI` | `Philadelphia, PA` |
| `San Jose, CA` | `Houston, TX` | `Boston, MA` |
| `Seattle, WA` | `Dallas, TX` | `Miami, FL` |
| `Portland, OR` | `San Antonio, TX` | `Jacksonville, FL` |
| `Phoenix, AZ` | `Austin, TX` | `Atlanta, GA` |
| `Las Vegas, NV` · `Denver, CO` | | |

***

### 🔁 Pagination & scale

The **OfferUp Scraper** is built to scale from quick 60-item checks to **1,000+ listing sweeps**:

- **Unlocked multi-page pagination (`maxPages: 0`):** By default, `maxPages` is `0` (unlimited per keyword, governed by `maxRecords`). For each keyword, the scraper steps through `?page=1, 2, 3 …` (~30–50 listings per page) until `maxRecords` is reached or the search runs out of new unique items.
- **Empty-page streak detection:** If OfferUp reaches the end of a keyword's feed and returns 0 new unique listings for 2 consecutive pages, the scraper automatically closes that keyword and moves to the next keyword in your list.
- **Global `listingId` deduplication:** Every record is deduplicated across all pages and all keywords within the run (**0% duplicates** verified across 300+ listing runs).
- **Automatic session rotation on 403/429:** Each keyword gets a fresh US residential proxy session and homepage cookie warmup. If a page encounters a 403 or 429 block, the actor discards the burned session, rotates to a new residential IP, re-warms cookies, and retries the exact same page automatically.

***

### 💻 API Integration Examples

#### Python (`apify-client`)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("haketa/offerup-scraper").call(run_input={
    "keywords": ["iphone 15", "macbook air", "ps5"],
    "location": "Los Angeles, CA",
    "radius": "50",
    "maxRecords": 500,
    "maxPages": 0,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    ship = "Ships" if item["shippingAvailable"] else "Local Pickup"
    print(f"${item['price']:>6} | {item['title'][:45]:45s} | {item['location']} ({ship}) | {item['listingUrl']}")
```

#### Node.js / TypeScript (`apify-client`)

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

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

const run = await client.actor('haketa/offerup-scraper').call({
    keywords: ['iphone', 'macbook', 'ps5'],
    location: 'Los Angeles, CA',
    radius: '50',
    maxRecords: 300,
    maxPages: 0,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Extracted ${items.length} unique OfferUp listings`);
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/haketa~offerup-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "keywords": ["iphone"],
    "location": "Los Angeles, CA",
    "maxRecords": 100
  }'
```

#### Warehouse & BI Integration (PostgreSQL / BigQuery / Snowflake)

Stream completed datasets into your analytics warehouse via Apify Webhooks to track historical price depreciation and local resale velocity:

```sql
CREATE TABLE offerup_listings (
    listing_id         TEXT PRIMARY KEY,
    title              TEXT,
    price_usd          NUMERIC,
    condition          TEXT,
    location           TEXT,
    shipping_available BOOLEAN,
    search_keyword     TEXT,
    search_location    TEXT,
    listing_url        TEXT,
    images             JSONB,
    scraped_at         TIMESTAMPTZ
);
```

***

### 💡 Best Practices & Pro Tips

- **Combine multiple specific keywords for 1,000+ item pulls:** Because OfferUp caps the depth of any single search query, passing 5–10 related keywords (e.g., `["iphone 13", "iphone 14", "iphone 15", "iphone pro max"]`) with `maxPages: 0` and `maxRecords: 1000` is the fastest way to harvest 1,000+ unique, deduplicated listings.
- **Keep `requestDelay` at `2000` ms:** A 2-second pause between page loads keeps residential proxy sessions healthy and minimizes session rotations.
- **Understand OfferUp's IP geolocation behavior:** OfferUp blends your `location` query parameter with the geolocation of the browsing US residential IP, and also mixes nationwide shippable listings into local feeds. Every output record includes the item's exact `location` (`"City, ST"`) and `shippingAvailable` boolean so you can filter downstream by metro or state.
- **Leave `scrapeDetails: false` for high-speed price & inventory feeds:** Card mode extracts `listingId`, `title`, `price`, `location`, `shippingAvailable`, `images`, and `listingUrl` at ~30–50 listings per page load.

***

### ❓ Frequently Asked Questions

#### How many OfferUp listings can I scrape in a single run?

You can collect **1,000+ unique listings** in a single run by setting `maxRecords: 1000` (or `0` for unlimited) and leaving `maxPages: 0`. Combine several keywords in `keywords` to maximize total unique inventory.

#### Do I need an OfferUp account or login?

No. The actor extracts public marketplace listings without requiring an OfferUp account or API key.

#### Why are US Residential proxies required?

OfferUp blocks all datacenter IP ranges at the network edge. The actor is pre-configured to use Apify's `RESIDENTIAL` proxy pool pinned to the United States (`country-US`), rotating sessions automatically per keyword and on any 403/429 response.

#### Why are `condition`, `postDate`, or `sellerName` sometimes `null`?

OfferUp's search feed reliably provides `listingId`, `title`, `price`, `location`, `shippingAvailable`, `images`, and `listingUrl` (100% coverage), but frequently omits seller and condition metadata on search cards. Those optional fields are populated whenever OfferUp surfaces them or when `scrapeDetails: true` is enabled.

#### Can I schedule automated runs for deal alerts?

Yes! Use the Apify Scheduler to run your search hourly or daily, and connect a webhook, Make, Zapier, or n8n workflow to compare `listingId` and `price` against your previous run.

***

### 🔗 Related classifieds & marketplace scrapers

Building a multi-platform recommerce or classifieds dataset? Pair this **OfferUp scraper** with sibling scrapers from [haketa](https://apify.com/haketa):

- [Kijiji.ca Scraper (Canada)](https://apify.com/haketa/kijiji-scraper) — Canada's #1 classifieds marketplace
- [OLX Brazil Scraper (Brazil)](https://apify.com/haketa/olx-brasil-scraper) — Brazil classified ads, prices, attributes & vehicle benchmarks
- [Marktplaats.nl Scraper (Netherlands)](https://apify.com/haketa/marktplaats-scraper) — Netherlands' top classifieds platform
- [Kleinanzeigen.de Scraper (Germany)](https://apify.com/haketa/kleinanzeigen-scraper) — Germany's largest classifieds marketplace
- [Chotot.com Scraper (Vietnam)](https://apify.com/haketa/chotot-scraper) — Vietnam buy-and-sell classifieds
- [Mourjan Scraper (MENA)](https://apify.com/haketa/mourjan-scraper) — Middle East classifieds marketplace

***

### 🔍 SEO Keywords

OfferUp scraper · scrape OfferUp · OfferUp data extractor · OfferUp API alternative · US local marketplace scraper · used electronics price tracker · OfferUp lead generation · recommerce price intelligence · reseller deal finder · bulk export JSON CSV Excel API · 1,000+ results pagination · B2B intelligence

***

### 📋 Changelog

| Version | Date | Notes |
|---|---|---|
| **1.2.0** | **2026-11** | **Unlocked 1,000+ deep pagination & auto page scaling:** Changed `maxPages` default from `10` to `0` (unlimited, governed by `maxRecords`), added automatic multi-page scaling on default keyword runs when `maxRecords > 100`, added 2-page empty-streak detection to stop cleanly at the end of results, and removed `fields` block from `dataset_schema.json`. |
| **1.1.0** | **2026-11** | **Verified 300+ multi-keyword extraction:** Confirmed 0% duplicates and 100% fill rate on all core marketplace fields (`listingId`, `title`, `price`, `location`, `shippingAvailable`, `images`, `listingUrl`). Tuned fast 60-listing prefill for sub-minute runs. |
| **1.0.0** | **2026-06** | Initial release — Multi-keyword OfferUp search, US residential session warmup & rotation, price/condition/delivery filters, and optional detail-page enrichment. |

# Changelog

This Actor's version history is a separate document: https://apify.com/haketa/offerup-scraper/changelog.md

# Actor input Schema

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

What are you looking for? Each keyword runs its own search. Leave empty to pull a mixed sample of popular items automatically.

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

Pick a US metro area to search around. Choose 'Nationwide (popular cities)' to sample listings from several large markets at once.

## `locationCustom` (type: `string`):

Prefer a different area? Type any US city and state or a ZIP code (e.g. 'Nashville, TN' or '37201'). When set, this overrides the City dropdown above.

## `radius` (type: `string`):

How far from the city to search, in miles.

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

Only keep listings in the condition you want.

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

Filter by how the item can be received.

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

Lowest price to include, in US dollars. Leave 0 for no minimum.

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

Highest price to include, in US dollars. Leave 0 for no maximum.

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

Visit each listing for the full description, seller profile, all images and category. Richer data, but slower.

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

Stop after this many listings in total. Set 0 for unlimited.

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

How many result pages to collect for each keyword. Set 0 for unlimited (governed by Max listings).

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

Pause between page loads. A gentle pace keeps results reliable.

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

US residential proxy is recommended for the best results.

## Actor input object example

```json
{
  "keywords": [
    "iphone"
  ],
  "location": "Los Angeles, CA",
  "radius": "30",
  "condition": "all",
  "deliveryType": "all",
  "priceMin": 0,
  "priceMax": 0,
  "scrapeDetails": false,
  "maxRecords": 60,
  "maxPages": 0,
  "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"
    ],
    "scrapeDetails": false,
    "maxRecords": 60,
    "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"],
    "scrapeDetails": False,
    "maxRecords": 60,
    "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(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 '{
  "keywords": [
    "iphone"
  ],
  "scrapeDetails": false,
  "maxRecords": 60,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call haketa/offerup-scraper --silent --output-dataset

```

## MCP server setup

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

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

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/x0T5IIhguxNKmf1et/builds/5ckPrS7K3667LBvtA/openapi.json
