Reverb Music Gear and Sold Price Guide Scraper
Pricing
from $1.20 / 1,000 results
Reverb Music Gear and Sold Price Guide Scraper
Scrape reverb.com music gear: guitars, amps, synths, pedals, drums and pro audio. Search live listings by brand, category, condition, price, year, region and shipping, or paste links. Uniquely returns the sold Price Guide per gear model: median, low, high and quartile realised prices.
Pricing
from $1.20 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
0
Monthly active users
14 days ago
Last modified
Categories
Features
Share
Pull music gear from Reverb (reverb.com), the marketplace for new, used and vintage guitars, amps, synthesizers, pedals, drums and pro audio. Search live listings with the marketplace's own brand, category, condition, price, year, region, shipping and seller filters, or paste links and let the actor route them. Alongside every listing you also get the Price Guide: what that exact gear model has actually sold for, as a median, a low and high, quartiles, a breakdown per condition, the gap between asking and realised price, the individual recent sales, and a period by period history. Export the dataset as JSON, CSV or Excel, or pull it straight into your app through the API.
Why This Scraper?
- Realised sale prices, not just asking prices. An asking price tells you what a seller hopes for. This returns what buyers actually paid: median, low, high, 25th and 75th percentile, per condition, with the individual sales behind the numbers and their dates.
- A deal rating on every live listing. Each listing is positioned against its own model's sold history and labelled
below-market,at-marketorabove-market, with the exact percentage above or below the sold median. - Over 60 fields per listing including view and watcher counts, days on market, price drops, seller feedback and rating, seller location, per region shipping rates, return policy, and the canonical model id.
- Three modes, one actor. Keyword search across live listings, Price Guide lookup by gear model, and paste anything: item links, price guide links, product links, shop links, brand links, marketplace search links, or bare listing ids.
- Built for recurring monitoring. Incremental mode returns only what changed since the last run, so a daily watch on "1960s Stratocasters under $8,000" returns the new listings and the price drops instead of the same catalogue every day.
- Filters that actually narrow. Category and price are re-checked against each listing's own data after the search, because the marketplace's own filters can otherwise let off-category or out-of-window rows through.
Use Cases
- Gear buyers and collectors: check whether an asking price sits below, at, or above what the exact model has actually sold for before making an offer.
- Dealers and resellers: source stock across brands and categories, and price it against realised sale history instead of sticker prices.
- Vintage gear researchers: track price trends by condition, year and category over time using the period by period sale history.
- Marketplace monitoring tools: watch a saved search or a shop and get only new listings, price drops and Price Guide changes on a schedule.
- Price comparison and alert apps: feed live asking prices plus realised sold prices into your own app, bot or spreadsheet.
- Market analysts: build datasets of completed sales, ask to sold spreads and per condition pricing for a category of instruments.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
recordType | "listing" (also "priceGuide" in Price Guide mode) |
listingId | "12345678" |
title | "Sample Vintage-Style Solidbody Guitar" |
make / model / year / finish | "Sample Brand" / "Model X" / "1965" / "Sunburst" |
condition / conditionSlug | "Very Good" / "very-good" |
price / currency / priceDisplay | 1200.0 / "USD" / "$1,200" |
originalPrice / priceDropPercent | 1400.0 / 14 |
categories / rootCategory | ["Electric Guitars / Solid Body"] / "electric-guitars" |
state / inventory / offersEnabled / isAuction | "live" / 1 / true / false |
shopName / shopSlug / preferredSeller | "Sample Music Shop" / "sample-music-shop" / true |
sellerLocation / sellerCountryCode | "Springfield, United States" / "US" |
views / watchers / daysOnMarket | 240 / 12 / 30 (views and watchers need the item page read on) |
freeShipping / shippingRates | true / [{"regionCode": "US", "price": 0.0}] |
photo / photos / photoCount | image URL / list of image URLs / 4 |
url | link to the listing, model or price guide page |
publishedAt / scrapedAt | "2026-01-01T00:00:00Z" |
guideMedianPrice / priceVsGuidePercent / dealRating | 1350.0 / -11.11 / "below-market" (needs the sold Price Guide on) |
soldPriceMedian / soldPriceLow / soldPriceHigh | 1350.0 / 900.0 / 2200.0 (inside priceGuide on listings) |
byCondition / recentSales / priceHistory | per-condition breakdown / individual sales / monthly averages, as arrays |
changeType / firstSeenAt / lastSeenAt | "NEW" / "2026-01-01T00:00:00Z" / "2026-01-01T00:00:00Z" (incremental mode only) |
Price Guide mode records (recordType priceGuide) are a gear MODEL rather than one listing: productId, soldSalesTotal, soldSampleSize, soldPriceP25, soldPriceP75, soldPriceAverage, askPriceAverage, askToSoldDiscountPercent, firstSaleDate, lastSaleDate, usedListings, newListings, usedLowPrice, newLowPrice, productRating and productReviewCount, plus a nested reviews list (reviewId, title, body, rating, reviewer, date, verified, helpfulVotes when the source provides it). Reviews are read for Price Guide records only, never as separate dataset items; Max reviews per Price Guide record (maxReviewsPerProduct, default 20, at most 1000, 0 turns reviews off) bounds them. The Reviews view in the Console unwinds the list into one row per review.
Reviews add no charge of their own: a Price Guide record is billed exactly as before, whether it carries 0, 20 or 1000 reviews. The maxReviewsPerProduct limit only bounds how many are read and attached.
soldPriceMedian is the number to compare an asking price against, and soldPriceP25 / soldPriceP75 bracket the normal trading range that dealRating is judged from. A model with fewer than five recorded sales gets its live-market snapshot (usedListings, newListings, usedLowPrice, newLowPrice) but no dealRating, left empty rather than guessed on a thin sample. A sale recorded in a currency other than the reported one is excluded from the statistics rather than mixed in, and the count of excluded sales is reported as mixedCurrencySalesSkipped.
How to Use
- Pick a mode:
search(keyword search across live listings, with filters),price-guide(look up gear models and their realised sold-price statistics), orurl(paste links). - Add keywords or links, and for search and Price Guide modes narrow with the brand, category, condition, price, year, region and shipping filters (URL mode ignores them, the link carries its own).
- Turn on the sold Price Guide and, if you also want each listing's own item page (views, watchers, seller location, policies and videos), turn that on too. Each is a per-result surcharge, so a lean run can leave both off.
- Set Max results, click Start, then read the dataset as JSON, CSV or Excel, through the API, or via the MCP connector.
Search live listings with filters:
{"mode": "search","queries": ["Stratocaster"],"category": "electric-guitars","conditions": ["excellent", "very-good"],"minPrice": 500,"maxPrice": 3000,"includeSoldPriceGuide": true,"maxItems": 20}
Look up what gear models actually sell for:
{"mode": "price-guide","queries": ["Moog Subsequent 37", "Shure SM57"],"includeSoldPriceGuide": true,"maxItems": 20}
Paste links of any supported kind:
{"mode": "url","urls": ["https://reverb.com/item/00000001-sample-listing","https://reverb.com/price-guide/sample-brand-model","https://reverb.com/shop/sample-music-shop","https://reverb.com/marketplace?query=Gibson%20Les%20Paul&condition=used"],"includeSoldPriceGuide": true,"maxItems": 100}
Watch a search daily and get only the changes:
{"mode": "search","queries": ["1960s Stratocaster"],"maxPrice": 8000,"incrementalMode": true,"stateKey": "vintage-strat-watch","maxItems": 0}
URL mode: supported link shapes
In URL mode the urls field now ships with one working example per shape below (previously it was empty unless you typed links). Clear the list and paste your own to run only those.
| Shape | Example | What you get |
|---|---|---|
| Marketplace search (keyword + filters) | reverb.com/marketplace?query=Gibson%20Les%20Paul&condition=used | Matching listings |
| Paginated search | ...listings?query=stratocaster&page=2 | Listings from that page forward (partial scope: nothing is marked EXPIRED) |
| Brand page | reverb.com/brand/fender | Listings of that brand |
| Shop page | reverb.com/shop/<shop-slug> | Listings of that shop; an unknown shop logs a warning |
| Item | reverb.com/item/103425668 or 103425668 | One listing |
| Price Guide search | ...api/csps?query=stratocaster | Gear models with sold-price statistics |
| Price Guide product | reverb.com/price-guide/<slug> or ...comparison_shopping_pages/126164 | One gear model |
| Price Guide sales | ...comparison_shopping_pages/126164/transactions | The same model record with its sold history (the same target as the plain product link, so only one of the two is pre-filled) |
A link that is not one of these is reported and skipped.
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/reverb-scraper").call(run_input={"mode": "search","queries": ["Stratocaster"],"maxItems": 20,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item.get("price"), item.get("dealRating"))
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/reverb-scraper').call({mode: 'search',queries: ['Stratocaster'],maxItems: 20,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Filters that narrow twice
Category and price are applied both upstream (so the walk itself stays narrow) and again against each returned listing's own category and its own US dollar price, because the marketplace's own matching can otherwise let off-category or out-of-window rows through, sometimes a large share of a page. The walk for a keyword stops reading new pages once it has read enough candidate listings to fill that keyword's share of maxItems, and the re-check runs after that. So a heavily filtered run can return fewer rows than maxItems asks for even when later pages still hold matching listings. Raising maxItems makes the walk read further.
How Max results splits across keywords and links
In search and Price Guide modes each keyword gets its own share of maxItems, split evenly, so the first keyword of a multi-keyword run cannot silently use up the whole cap. A share a keyword does not fill (because it has fewer matches) is not handed on to the other keywords. In URL mode the pasted item and model links are read first, then each pasted search, shop or brand link in order takes whatever is left of maxItems, so an early search link can use up the rest of the cap on its own.
Results are read 50 at a time (one page), so the walk for one keyword can read up to a full page of candidates before trimming to that keyword's own share. A listing read past the share is already counted as seen for duplicate detection even though it was never returned. When two keywords in the same run overlap (close synonyms, or one a substring of the other), a later keyword skips those listings, so it can return fewer matches than it would alone, or none at all, and the run can finish below maxItems. Run overlapping keywords as separate runs if you need every match from each one.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted run: paste its run or dataset id and the actor skips everything already collected there, so you don't pay twice. - Incremental mode (
incrementalMode) is for running this same search again and again (for example daily) and getting only what changed. Each result is classifiedNEW,UPDATED(withchangedFields),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEARED, orEXPIRED(only after a run that scanned the whole tracked search, and only withemitExpired).stateKeynames or shares the stored state; leave it empty to let the actor derive one from the mode, keywords, links and filters. - What is compared. Every field of the record: asking price, currency, condition, listing state and inventory, title, description, seller, shipping, photos and the Price Guide statistics for Price Guide records. Never compared: the scrape time, days on market, the views, watchers and offer-count counters (they tick on their own), and the
reviewslist of a Price Guide record (a review read can come back short or be limited bymaxReviewsPerProduct, which would otherwise create anUPDATEDrow for data that did not change); all of these stay in every row. Photo links are compared by the image file, not by the CDN's per-link signature. Timestamps are compared as the instant they name (the source shows the same moment in a different time-zone offset from one fetch to the next), the order of the recent-sales list does not matter, and the sold statistics of a Price Guide record (averages, median, quartiles, the per-condition table) count as changed only when the model's total sale count or its latest sale date moved too, because the sampled sales at the edge of the window shift between fetches. - Ignore fields when detecting changes (
ignoreFieldsForChanges, incremental mode only) lists extra field names that must never create anUPDATEDrow, for examplephotos. A dotted name such asshippingRates.rateignores that key inside a nested field. Ignored fields still appear in the rows, and changing the list does not re-bill your saved baseline. - Price and availability only (
changeScope=priceAndStock) compares only the prices, currency, listing state, live flag and inventory and each shipping rate by region (shippingRates: amount, currency and whether it is flat or carrier-calculated; a region appearing or disappearing counts too) (for Price Guide records, the sold median and average, ask average, low prices and listing counts). Titles, descriptions, photos and seller details never create anUPDATEDrow. Default is all fields. - Compact update rows (
compactUpdates) makeUPDATEDandEXPIREDrows short: ids, link, title, current price and availability, pluspriceChangeswith the old and new value of each moved field andvariantChangeswith the old and new rate of each shipping-rate region (regionCode) that was added, removed or changed.NEWrows stay complete. A compact row carries no item-page or Price Guide data, so the detail-enrichment charge is not applied to it. - Expire after N missed scans (
expireAfterMissedScans, default 1) marks a resultEXPIREDonly after it was missing from that many complete scans in a row.EXPIREDmeans the listing was not found again; it does not prove it sold or was withdrawn, so use the state and inventory fields for availability. - Partial scans never expire anything. A link that starts at
?page=2or later, a run stopped by Max results, or a Resume run is an incomplete scan and never producesEXPIREDrows. - EXPIRED rows are not limited by Max results. They are computed from whatever is left in the tracked baseline once a complete scan proves it is gone, and Max results only governs the live collection in that same run. A state key tracking a large catalogue that mostly disappeared between runs (for example after narrowing the filters) can return far more EXPIRED rows in one run than Max results was set to. If you need a hard ceiling on a single run's total output, keep
emitExpiredoff, or use a narrower, more stable tracked search. - Incremental mode with a Max results cap counts unchanged listings while walking. The walk for a keyword stops reading new pages once it has read that keyword's share of
maxItemsin listings not already seen this run, whether or not they turn out to be unchanged. If the first page is all unchanged, the run can stop there and report nothing changed even though new listings sit on a later page. For scheduled monitoring, setmaxItemsto0(as in the example above), or at least sort bynewestso new listings come first. - Seeding incremental state from a resumed run is a one-off with a catch. Combining
resumeFromRunIdwithincrementalModeon a state key with no saved state records every result of the resumed run as already known, but without its details. The next incremental run therefore returns each of those results once asUPDATED(and bills it), with every field listed inchangedFields. From the run after that they are classified normally. - A run that the platform restarts part way through (for example when it moves the run to another server) picks up again at the keyword or link it was working on. That keyword or link starts from its first page again, so rows it had already returned can be returned (and billed) a second time, and the run's total can go over
maxItems. In incremental mode, rows returned before the restart for earlier keywords are not recorded in the saved state, so the next run reports them asNEWagain.
Send results into your apps (MCP connectors)
Optionally pipe results into Notion, Linear, Airtable or Apify via MCP connectors, using the Export to your apps (MCP connectors, optional) section of the input. Authorize a connector under Apify, Settings, API and Integrations, then select it here.
mcpConnectorsselects the connectors this run exports into.notionParentPageUrlis the Notion page under which one page per item is created. It is required for the Notion export and ignored by every other connector.maxNotifyListingscaps how many items are written to each connector.
Each connector receives a condensed, human readable summary per item: a title plus the key fields flattened to plain text, with nested objects collapsed to their main value and long lists trimmed. The complete record, including the whole priceGuide block, always stays in the Apify dataset. The export is a side channel: it never changes the dataset output, and a connector error is logged as a warning while the run still succeeds.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search, price-guide, or url. |
queries | array | ["Fender Stratocaster"] | Keywords, read in search and Price Guide modes. Each is searched separately and gets its own share of the item cap. |
urls | array | sample | Reverb links or bare listing ids, read in URL mode. Filters below are ignored in this mode. |
make | string | (none) | Brand, matched against the marketplace's own brand list (capitalisation does not matter); a brand that does not exist stops the run with a message instead of searching everything. Applies to search and Price Guide modes. |
category | string | (any) | A top-level category (such as electric-guitars) or the name of a sub-category such as Solid Body or Electric Guitars / Solid Body, matched against the marketplace's own category list; a name shared by several categories (for example 12-String) needs its full path. A category that does not exist stops the run with a message instead of searching everything. Applies to search and Price Guide modes. |
minYear | integer | (none) | Earliest year. Applies to search and Price Guide modes. |
maxYear | integer | (none) | Latest year. Applies to search and Price Guide modes. |
conditions | array | [] | One or more of new, b-stock, used, mint, excellent, very-good, good, fair, poor, non-functioning. Search mode only. |
minPrice | integer | (none) | Minimum price in US dollars. Search mode only. |
maxPrice | integer | (none) | Maximum price in US dollars. Search mode only. |
itemRegion | string | (any) | Seller country. Search mode only. |
shipsTo | string | (anywhere) | Country the seller ships to. Search mode only. |
shopSlug | string | (none) | One seller, given as the handle in the shop address. Search mode only. |
handmadeOnly | boolean | false | Handmade or custom built gear only. Search mode only. |
freeShippingOnly | boolean | false | Only listings that ship free. Search mode only. |
preferredSellersOnly | boolean | false | Preferred sellers only. Search mode only. |
sortBy | string | relevance | relevance, price-asc, price-desc, or newest. Search mode only. |
includeSoldPriceGuide | boolean | true | Attach the realised sale statistics, and score each live listing against them. |
fetchDetails | boolean | false | Read each listing's own item page for views, watchers, seller location, policies and videos. |
maxReviewsPerProduct | integer | 20 | Price Guide records: how many owner reviews to attach as a nested reviews list, newest first. 0 turns reviews off, at most 1000. Reviews add no charge. In incremental mode the reviews list never decides UPDATED. |
maxItems | integer | 20 | Maximum number of results returned across the whole run. 0 for unlimited. |
maxPages | integer | 0 | Maximum result pages walked per keyword or link, at 50 results a page. 0 for no page limit. |
resumeFromRunId | string | (none) | Continue one interrupted run without returning, or charging for, results already collected there. |
incrementalMode | boolean | false | Turn this on for daily or recurring monitoring: return only what changed since the last run of this search. |
changeScope | string | all | Incremental mode: priceAndStock returns an UPDATED row only for price or availability changes. |
compactUpdates | boolean | false | Incremental mode: short UPDATED and EXPIRED rows with priceChanges and variantChanges. |
expireAfterMissedScans | integer | 1 | Incremental mode: mark EXPIRED only after this many consecutive complete scans missed the result. |
ignoreFieldsForChanges | array | [] | Incremental mode: field names (or dotted paths) that never create an UPDATED row. |
stateKey | string | (none) | Name a monitoring campaign, or share state across differently configured runs. Derived automatically when empty. |
emitUnchanged | boolean | false | Also return (and bill) results that have not changed since the last run. |
emitExpired | boolean | false | Also return (and bill) results that were present before and are no longer found. |
proxy | object | Apify Proxy | Connection settings. Leave the default selected unless a run reports refused requests. |
mcpConnectors | array | (none) | Optional: send a summary of each result to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which item pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. Does not affect the dataset. |
searchQueries | array | (none) | Hidden alias of queries. |
condition | string | (none) | Hidden alias of conditions (a single value). |
maxListings | integer | (none) | Hidden alias of maxItems. |
scrapeDetails | boolean | (none) | Hidden alias of fetchDetails. |
proxyConfiguration | object | (none) | Hidden alias of proxy. |
Input aliases
Inputs written for other Reverb scrapers keep working. These hidden aliases are accepted and map onto the fields above: searchQueries (Search queries), condition (one value for Conditions), maxListings (Max items), scrapeDetails (Fetch details) and proxyConfiguration (Proxy). When both the alias and the main field are given, the main field wins, unless it is still at its default value, in which case the alias value is used.
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"recordType": "listing","listingId": "00000001","sku": "REF-0001","slug": "sample-brand-model-1965-sunburst","url": "https://reverb.com/item/00000001-sample-brand-model-1965-sunburst","comparisonShoppingPageId": "000000","title": "Sample Brand Model 1965 Sunburst","make": "Sample Brand","brandSlug": "sample-brand","model": "Model X","year": "1965","finish": "Sunburst","rootCategory": "electric-guitars","categories": ["Electric Guitars / Solid Body"],"condition": "Very Good","conditionSlug": "very-good","price": 1200.0,"currency": "USD","priceDisplay": "$1,200","originalPrice": 1400.0,"priceDropPercent": 14,"state": "live","inventory": 1,"offersEnabled": true,"offerCount": 0,"isAuction": false,"freeShipping": true,"freeExpeditedShipping": false,"shippingRates": [{ "regionCode": "US", "price": 0.0, "currency": "USD" }],"shopName": "Sample Music Shop","shopSlug": "sample-music-shop","preferredSeller": true,"sellerFeedbackCount": 120,"sellerRatingPercentage": 100.0,"sellerLocation": "Springfield, United States","sellerCountryCode": "US","views": 240,"watchers": 12,"daysOnMarket": 30,"publishedAt": "2026-01-01T00:00:00Z","scrapedAt": "2026-01-01T00:00:00Z","guideMedianPrice": 1350.0,"priceVsGuidePercent": -11.11,"dealRating": "below-market","priceGuide": {"soldSalesTotal": 140,"soldSampleSize": 60,"currency": "USD","soldPriceLow": 900.0,"soldPriceP25": 1100.0,"soldPriceMedian": 1350.0,"soldPriceP75": 1600.0,"soldPriceHigh": 2200.0,"soldPriceAverage": 1380.0,"askPriceAverage": 1490.0,"askToSoldDiscountPercent": 7.4,"firstSaleDate": "2024-03-01","lastSaleDate": "2026-01-01","byCondition": [{ "condition": "Excellent", "salesCount": 22, "lowPrice": 1200.0, "medianPrice": 1450.0, "highPrice": 1700.0 }],"recentSales": [{ "date": "2026-01-01", "condition": "Excellent", "askPrice": 1500.0, "soldPrice": 1425.0, "currency": "USD" }],"priceHistory": [{ "periodStart": "2025-12-01", "averageAskPrice": 1490.0, "averageSoldPrice": 1380.0 }],"liveMarket": { "usedListings": 34, "newListings": 6, "usedLowPrice": 900.0, "newLowPrice": 1899.0 },"mixedCurrencySalesSkipped": 0}}
Plan Requirement
Reverb's public data interface answers normal requests, and the actor reads that interface rather than the website pages. The default Apify Proxy connection is tried first. Whether a free plan's default connection is enough has not been measured for this release, so no "works with no action" promise is made here. What the actor does, as it now reads in the code:
- If the residential connection is refused for the account (Apify free plans do not include residential proxies), the run logs: "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable." and then "Served over the backup connection (the default connection was unavailable)." when a request is served that way.
- If the account has no proxy access at all, the run stops with: "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required". If you entered your own proxy URLs, check their credentials.
- If residential is unavailable and the backup connection could not load the pages, the run stops with: "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Reverb pages."
- If the requests simply fail, the run stops with: "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search." Run it again later.
Residential traffic is billed by your Apify plan, so keep the default connection selected unless a run reports refused requests. You can also supply your own proxy URLs.
FAQ
How much does it cost?
You pay per result returned, with the sold Price Guide and each listing's own item page billed only when you switch them on, once per result they actually add data to. The Pricing tab shows the current rates. Use Max results to cap the cost of any run.
Is it legal to scrape Reverb?
This actor collects only publicly available marketplace data. You are responsible for how you use it: follow Reverb's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing content, photos and seller information may carry rights belonging to the seller or the marketplace.
Can I get only new or changed listings on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared results by default, and unchanged ones are not billed unless you turn emitUnchanged on. Leave Max results at 0 for monitoring runs so the walk is not cut short by unchanged listings.
Why did I get fewer results than Max results asked for?
A few reasons, all described under How to Use above. The category and price filters are re-checked against each listing's own data after the walk has already stopped reading pages, so a heavily filtered run can return fewer than maxItems even when later pages hold more matches. Each keyword only gets its own share of the cap, and an unused share is not passed on. Keywords that overlap in one run can take matches away from each other. In incremental mode, unchanged listings are suppressed but still count toward the walk's stop point. Raise maxItems, broaden the filters, or run overlapping keywords separately.
Why did incremental mode return more EXPIRED rows than Max results?
emitExpired rows come from comparing the whole tracked baseline against what a complete scan found this run, and that comparison is not capped by maxItems, only the live collection is. A state key watching a large catalogue that shrank a lot since the last run (for example after narrowing the filters) can return many more EXPIRED rows in one run than maxItems was set to. Keep emitExpired off if you need a hard ceiling on a single run's output.
Why did my run fail instead of returning an empty dataset?
If every request was refused, the run stops with a clear message so "nothing matched" is never confused with "nothing could be read". Run it again in a few minutes, or switch the connection if it keeps happening.
What is the difference between Resume and Incremental mode?
Resume (resumeFromRunId) continues one specific interrupted run using its run or dataset id. Incremental mode remembers state itself, keyed on the search, and is for running the same search again and again on a schedule. They can be combined once, to seed a brand-new monitoring campaign's baseline from an existing run, but not against a state key that already has saved state. After such a seed, the next incremental run returns every seeded result once as UPDATED (billed), because the seed records which results exist but not their details.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
๐ Want more e-commerce data?
Pair this actor with these related scrapers from the same team:
| ๐ Depop Scraper Scrape Depop search results, listings, shops, and reviews to JSON, CSV, or Excel. Extract... | โฝ Whatnot Scraper Scrape Whatnot live and upcoming shows, queued items and lots, and seller profiles... |
| ๐ท๏ธ Vinted.fr Scrape Vinted.fr, France's C2C second-hand fashion marketplace: search with... | ๐ท๏ธ Chrono24 Scraper Scrape Chrono24 luxury watch listings by keyword, filters or URL. Extract 50+ fields... |
| ๐ OfferUp Scraper Scrape OfferUp listings by keyword, location and radius. Returns 40+ fields per item... | ๐ Mercari Japan Scraper Scrape Mercari Japan listings, sellers and reviews at scale. Extract names, prices... |
๐ Browse all abotapi scrapers
๐ฌ Support
- ๐ Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- ๐ ๏ธ Need another site, extra fields or a private build? Email contact@abotapi.com.
- โญ Enjoying it? A quick review on the actor page helps other users find it.