OfferUp Scraper $1๐ฐ Listings, Sellers, Geo & Categories
Pricing
from $1.00 / 1,000 listing results
OfferUp Scraper $1๐ฐ Listings, Sellers, Geo & Categories
Scrape OfferUp listings by keyword, location and radius. Returns 40+ fields per item: price, condition, GPS, full photo set, category tree and rich seller profiles (rating, items sold, join date, verification). Search and URL modes, 5 sort orders, price and condition filters.
Pricing
from $1.00 / 1,000 listing results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
12 days ago
Last modified
Categories
Share
OfferUp Scraper
Scrape public listings from OfferUp, the largest mobile-first local marketplace in the United States. Give it a keyword and a location, or paste OfferUp URLs, and get clean structured JSON: prices, conditions, photos, GPS coordinates, category trees and full seller profiles. Search and URL modes, five sort orders, and price and condition filters are all built in.
Why this scraper
- Returns 40+ fields per listing, far more than typical OfferUp scrapers (geo coordinates, full photo set, category L1/L2/L3, and a complete seller profile).
- Two modes: keyword search with filters, or paste OfferUp search and item URLs directly.
- Five native sort orders: best match, newest, closest, price low to high, price high to low.
- Price range and multi-condition filtering, applied at the source.
- Location by city name, ZIP code, or raw coordinates, with adjustable radius.
- Rich seller data: rating, review count, items sold, join date, response time and verification status.
- Fast HTTP extraction with automatic connection rotation and retry.
- Walks the whole catalogue by default.
maxPagesdefaults to0(unlimited): the run walks every result page per query/URL, stopping on its own once OfferUp's own last page is reached or a page repeats listings already seen this walk.maxItemsis the sole cap on volume. - Resumable runs. Set
resumeFromRunIdto a previous run or dataset id to collect only listings that run doesn't already have (a delta). Long runs also checkpoint their progress, so a platform migration or a Resurrect of a failed run picks up where it left off instead of starting over.
Data you get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
| listingId | 00000000-0000-0000-0000-000000000000 |
| title | Sample Listing Title |
| price | 799 |
| isFirmPrice | false |
| conditionText | Used |
| locationName | Miami, FL |
| url | https://offerup.com/item/detail/00000000-0000-0000-0000-000000000000 |
| imageUrl | https://images.offerup.com/000000000-254x250.jpg |
| flags | ["LOCAL_PICKUP"] |
| latitude | 25.0000 |
| longitude | -80.0000 |
| distanceMiles | 4.9 |
| categoryL1Name | Electronics & Media |
| categoryL2Name | Cell phones & Accessories |
| description | Full item description appears here when Fetch full details is on. |
| originalPrice | 899 |
| isOnSpecial | true |
| savingsAmount | 100 |
| discountPercent | 11 |
| photos | [{ "uuid": "0000", "url": "https://images.offerup.com/000-1440x1920.jpg" }] |
| postDate | 2026-01-01T00:00:00.000Z |
| localPickupEnabled | true |
| shippingEnabled | false |
| sellerName | Jane Doe |
| sellerRating | 5 |
| sellerReviewCount | 89 |
| sellerItemsSold | 564 |
| sellerDateJoined | 2016-01-01T00:00:00Z |
| sellerResponseTime | Responds in a few minutes |
| sellerIsTruYou | true |
How to use
Search a city with filters:
{"mode": "search","searchQueries": ["iphone 14"],"location": "Miami, FL","radiusMiles": 30,"priceMin": 200,"priceMax": 600,"condition": ["USED", "REFURBISHED"],"sortBy": "-price","maxItems": 50,"proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "US" }}
Search multiple keywords with full details:
{"mode": "search","searchQueries": ["mountain bike", "road bike"],"location": "33101","fetchDetails": true,"maxItems": 40}
Search for genuine price drops only (detail fetch is auto-enabled for this):
{"mode": "search","searchQueries": ["couch"],"location": "Miami, FL","priceDropOnly": true,"maxItems": 40}
Paste OfferUp URLs (search pages and item pages):
{"mode": "url","urls": ["https://offerup.com/search?q=sofa&radius=20","https://offerup.com/item/detail/00000000-0000-0000-0000-000000000000"],"fetchDetails": true}
Resuming a previous run (only the listings you don't already have):
{"mode": "search","searchQueries": ["iphone 14"],"location": "Miami, FL","maxItems": 0,"resumeFromRunId": "<a previous run id or dataset id from this account>"}
Recurring monitoring of the same search (Incremental mode) โ schedule this input daily/weekly and only NEW/UPDATED/REAPPEARED/EXPIRED listings are worth looking at:
{"mode": "search","searchQueries": ["iphone 14"],"location": "Miami, FL","incrementalMode": true}
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| mode | string | search | search (keyword + location) or url (paste OfferUp URLs). |
| searchQueries | array | ["iphone"] | Keywords to search (search mode). |
| location | string | Miami, FL | City, ZIP, or lat,lon. Empty searches near the connection location. |
| radiusMiles | integer | 50 | Radius in miles around the location (1 to 500). |
| priceMin / priceMax | integer | none | Price range in USD. |
| condition | array | none | One or more of NEW, OPEN_BOX, REFURBISHED, USED, BROKEN, OTHER. |
| priceDropOnly | boolean | false | Keep only listings with a genuine seller price drop (search mode). Price-drop data lives on the listing detail page, not the search results, so turning this on auto-enables fetchDetails for the run (and its per-item surcharge) even if left off. |
| sortBy | string | best_match | best_match, -posted, distance, price, -price. |
| urls | array | none | OfferUp search or item URLs (url mode). |
| fetchDetails | boolean | false | Visit each listing for description, GPS, photos, category and seller profile. Always on when priceDropOnly is set. |
| maxItems | integer | 20 | The single run cap. Set 0 for unlimited. |
| maxPages | integer | 0 | Optional safety limit on result pages walked per query. Leave at 0 (default) to walk the whole catalogue: the run stops at Max items, OfferUp's own last page, or a repeat-page guard, not an artificial page cap. |
| resumeFromRunId | string | (empty) | ID of a previous run (or dataset) of this actor. Listings already in that dataset are skipped, so this run returns only NEW listings (a delta). |
| incrementalMode | boolean | false | For a search you run on a schedule: remembers this search's own listings between runs and tags each row's changeType as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED. State is kept automatically โ unlike resumeFromRunId, you never paste a run/dataset id. Don't combine with resumeFromRunId once a baseline already exists for the search. |
| stateKey | string | (empty) | Optional label naming the tracked baseline for Incremental mode. Leave empty to auto-derive one from your search/URLs and filters. |
| emitUnchanged | boolean | false | Incremental mode: also return and bill listings with no change since the last run, instead of only NEW/UPDATED/REAPPEARED/EXPIRED. |
| emitExpired | boolean | false | Incremental mode: also return and bill a row for each previously-tracked listing no longer found โ only once a run completes a full scan (never on Resume, a Max items cap, or an error-stopped scan). |
| proxy | object | Residential US | Proxy configuration. |
maxItems is the single cap. maxPages is only an optional safety bound (0 = unlimited) and does not limit below maxItems. Progress is checkpointed automatically, so a run interrupted by a platform migration or restarted via Resurrect picks up where it left off instead of re-collecting and re-charging already-pushed listings.
Incremental mode: what counts as a change
Incremental mode compares every field in the output row against your last run, with five exceptions that are ignored for change detection because they drift on their own โ independent of anything about the listing itself โ and would otherwise make almost every listing look "UPDATED" on every run: discussionCount (a live comment/question counter), sellerLastActive / sellerResponseTime (rolling seller-activity stats), and distanceMiles / isLocal (computed relative to where the scrape ran from โ a residential proxy's exit location moves between runs, so these can change even though the listing itself did not). These five fields are still returned with their real, current value in every row; they are just not compared when deciding NEW/UPDATED/UNCHANGED/REAPPEARED.
Output example
Sample shape: values are illustrative placeholders, not from a live listing.
{"listingId": "00000000-0000-0000-0000-000000000000","url": "https://offerup.com/item/detail/00000000-0000-0000-0000-000000000000","title": "Sample Listing Title","price": 799,"isFirmPrice": false,"conditionText": "Used","conditionCode": 40,"locationName": "Miami, FL","latitude": 25.0000,"longitude": -80.0000,"distanceMiles": 4.9,"flags": ["LOCAL_PICKUP"],"categoryL1Name": "Electronics & Media","categoryL2Name": "Cell phones & Accessories","description": "Full item description appears here when Fetch full details is on.","originalPrice": 899,"isOnSpecial": true,"savingsAmount": 100,"discountPercent": 11,"photos": [{ "uuid": "0000", "url": "https://images.offerup.com/000-1440x1920.jpg", "width": 1440, "height": 1920 }],"photoCount": 7,"postDate": "2026-01-01T00:00:00.000Z","localPickupEnabled": true,"shippingEnabled": false,"sellerName": "Jane Doe","sellerRating": 5,"sellerReviewCount": 89,"sellerItemsSold": 564,"sellerDateJoined": "2016-01-01T00:00:00Z","sellerResponseTime": "Responds in a few minutes","sellerIsTruYou": true}
With incrementalMode on, every row also carries changeType (NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED), changedFields, firstSeenAt and lastSeenAt.
Send results into your apps (MCP connectors)
Optionally pipe results into the apps you already use, through Model Context Protocol (MCP) connectors. Authorize a connector under Apify, Settings, API and Integrations, then select it in the mcpConnectors input. For Notion, also set notionParentPageUrl. Each item is written as a condensed, human-readable summary (title plus key fields), not the full JSON; the complete record always stays in the Apify dataset. Leave the field empty to skip; it never changes the dataset output.
Plan requirement
OfferUp only serves connections from the United States and blocks non-US and datacenter connections. Use Apify Residential proxy with country US (Starter plan or higher includes Residential proxy access). On a free plan or a non-residential connection, runs will usually return zero items and a notice explaining the upgrade path.