# OfferUp Scraper: Local Listings, Prices, Sellers (`automation_craft/offerup-scraper`) Actor

Scrape OfferUp listings by keyword, category and US city, ZIP code or map point with radius: title, price, place, photo and private or dealer seller. Optional details: description, posted time, condition, seller stats, car make, model, year and VIN. New listing monitor. JSON, CSV, Excel.

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

## Pricing

from $1.33 / 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: Local Listings, Prices, Sellers

**Scrape OfferUp listings** by keyword, category and US place into clean rows: title, price as a number, city and state,
photo, link, seller type (private or dealer) and, for vehicles, the mileage. Search around a city ("Houston, TX"), a ZIP
code or a map point with OfferUp's own radius, in several places at once. On request each listing's details are added:
description, posted time, original price, condition, coordinates, category, all photos, the seller's join date, items sold,
rating and the phone number OfferUp shows for dealers and business accounts, and for cars the make, model, year, mileage,
color and VIN. Give the run a monitor name and schedule it: each run then delivers only the listings that are new.

No OfferUp account, no cookies, no API key, no browser. The Actor reads only what OfferUp shows every visitor, checks that
OfferUp applied each search exactly as you sent it. Private sellers' name and phone number fields and exact coordinates
are switched off by default, and contacts they write into texts are masked on a best effort basis.

This Actor is not affiliated with, endorsed or sponsored by OfferUp Inc. OfferUp is a trademark of OfferUp Inc.

#### Who uses it

- **Flippers and resellers**: a monitor on a narrow search (a model, a price range, a few cities) that delivers each new
  listing once, newest first, to a spreadsheet, Slack or e-mail through Apify's integrations.
- **Car buyers and small dealers**: Cars & Trucks around a city with year and mileage filters, dealers only or no
  dealers, with make, model, year, mileage and VIN from the details.
- **Price research**: what a product sells for in several US cities, with prices as numbers and the original price next to
  the asking price.
- **Data teams and agents**: a structured OfferUp feed through the Apify API, one schema for every category.

### Quick start

1. Type what you want in **Keywords** (`iphone`, `sectional couch`), and optionally **Categories** (`Cars & Trucks`, or the
   id `5.1`).
2. Add one or more **Places**: `Houston, TX`, a ZIP code such as `77002`, or coordinates such as `29.7604, -95.3698`.
3. Optionally set a **Radius**, a price range, conditions, a seller type or the vehicle filters.
4. Turn on **Add listing details** if you need descriptions, posted times, sellers and car fields.
5. Run it, then download the dataset as Excel, CSV or JSON, or read it through the Apify API.

### How new is new?

OfferUp shows a new listing to the public, and so to this Actor, about 30 minutes after it is posted: the newest public
listings in Houston, Los Angeles, New York and Chicago were 30.0 to 31.2 minutes old (24 of 24, measured 2026-10-11).
OfferUp sells the earlier view to its Premium members. This Actor reads the same public feed as every visitor; it does not
see listings sooner.

### How deep does a search go?

Searches read OfferUp's **recent first** order by default, page after page along OfferUp's own cursor, about 50 listings a
page (100 for a search with places only). A recent first walk of 40 pages in Houston met almost no repeats (1,992
different "iphone" listings in 1,998 rows, about two weeks back), so depth is set by **Maximum pages per search** (10 by default, up to
100\). In OfferUp's best match order listings start to repeat after about 12 pages; the run counts the repeats and bills each
listing once. In recent first order OfferUp's search also returns related listings (a case for "iphone"); every row says
`titleMatchesKeyword`, and **Only titles with the keyword** leaves the others out for free.

### What you get

One row per listing (`type: "listing"`). Measured fill rates (2026-10-11): search rows from 1,390 rows of 14 pages, details
from 62 listings.

| Field | What it holds | Filled |
|---|---|---|
| `listingId`, `url`, `title`, `imageUrl`, `locationName`, `city`, `state`, `isLocalPickup` | the listing as OfferUp's search shows it (`state` as a two letter code, also where OfferUp writes the state's name) | 100% |
| `price`, `priceText`, `isCallForPrice` | price in USD as a number; null when the seller asks to call for the price | price on 99.6% |
| `sellerType` | `dealer` (a vehicle dealer) or `private` (every other seller: private people and shops), OfferUp's own mark on every search row | 100% |
| `vehicleMiles` | mileage shown on vehicle rows | the vehicle rows |
| `isPromoted` | a promoted listing OfferUp placed at the top of the first pages | 4.3% of rows are promoted |
| `titleMatchesKeyword` | every word of the keyword starts a word of the title | on keyword searches |
| `searchKeyword`, `searchCategory`, `searchLocation`, `searchLatitude`, `searchLongitude`, `searchRadiusMiles`, `searchSort`, `page`, `position` | the search that found the listing, with the radius OfferUp applied | 100% |
| `description` | the description (details) | 82% |
| `postedAt`, `lastEditedAt` | when it was posted and last edited, UTC (details) | 100%, last edit 13% |
| `originalPrice`, `condition`, `conditionCode`, `isFirmPrice`, `quantity`, `listingState` | details | 100% |
| `latitude`, `longitude`, `coordinatesRounded` | the listing's map point (details); rounded to about 1 km for private sellers by default | 100% |
| `categoryId`, `categoryName`, `categoryPath`, `photoUrls`, `photoCount` | details | 100% |
| `sellerId`, `sellerJoinedAt`, `sellerItemsSold` | details | 100% |
| `sellerRatingAverage`, `sellerRatingCount` | details | rated sellers 47% |
| `sellerName` | dealers and business accounts; private sellers only with **Include private sellers' personal data** | dealers 100% |
| `sellerPhone` | the seller's phone number as OfferUp shows it to any visitor, written as OfferUp gives it (`8664012666`), details; dealers and business accounts always, private sellers only with **Include private sellers' personal data**; null when OfferUp shows none | dealers 6 of 6, business accounts 5 of 7, private sellers 0 of 13 (2026-10-14) |
| `sellerIsAutosDealer`, `sellerIsBusiness`, `sellerIsTruyouVerified` | details: dealer flag, business account, TruYou verified (null when OfferUp does not state it) | dealer flag 62 of 62 |
| `vehicleMake`, `vehicleModel`, `vehicleYear`, `vehicleMileage`, `vehicleColor`, `vehicleVin`, `vehicleTitleStatus`, `vehicleBody`, `vehicleTransmission`, `vehicleFuelType`, `vehicleTrim`, `vehicleDrivetrain` | vehicles (details) | make on 14 of 14 vehicles read, VIN on 11 of 14 |

**Private sellers' personal data** is off by default. Switch on **Include private sellers' personal data** to also get, for
private sellers, the name, the phone number and the exact coordinates (with details), and the phone numbers and e-mail
addresses they write into the texts of a row (title, description, place, category and vehicle fields), all as OfferUp
shows them to any visitor.
With it off, the name and phone number are empty, coordinates are rounded to about 1 km, and contacts in the texts are
masked on a best effort basis (a contact written in an unusual way can stay; other personal details a seller writes,
such as a name, are not masked; a text longer than 100,000 characters is cut there, far beyond any OfferUp description). Dealers' and
business accounts' contact details are delivered either way. You are responsible for a lawful use of personal data, GDPR
included.

A real row (a dealer car with details, shortened):

```json
{
  "type": "listing",
  "listingId": "fa5a4baf-f86c-347d-a274-4e0fc649923a",
  "url": "https://offerup.com/item/detail/fa5a4baf-f86c-347d-a274-4e0fc649923a",
  "title": "2026 Porsche Macan",
  "price": 83679,
  "originalPrice": 92220,
  "locationName": "Plano, TX",
  "sellerType": "dealer",
  "vehicleMiles": 3192,
  "postedAt": "2026-06-18T03:54:34.281Z",
  "condition": "Used",
  "categoryPath": "Vehicles > Cars & Trucks",
  "sellerName": "Porsche Plano",
  "sellerPhone": "8664012666",
  "sellerJoinedAt": "2025-07-30T22:38:44Z",
  "vehicleMake": "Porsche",
  "vehicleModel": "Macan",
  "vehicleYear": 2026,
  "vehicleVin": "WP1AG2A50TLB40637",
  "searchLocation": "Dallas, TX",
  "searchRadiusMiles": 80,
  "detailsIncluded": true
}
```

Free rows, never charged: one coverage row per search (`type: "search"`: pages read, listings seen and delivered, listings
already delivered or known to the monitor, listings left out by filters, the radius, order and category OfferUp applied,
`complete`, `stoppedBy`, and for a monitor `newListingsMayLieBeyond`), status rows (`type: "status"`) for input that cannot be used, a place OfferUp does not know (with
OfferUp's suggestions), a category name several categories share (with their ids), a listing that no longer exists, a
search OfferUp did not apply as sent (with what it applied and the values it offers), and a run summary (`type: "summary"`)
at the end.

### How much does it cost to scrape OfferUp?

Pay per event, with Apify's Store discounts by plan:

| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
| Listing (one listing row) | $0.00186 | $0.0017 | $0.00154 | $0.00133 |
| Listing detail (the details of a delivered listing, only when details are read) | $0.0018 | $0.0016 | $0.0014 | $0.0012 |
| Results page (only in monitor runs: one results page read, about 50 listings) | $0.00015 | $0.00015 | $0.00015 | $0.00015 |
| Actor start (once per run) | $0.007 | $0.007 | $0.007 | $0.007 |

Platinum and Diamond plans pay the Gold price. The Store pricing card shows these prices per 1,000 events: "$1.86 / 1,000"
on the Listing row means one listing costs 0.186 cents.

Examples on the Free plan: 100 listings cost $0.007 + 100 x $0.00186 = $0.193. 1,000 listings cost $1.867. 1,000 listings
with their details cost $0.007 + 1,000 x ($0.00186 + $0.0018) = $3.667. An hourly monitor of 5 searches that reads 1 page each
and finds 10 new listings costs $0.007 + 5 x $0.00015 + 10 x $0.00186 = $0.02635 per run.

Free: listings left out by your filters, listings already delivered in the run, listings a monitor delivered before,
listings that no longer exist, places OfferUp does not know, searches OfferUp did not apply as sent, invalid input, coverage
rows, status rows and the summary. A listing link is always read with its details, so each one delivered is billed as Listing
plus Listing detail.

Work that delivers nothing is bounded: a run may send 40 requests plus 2 per listing, 2 per listing detail and 2 per Results
page delivered before it stops with a status row that says so. A filter that almost no listing passes, or a long list of
listing links that no longer exist, ends there; narrow the search or split the list. A monitor's own results pages are paid
as Results pages and never count against it.

### Input

| Field | What it does |
|---|---|
| `keywords` | Search words as you would type them on OfferUp (`iphone`, `toyota camry`). |
| `locations` | US places: `Houston, TX` (or `Houston, Texas`), a 5 digit ZIP code (`77002`), or coordinates (`29.7604, -95.3698`). Each is checked with OfferUp's own place search and geocoder. A city must be written as OfferUp writes it (`St Louis, MO`); a free row lists OfferUp's suggestions when it is not. |
| `categories` | OfferUp categories by id (`5.1`), name (`Cars & Trucks`) or path (`Vehicles > Cars & Trucks`), from OfferUp's own list of 1,244. |
| `listingUrls` | OfferUp listing links or listing ids; each is read with its details. |
| `radiusMiles` | Distance around each place. OfferUp offers 5, 10, 20, 30 (default) or 50 miles in most categories, and 25, 80 (default), 100, 200 or 5000 in Cars & Trucks. Another value is answered with a free row listing the offered values. |
| `sort` | `newest` (default), `best_match`, `closest`, `price_low`, `price_high`. A monitor and a search with places only read `newest`. |
| `minPrice`, `maxPrice` | Price range in whole dollars, up to 1,000,000. Listings without a price are left out when it is set. |
| `conditions` | `NEW`, `OPEN_BOX`, `REFURBISHED`, `USED`, `BROKEN`, `OTHER` (needs a keyword or category). |
| `sellerType` | `any`, `private` or `dealer`, from OfferUp's own mark on every search row: `dealer` keeps vehicle dealers, `private` every other seller (private people and shops such as furniture stores; with details, `sellerIsBusiness` tells them apart). |
| `vehicleMinYear`, `vehicleMaxYear`, `vehicleMaxMileage` | Cars & Trucks only (category `5.1` and its sub categories). OfferUp offers mileage limits of 25,000 to 200,000 in steps of 25,000. |
| `includePromoted` | Include OfferUp's promoted listings (default on; each is marked `isPromoted`). |
| `onlyTitleMatches` | Leave out related listings whose title does not carry the keyword (free). |
| `includeDetails` | Read each delivered listing's details (Listing detail). |
| `includePrivateSellerDetails` | Include private sellers' personal data: names, phone numbers, exact coordinates, and the phone numbers and e-mail addresses written into the row's texts, which are otherwise masked on a best effort basis (off by default). |
| `maxItems` | Most listing rows this run delivers (default 100). |
| `maxPagesPerSearch` | Results pages per search, 1 to 100 (default 10). |
| `monitorName` | A name for the monitor memory (new listings only). |

Places, keywords and categories are combined: every keyword is searched in every category around every place (at most 100
searches a run). Example input:

```json
{
  "keywords": ["ps5", "nintendo switch"],
  "locations": ["Houston, TX", "Dallas, TX", "78701"],
  "maxPrice": 400,
  "sellerType": "private",
  "onlyTitleMatches": true,
  "maxItems": 300
}
```

Cars from private sellers, 2018 or newer, under 75,000 miles, with details:

```json
{
  "categories": ["5.1"],
  "keywords": ["honda civic"],
  "locations": ["Phoenix, AZ"],
  "vehicleMinYear": 2018,
  "vehicleMaxMileage": 75000,
  "sellerType": "private",
  "includeDetails": true
}
```

### The monitor: new listings only

Give the run a **Monitor name** and schedule it. The monitor remembers every listing it delivered: a later run with the
same name and the same settings reads the newest **Maximum pages per search** pages of each search (its window) and delivers
and bills only the listings it has not delivered before; listings it delivered before are skipped for free. A monitor run pays
a Results page event for every page it reads, so keep the window small for a frequent monitor (1 or 2 pages an hour is
enough for most searches). Listings a run did not reach (its limits, an error) are delivered by a later run while they are
still in the window, and a listing your filters left out is judged again on every run. When the last page of the window
still held new listings, the coverage row says `newListingsMayLieBeyond: true`: more listings arrived between two runs than
the window holds, so raise the pages or run more often. A monitor name belongs to one set of settings; use a new name for
other searches, and schedule runs on one name so they do not overlap (an overlapping run reads nothing and says why). A
monitor remembers up to 100,000 delivered listings; after that it holds new ones back with a free status row: start a new
monitor name.

### FAQ

#### Does OfferUp have an API?

OfferUp offers no public API for its listings. This Actor reads the same public search and listing data any visitor sees
and gives you the listings as rows that you can read through the Apify API, with no key from OfferUp.

#### Is it legal to scrape OfferUp?

This Actor reads only public data without logging in: what OfferUp shows any visitor, including the phone number it shows
for dealers and business accounts. It never requests the e-mail addresses OfferUp holds.
OfferUp's terms restrict automated collection and commercial use; you are responsible for a lawful use of the data you
collect, including personal data.

#### How do I get notified when new OfferUp listings are posted?

Run a search with a **Monitor name** on an Apify schedule (every hour, for example). Each run delivers only the listings that
are new to the monitor; connect the run to Slack, e-mail, Google Sheets or a webhook with Apify's integrations. New listings
reach OfferUp's public feed about 30 minutes after they are posted.

#### Can I search OfferUp in another city or nationwide?

Yes for other cities: give any US city as "City, ST", a ZIP code or coordinates, several in one run, with OfferUp's radius
of up to 50 miles (5,000 in Cars & Trucks). OfferUp is local pickup only, so there is no nationwide search; list the cities
you want.

#### Will I get blocked when scraping OfferUp?

The Actor uses Apify's proxy and moves to a fresh address when OfferUp refuses one (at most three times per run). If OfferUp
keeps refusing, the run stops with a status row that says so rather than delivering partial data as complete.

#### Why does this Actor run with limited permissions?

It needs no access to your other Apify data. It only writes to its own run's dataset and key-value store and, when you use
a monitor, to one named key-value store it creates itself for that monitor.

### What this Actor does not do

- No listings sooner than the public feed: OfferUp shows a new listing about 30 minutes after it is posted (Premium members
  see it earlier).
- No e-mail field: OfferUp's own e-mail field is never requested.
- No nationwide search and no shipping filter: OfferUp has been local pickup only since October 2025.
- No radius, price or condition that OfferUp does not offer: OfferUp would replace it without a word, so such a search is
  answered with a free row that lists the values OfferUp offers.
- No pasted OfferUp search links: a search link does not carry its place (OfferUp keeps it in a cookie); give keywords,
  categories and places instead.
- No price history, price drop alerts or tracking of sold and removed listings: the monitor delivers new listings only.
- No deal score and no built in alerts: connect Apify's integrations (Slack, e-mail, a webhook) to a monitor run, and score
  the rows with your own rule.
- No age filter ("posted in the last N hours"): a search row carries no post time (the details do); a monitor delivers only
  what is new since its last run.
- No vehicle make filter: OfferUp's make filter takes internal codes; search the make as a keyword in Cars & Trucks.
- No view counts, messages, offers, posting, or anything behind a login.
- No photo download: photo addresses are in every row.

### API

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~offerup-scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["iphone"], "locations": ["Houston, TX"], "maxItems": 20}'
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('automation_craft/offerup-scraper').call({ keywords: ['iphone'], locations: ['Houston, TX'], maxItems: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((x) => x.type === 'listing'));
```

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("automation_craft/offerup-scraper").call(run_input={"keywords": ["iphone"], "locations": ["Houston, TX"], "maxItems": 20})
rows = [x for x in client.dataset(run["defaultDatasetId"]).iterate_items() if x["type"] == "listing"]
```

### Changelog

See the Changelog tab.

### More data tools by Automation Craft

- [Airbnb Scraper: Prices, Calendar, Reviews](https://apify.com/automation_craft/airbnb-scraper)
- [Amazon Product Scraper - Search, Best Sellers](https://apify.com/automation_craft/amazon-data-scraper)
- [Trustpilot Reviews Scraper: Coverage Per Company](https://apify.com/automation_craft/trustpilot-reviews-scraper)
- [Google Trends Scraper - Compare and Trending Now](https://apify.com/automation_craft/google-trends-scraper)
- [US New Business Registrations Scraper - LLC Leads](https://apify.com/automation_craft/us-new-business-registrations-scraper)
- [Meta Ads Library Scraper - Ad Library, All Filters](https://apify.com/automation_craft/meta-ads-library-scraper)

# Changelog

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

# Actor input Schema

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

Search words as you would type them on OfferUp, for example iphone, sectional couch or toyota camry. Up to 100 characters each.

## `locations` (type: `array`):

US places written as "City, ST" (Houston, TX or Houston, Texas), a 5 digit ZIP code (77002) or coordinates (29.7604, -95.3698). Each place is checked with OfferUp's own place search and geocoder; a city written differently from OfferUp's place search (St. Louis, MO where it writes St Louis, MO), a city without its state, or a place outside the 50 states and DC is answered with a free row that lists OfferUp's suggestions, and its searches are not read.

## `categories` (type: `array`):

OfferUp categories by id (5.1), by name (Cars & Trucks) or by full path (Vehicles > Cars & Trucks), from OfferUp's own list of 1,244 categories. A name several categories share (Accessories, Furniture) is answered with a free row that lists their ids and paths.

## `listingUrls` (type: `array`):

OfferUp listing links (https://offerup.com/item/detail/<listing id>) or listing ids. Each link is read with its details and delivered as given; the search filters below do not apply to links. A listing that no longer exists is a free row.

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

Distance around each place. OfferUp offers 5, 10, 20, 30 or 50 miles in most categories (30 when left empty) and 25, 80, 100, 200 or 5000 in Cars & Trucks (80 when left empty).

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

newest is OfferUp's recent first order (the default, and the only order a monitor or a search without keyword or category reads). best_match repeats listings after about 12 pages; the run counts the repeats and bills each listing once.

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

Whole dollars, up to 1,000,000 (OfferUp's own bound). A listing without a price (call for price) never passes a price filter. On a search without keyword or category the range is applied to the rows by this Actor.

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

Whole dollars, up to 1,000,000 (OfferUp's own bound). A listing without a price (call for price) never passes a price filter. On a search without keyword or category the range is applied to the rows by this Actor.

## `conditions` (type: `array`):

One or more of OfferUp's conditions. Leave empty for every condition. Needs a keyword or category (OfferUp's local feed takes no condition).

## `sellerType` (type: `string`):

OfferUp marks every search row as a vehicle dealer or not. dealer keeps vehicle dealers only; private keeps every other seller (private people, and shops such as furniture or appliance stores: with details on, sellerIsBusiness tells them apart). Listings left out are free.

## `vehicleMinYear` (type: `integer`):

Cars & Trucks only (categories 5.1 and its sub categories): the earliest model year.

## `vehicleMaxYear` (type: `integer`):

Cars & Trucks only: the latest model year.

## `vehicleMaxMileage` (type: `integer`):

Cars & Trucks only. OfferUp offers 25000, 50000, 75000, 100000, 125000, 150000, 175000 or 200000 miles.

## `includePromoted` (type: `boolean`):

OfferUp places a few promoted listings at the top of the first pages. They are real listings and are marked isPromoted; switch this off to leave them out (free).

## `onlyTitleMatches` (type: `boolean`):

OfferUp's search also returns related listings (a case for iphone, a loveseat for couch), more so in the newest first order. Every row says titleMatchesKeyword; switch this on to leave the others out (free). A title matches when every word of the keyword starts a word of the title, after styled letters are read as plain ones.

## `includeDetails` (type: `boolean`):

Read each delivered listing's detail and add it to the row: description, posted time, last edit, original price, condition, coordinates, category, all photos, seller id, join date, items sold, rating, verified and dealer flags, and for vehicles make, model, year, mileage, color, VIN and title status. Each such row is billed as Listing detail too.

## `includePrivateSellerDetails` (type: `boolean`):

Off by default. For a private seller, switch on to also get: the seller's name (sellerName) and phone number (sellerPhone) and the listing's exact coordinates (latitude, longitude) with details on, and the phone numbers and e-mail addresses the seller wrote into the title, the description and the other texts of the row, which are otherwise masked on a best effort basis (\[phone number removed], \[e-mail removed]; a contact written in an unusual way can stay). All of it is what OfferUp shows any visitor. Dealers' and business accounts' contact details are delivered either way; a row that cannot tell (no details read) counts as a private seller's. You are responsible for a lawful use of this personal data, GDPR and other privacy laws included.

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

The most listing rows a run delivers (and bills), over all searches and links. Default 100.

## `maxPagesPerSearch` (type: `integer`):

Results pages read per search, about 50 listings each (100 for a search without keyword or category). Default 10.

## `monitorName` (type: `string`):

Give a name (such as iphones-houston) to remember, across scheduled runs, every listing this monitor delivered: each run reads the newest Maximum pages per search pages of each search and delivers and bills only listings it has not delivered before. A monitor pays a small Results page fee for every results page it reads, so keep the pages small for a frequent monitor. One name belongs to one set of settings. Leave empty for a normal run.

## Actor input object example

```json
{
  "keywords": [
    "iphone"
  ],
  "locations": [
    "Houston, TX"
  ],
  "sort": "newest",
  "sellerType": "any",
  "includePromoted": true,
  "onlyTitleMatches": false,
  "includeDetails": false,
  "includePrivateSellerDetails": false,
  "maxItems": 20,
  "maxPagesPerSearch": 1
}
```

# Actor output Schema

## `items` (type: `string`):

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "keywords": [
        "iphone"
    ],
    "locations": [
        "Houston, TX"
    ],
    "maxItems": 20,
    "maxPagesPerSearch": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/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"],
    "locations": ["Houston, TX"],
    "maxItems": 20,
    "maxPagesPerSearch": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/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"
  ],
  "locations": [
    "Houston, TX"
  ],
  "maxItems": 20,
  "maxPagesPerSearch": 1
}' |
apify call automation_craft/offerup-scraper --silent --output-dataset

```

## MCP server setup

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