# OfferUp Scraper API - Listings & Sellers, $1.40/1K (`sweet_stickball/offerup-scraper`) Actor

OfferUp scraper and API alternative: extract marketplace listings for any search near a US city or ZIP code with title, price, condition, description, category, location with coordinates, posting date, seller name and rating, photos and shipping. Price and radius filters, no login.

- **URL**: https://apify.com/sweet_stickball/offerup-scraper.md
- **Developed by:** [CrawlKit](https://apify.com/sweet_stickball) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.84 / 1,000 listings

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

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

## OfferUp Scraper - Marketplace Listings & Prices

Scrapes OfferUp, the US peer-to-peer marketplace. Give it search keywords and a US city or ZIP code; it returns one flat JSON record per listing with the title, price, condition, full description, category, location with coordinates, posting date, public seller name and rating, all photo URLs and the shipping / local pickup flags. It can also return a single listing from its URL.

### What it returns

- Search results around a US location (`City, ST` or a 5-digit ZIP), with optional radius and price filters.
- For every listing, the detail fields shown on the listing page: description, condition, category, `postedAt`, approximate latitude/longitude, all photos, seller name, seller id, rating, join date and items sold, shipping and pickup options, vehicle make/model/year/miles for vehicle listings.
- Listings are de-duplicated by `listingId` across result pages.

### Input

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `query` | string | Yes\* | | Search keywords, e.g. `iphone`, `couch`, `mountain bike` |
| `location` | string | No | OfferUp default for the request IP | US city as `City, ST` (`Seattle, WA`, `Los Angeles, California`) or a ZIP code (`98101`) |
| `radiusMiles` | integer | No | 30 (OfferUp default) | Search radius in miles. OfferUp's own options are 5, 10, 20, 30, 50 |
| `minPrice` | integer | No | | Minimum price in USD |
| `maxPrice` | integer | No | | Maximum price in USD |
| `maxItems` | integer | No | 20 | Maximum number of listings to return |
| `listingUrl` | string | No | | One listing URL (`https://offerup.com/item/detail/<id>`). When set, only this listing is returned and the search fields are ignored |

\*`query` is required unless `listingUrl` is set.

Example:

```json
{
    "query": "couch",
    "location": "Los Angeles, CA",
    "maxItems": 100
}
```

### Output

One dataset item per listing. Example from a real run (`couch`, `Los Angeles, CA`):

```json
{
    "listingId": "d83e89f3-77bb-3de8-b85f-9f03fe7a7c4b",
    "title": "Love Seat",
    "url": "https://offerup.com/item/detail/d83e89f3-77bb-3de8-b85f-9f03fe7a7c4b",
    "price": 200,
    "originalPrice": 200,
    "currency": "USD",
    "isFirmPrice": false,
    "condition": "Used",
    "description": "Two person Seat love seat. In great condition was used for staging air bnb. Also have the longer piece available",
    "category": "Home & Garden > Furniture",
    "postedAt": "2026-10-23T20:55:08.005Z",
    "lastEditedAt": null,
    "status": "LISTED",
    "quantity": 1,
    "location": "Los Angeles, CA",
    "city": "Los Angeles",
    "state": "CA",
    "latitude": 34.271,
    "longitude": -118.625,
    "image": "https://images.offerup.com/pTWQb6hH716FT4f25UTUigdPQ3s=/1280x960/670f/670f70bf65a84366bfea811a11440744.jpg",
    "images": [
        "https://images.offerup.com/pTWQb6hH716FT4f25UTUigdPQ3s=/1280x960/670f/670f70bf65a84366bfea811a11440744.jpg",
        "https://images.offerup.com/OUDj2094rzdUzfyShqmSA73fm-Q=/1280x960/6e0a/6e0ae879f5d94430b439fb754f9bd952.jpg"
    ],
    "photoCount": 2,
    "sellerName": "Andrea",
    "sellerId": "35142786",
    "sellerRating": 5,
    "sellerRatingCount": 5,
    "sellerJoinedAt": "2016-05-07T04:56:29Z",
    "sellerItemsSold": 5,
    "isBusinessSeller": false,
    "isVerifiedSeller": null,
    "isShippable": false,
    "shippingPrice": null,
    "sellerPaysShipping": false,
    "localPickup": true,
    "vehicleMake": null,
    "vehicleModel": null,
    "vehicleYear": null,
    "vehicleMiles": null,
    "hasDetails": true,
    "searchQuery": "couch",
    "scrapedAt": "2026-10-23T22:09:43+00:00"
}
```

| Field | Description |
|---|---|
| `listingId`, `url` | OfferUp listing id and page URL |
| `title`, `description`, `category` | Listing text and category path |
| `price`, `originalPrice`, `currency`, `isFirmPrice` | Asking price (numeric, USD), price before a price drop, firm-price flag |
| `condition` | `New`, `Open box`, `Reconditioned`, `Used` or `For parts` |
| `postedAt`, `lastEditedAt`, `status`, `quantity` | ISO 8601 dates, listing state, quantity |
| `location`, `city`, `state`, `latitude`, `longitude` | Public listing location; coordinates are approximate (rounded by OfferUp) |
| `image`, `images`, `photoCount` | Main photo, all full-size photo URLs |
| `sellerName`, `sellerId`, `sellerRating`, `sellerRatingCount`, `sellerJoinedAt`, `sellerItemsSold`, `isBusinessSeller`, `isVerifiedSeller` | Public seller profile fields (no contact details) |
| `isShippable`, `shippingPrice`, `sellerPaysShipping`, `localPickup` | Delivery options |
| `vehicleMake`, `vehicleModel`, `vehicleYear`, `vehicleMiles` | Vehicle listings only |
| `hasDetails` | `false` if only the search-card fields could be fetched for this listing |
| `searchQuery`, `scrapedAt` | Search keywords and extraction time |

### How it works

The Actor reads the same JSON endpoint that offerup.com uses in the browser (`/api/graphql`): the search feed for the result list, then the listing detail query for each listing (fetched in parallel). City names are converted to coordinates with the public zippopotam.us ZIP database. Requests go through Apify Proxy (datacenter, a new session on each retry, residential only as a last resort). No login, no cookies and no captcha solving.

### Pricing

Pay-per-event, **no start fee**: **$1.40 per 1,000 listings** on the Apify Free plan, with lower prices on paid plans. Each listing pushed to the dataset is one event (full listing details included).

| Event | Free | Starter | Scale | Business | Enterprise |
|-------|------|---------|-------|----------|------------|
| Listing (`LISTING`) | $1.40 | $1.20 | $1.00 | $0.84 | $0.84 |

Prices in USD per 1,000 events.

#### Cost examples (Free plan)

| Scenario | Listings | Cost |
|----------|----------|------|
| Quick look | 20 | $0.028 |
| One city search | 300 | $0.42 |
| Market research | 5,000 | $7.00 |

### Limitations

- US only (OfferUp's market). `location` must be `City, ST` or a 5-digit ZIP; an unknown city or ZIP fails the run with an explicit message.
- The OfferUp website search returns local listings; listings that are only available with nationwide shipping rarely appear, so `isShippable` is mostly `false`.
- Some listings have a price of `0` (free items or "make an offer" listings) and are kept unless `minPrice` is set.
- Seller ratings are `null` when the seller has no ratings yet; `isVerifiedSeller` is only filled when OfferUp shows the badge.
- Latitude/longitude are OfferUp's public approximate coordinates of the listing, not an exact address.

### Related Actors

- [Vinted Scraper - Listings, Prices & Sellers](https://apify.com/sweet_stickball/vinted-scraper) — Scrape Vinted search results on any Vinted country site (France, Germany, UK, US, Spain, Italy, Poland...): title, price, buyer fee, brand, size, condition, favourites, photo and seller id.
- [Best Buy Scraper - Product Prices, Ratings & Stock](https://apify.com/sweet_stickball/bestbuy-scraper) — Scrape bestbuy.com search results, category pages or product URLs: SKU, name, price, regular price, savings, on-sale flag, rating, review count, brand, model, category, image and stock button state.
- [Zillow Scraper - Homes for Sale & Rent Listings](https://apify.com/sweet_stickball/zillow-scraper) — Scrape Zillow listings for a city, ZIP code or neighborhood: price, Zestimate, beds, baths, square feet, home type, status, address and coordinates, for sale or for rent.

# Actor input Schema

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

What to search on OfferUp (e.g. 'iphone', 'couch', 'mountain bike'). Required unless 'listingUrl' is set.

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

US city as 'City, ST' (e.g. 'Seattle, WA') or a 5-digit ZIP code (e.g. '98101'). Empty = OfferUp's default location for the request IP.

## `radiusMiles` (type: `integer`):

Distance around the location. Empty = OfferUp default (30 miles). OfferUp's own options are 5, 10, 20, 30 and 50 miles.

## `minPrice` (type: `integer`):

Only listings priced at or above this amount (USD).

## `maxPrice` (type: `integer`):

Only listings priced at or below this amount (USD).

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

Maximum number of listings to return (each listing is one billed result).

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

OfferUp listing URL (https://offerup.com/item/detail/<id>). When set, the Actor returns only this listing and ignores the search fields.

## Actor input object example

```json
{
  "query": "couch",
  "location": "Los Angeles, CA",
  "maxItems": 10,
  "listingUrl": "https://offerup.com/item/detail/d83e89f3-77bb-3de8-b85f-9f03fe7a7c4b"
}
```

# Actor output Schema

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

Dataset items shown with the 'results' view.

# 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 = {
    "query": "iphone",
    "location": "Seattle, WA",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("sweet_stickball/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 = {
    "query": "iphone",
    "location": "Seattle, WA",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("sweet_stickball/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 '{
  "query": "iphone",
  "location": "Seattle, WA",
  "maxItems": 10
}' |
apify call sweet_stickball/offerup-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sweet_stickball/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/Id3EbCw0l8bBNtCJ8/builds/qUph9cZDK1BgYXSOF/openapi.json
