OfferUp Listings Scraper — Keyword, ZIP & Item URLs
Pricing
from $5.00 / 1,000 listing founds
OfferUp Listings Scraper — Keyword, ZIP & Item URLs
Scrape public OfferUp US listings by keyword+ZIP, search URL, or item URL. Title, price, location, images; optional seller enrich. MCP-ready.
Pricing
from $5.00 / 1,000 listing founds
Rating
0.0
(0)
Developer
Khadin Akbar
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
5 days ago
Last modified
Categories
Share
Use this Apify Actor to scrape public OfferUp US marketplace listings by keyword + ZIP, OfferUp search URL, or item URL/ID. Resellers, deal hunters, and lead-gen agents get a structured dataset of listing rows with title, price, location, images, and optional seller/description enrichment — cookieless, no login, MCP-ready.
Use this Actor when you need US local classified inventory from OfferUp into JSON. When the next workflow is Facebook Marketplace or another country, continue with a sibling marketplace Actor instead.
Best fit for this Actor
- You need public OfferUp US listings near a ZIP (keyword search, search URL, or direct item URL/ID).
- You want flat fields (
title,price,locationName,url,imageUrl) plus optional seller/description enrichment. - You want one MCP-ready tool with terminal
OUTPUT.outcomeand Pay per event billing. - For Facebook Marketplace, Craigslist-only workflows, or private OfferUp chat, route to a different tool.
Use case: Seattle phone sourcing sheet
A reseller preparing a weekend buy list runs this Actor with searchQueries: ["iphone"], zipCode: "98101", and maxItems: 30. Each row has title, price, locationName, and url. They sort by price, open the best five OfferUp item pages, then turn on fetchDetails for a shortlist of three to pull description and public seller rating before driving out.
Quick start input
{"searchQueries": ["iphone"],"zipCode": "98101","radiusMiles": 30,"maxItems": 3,"fetchDetails": false,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"],"apifyProxyCountry": "US"}}
Also supports searchUrls, listingUrls / listingIds, price/condition filters, and sort. Prefill keeps quality tests at three listings.
What data you receive
One dataset row per unique public listing.
{"listingId": "3f39a8bc-cf5b-32ce-a775-a8998113db81","url": "https://offerup.com/item/detail/3f39a8bc-cf5b-32ce-a775-a8998113db81","title": "Example listing","price": 200,"formattedPrice": "$200","locationName": "Bremerton, WA","imageUrl": "https://images.offerup.com/...","flags": ["LOCAL_PICKUP"],"sourceQuery": "iphone","sourceZip": "98101","enriched": false,"scrapedAt": "2026-09-17T12:00:00.000Z"}
| Field | Description |
|---|---|
| title, price, condition | Listing card basics |
| locationName, url, imageUrl | Where and how to open it |
| flags | e.g. LOCAL_PICKUP |
| description, photos, seller* | When fetchDetails or direct listing URLs |
| categoryL1/L2, shipping flags | Enriched only |
Pricing
Pay per event plus platform usage (isPPEPlatformUsagePaidByUser: true). Open the live Pricing tab in Apify Console for the current source of truth.
| Event | When | Price |
|---|---|---|
apify-actor-start | Every run | $0.00005 |
listing-found | Each accepted search-card row | $0.005 |
listing-enriched | Each accepted detail/enrich row | $0.012 |
A 3-listing search without enrich is about $0.01505 in events plus Residential proxy/compute. Invalid input and valid-empty searches leave listing events unbilled.
How it works
- Primary path: OfferUp public GraphQL (
GetModularFeed/ listing detail). Apify Residential US is required for OfferUp geo. - If Cloudflare/geo blocks HTTP, the Actor attempts a Playwright intercept fallback when available.
- Each accepted row is charged then pushed (
Actor.charge→pushData). - Terminal
OUTPUT/RUN_SUMMARYuse COMPLETE, PARTIAL, VALID_EMPTY, INVALID_INPUT, UPSTREAM_FAILED, or CONFIG_ERROR.
Honest contract and best results
- Public US listings only. No OfferUp account, DMs, or private seller contact data.
- Empty search results →
VALID_EMPTY(succeeded, zero listing charges). - Total block with zero rows →
UPSTREAM_FAILED(honest upstream outage). - Keep
maxItemssmall while testing; raise it only after a ZIP+keyword returns useful cards. - Prefer keyword + 5-digit ZIP; paste
searchUrlswhen you already have OfferUp filters in the browser. - Leave
fetchDetailsoff for discovery; turn it on for shortlists that need description and public seller fields. - Always pin
apifyProxyCountry: "US"— non-US exits often return Geolocation Unavailable.
Why agents choose this Actor
- One tool for keyword+ZIP, search URL, and item URL/ID.
- Predictable PPE with usage pass-through and a hard
maxItemsceiling. - Flat fields stay inside a small token budget for MCP clients.
- Terminal
OUTPUT.outcomemakes empty, upstream-outage, and invalid-input states machine-readable.
Agent checklist
- Supply
searchQueries+zipCode, or OfferUpsearchUrls/listingUrls/listingIds. - Cap
maxItemsto the budget you can spend at$0.005(or$0.012when enriched). - Keep Residential US in
proxyConfiguration. - After the run, read
OUTPUT.outcome, then the dataset. - Zero rows with
VALID_EMPTYmeans the query matched nothing public — change keyword or ZIP. - When
OUTPUT.outcomeisUPSTREAM_FAILED, retry once with a fresh Residential session before escalating.
Use through the API
curl "https://api.apify.com/v2/acts/khadinakbar~offerup-listings-scraper/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"searchQueries": ["iphone"],"zipCode": "98101","maxItems": 3,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"],"apifyProxyCountry": "US"}}'
When the Actor completes, read dataset items from the default dataset and the OUTPUT record from the default key-value store.
Use with AI agents through Apify MCP
Scrape OfferUp US listings for "iphone" near ZIP 98101. Return up to 10 rows with title, price, location, and URL. Keep Residential US. Stay on public listing fields only.
Point the MCP client at https://mcp.apify.com?tools=khadinakbar/offerup-listings-scraper, call khadinakbar/offerup-listings-scraper, then read the dataset and OUTPUT.outcome.
Builder's note
I built this Actor on OfferUp's public GraphQL after I found that GetModularFeed over Apify Residential US returns real cards for ZIP-centered searches. In my testing, non-US exits surface Geolocation Unavailable, so the Actor defaults to Residential US and finishes UPSTREAM_FAILED when every route is unavailable rather than inventing listings. My goal is truthful billing: dataset views stay view-only so detail enrich paths keep optional seller fields without schema crashes.
Connect the workflow
When the next market is US auction comps, continue with eBay All-in-One Scraper.
For handmade listing research after OfferUp discovery, feed titles into Etsy All-in-One Scraper.
When the SKU is a car and you need US vehicle listings after OfferUp discovery, start with Autotrader Scraper.
FAQ and responsible use
Is this affiliated with OfferUp? OfferUp is a trademark of its owner. This independent Actor is not affiliated with, associated with, or endorsed by OfferUp, Inc.
Is scraping allowed? You are responsible for complying with OfferUp’s Terms of Service and applicable laws (including privacy rules). Use only for legitimate purposes on publicly available data.
Why was my run empty? A valid keyword with zero public matches finishes SUCCEEDED / VALID_EMPTY. Missing ZIP or empty input finishes INVALID_INPUT. When every search route is unavailable the outcome is UPSTREAM_FAILED.
Does it return emails or phones? No. Public listing and seller-display fields only.
Open the Actor Issues tab for bugs. This Actor is independent research tooling, not legal, investment, or sourcing advice.