# Reverb Listings Scraper (`axiomworks/reverb-listings-scraper`) Actor

Retrieve public Reverb listings with listing titles, condition, make, model, seller, shipping, and state. The scraper accepts searches, shop URLs, and individual item URLs, and can request the public detail endpoint for location, seller feedback, views, watchers, and other available fields.

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

## Pricing

from $2.98 / 1,000 results

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

**Returns:** one row per Reverb listing with id, title, price, condition, make, model, sellerName, and sourceUrl.
**Input:** `{"searchTerms":["boss ds-1"],"condition":"used","maxItems":20}`
**Best for:** used gear research, listing monitoring, and comparing asking prices across shops.

```json
{"id": "101782260", "title": "Keeley Boss DS-1 Distortion with Ultra and Seeing Eye Mods 2010s - Orange", "price": 111.91, "currency": "USD", "condition": "Good", "make": "Keeley", "model": "Boss DS-1 Distortion with Ultra and Seeing Eye Mods", "sellerName": "Sam's Gear Locker", "sourceUrl": "https://reverb.com/item/101782260-keeley-boss-ds-1-distortion-with-ultra-and-seeing-eye-mods-2010s-orange"}
```

### What does Reverb Listings Scraper do?

Reverb Listings Scraper reads public gear listings through the Reverb listings API and returns a structured dataset. Search by words, paste a Reverb marketplace or category URL, collect listings from a shop, or fetch a single item by URL. The Actor can follow result pages, remove repeated listing IDs, and stop at the total item limit you choose. It reads public listing data without a Reverb login. This tool is independently operated and is not affiliated with Reverb.

A typical search begins with `searchTerms`, for example a pedal name or a guitar model. You can add filters for condition, make, product type, category, price range, year range, item location, shipping destination, listing status, and sort order. The output contains the listing page URL so you can inspect the current page yourself. It also includes the API values the Actor used for price, condition, shipping, seller, and listing state. For sold listings, the price is the final listing price exposed by the API; it is not a separately verified accepted-offer or transaction amount.

Search results supply most fields. With `includeDetails` enabled, the Actor requests each matching listing's public detail endpoint to add location, country code, seller feedback, views, watchers, offer count, and sold-as-is status when those fields exist. Turn details off when you need the search-page fields and want a faster run. The detail fields remain present as `null` when details are disabled or unavailable.

### What data can you get?

Each row represents one unique listing ID. Values originate in the Reverb listings API. Nullable fields reflect missing information in the public response rather than a guessed value. Seller-entered fields such as make, model, year, and finish can vary in wording and completeness.

| Field | Meaning |
| --- | --- |
| `id` | Stable Reverb listing ID as text. |
| `sourceUrl` | Public item page URL associated with the record. |
| `title` | Seller's listing title. |
| `price`, `currency`, `priceDisplay` | Numeric listing price, its currency code, and display text. |
| `condition`, `conditionSlug`, `state` | Displayed condition, condition slug, and listing state. |
| `make`, `model`, `year`, `finish` | Seller-entered gear descriptors. |
| `yearFrom`, `yearTo` | Numeric years parsed from `year` (`2010s` gives 2010 and 2019; `1994 - Present` gives 1994 and null). |
| `category`, `categories` | Primary and all category names returned for the listing. |
| `offersEnabled`, `auction`, `inventory` | Offer availability, auction flag, and inventory count. |
| `shippingPrice`, `shippingRegion`, `shippingRates` | Selected shipping rate, its region, and all public rates. |
| `freeExpeditedShipping`, `localPickup` | Shipping and pickup flags. |
| `sellerName`, `sellerSlug`, `sellerUrl`, `preferredSeller` | Public shop identity and preferred-seller flag. |
| `originalPrice`, `priceDropPercent` | Original asking price and published price drop percentage, or null. |
| `photoUrls` | Full image URLs from the listing photos; no image downloads. |
| `imageUrl`, `photoCount` | Main image URL and photo count. |
| `videoUrls` | Video links on the listing; `null` when details are off. |
| `handmade`, `usOutlet` | Handmade flag (details only) and US outlet flag. |
| `returnPolicy`, `shippingPolicy` | Seller policy text; `null` when details are off. |
| `description`, `publishedAt`, `createdAt`, `sku` | Plain-text description, timestamps, and optional seller SKU. |
| `location`, `countryCode` | Detail endpoint location and country code. |
| `sellerRating`, `sellerFeedbackCount` | Detail endpoint rating fraction and feedback count. |
| `views`, `watchers`, `offerCount`, `soldAsIs` | Detail endpoint engagement and listing flags. |
| `searchTerm`, `scrapedAt` | Source search or URL and extraction timestamp. |

The `shippingPrice` field chooses the continental United States rate when one is present; otherwise it uses the first returned rate. It can be `null` for a listing without a fixed public rate. `shippingRates` preserves the region and rate information used for comparison. The Actor outputs `imageUrl` as a URL string and does not download image files.

The price reduction fields come directly from Reverb: `originalPrice` is the published original amount, while `priceDropPercent` is the published percentage, including Reverb’s rounding. Neither field verifies an accepted offer. They remain null when Reverb does not publish a reduction. `photoUrls` preserves the available full photo links in source order and uses a large crop link if a full link is absent. These fields are collected from the existing responses and do not trigger additional requests.

### How to use

Open the Actor input form and enter one or more search terms. Set `maxItems` to the number of unique records you need. Add filters only when they apply to your research. Run the Actor, then open the dataset's overview table or download JSON. Each item has its public item URL for verification. The `RUN_SUMMARY` key-value record lists the inputs, each source's API URL, the reported total, pushed count, and any source errors.

You can also paste a marketplace search URL as a start URL. The Actor copies its query parameters into the public listings API request, including filters carried in the URL. An explicit filter input is added only if the URL does not already set the same parameter. This makes a shared marketplace link a reproducible starting point while preserving filters already encoded in that link.

For a single public item, use its `/item/{id}-{slug}` URL. The Actor fetches that item through the API and returns one record if it exists. A missing item ID yields no dataset rows and a warning. Shop URLs use the public shop slug as a listing filter. Search and URL sources share the same overall `maxItems` cap; duplicate listing IDs are returned once within a run.

The Actor sizes API pages to the remaining item budget (up to 50) and follows next-page links until the cap or exhaustion. Two concurrent detail requests feed ordered output; a spending-limit stop can leave one unused request. RUN_SUMMARY records requestCount and responseBytes. Requests retain spacing and backoff. Enable Apify Proxy if blocked. An unmatched term returns zero items with a status message and run summary.

### Input

| Input | Use |
| --- | --- |
| `searchTerms` | List of gear searches, such as `boss ds-1`. |
| `startUrls` | Reverb marketplace, API listings, category, brand, product, shop, or item URLs. |
| `maxItems` | Total unique item cap, from 1 to 10000; default 50. |
| `condition` | Condition filter; `any` omits the filter. |
| `listingStatus` | `live` or `sold` listing mode. |
| `make` | Brand or make filter. |
| `productType`, `category` | Top-level product type and optional subcategory slugs. |
| `priceMin`, `priceMax` | Minimum and maximum listed price. |
| `yearMin`, `yearMax` | Minimum and maximum listed instrument year. |
| `publishedWithinDays` | Keep only listings published in the last N days. Results are sorted newest first and each search stops at the first older listing. |
| `itemRegion`, `shipsTo` | Two-letter country codes for location and shipping destination. |
| `sortBy` | `relevance`, `newest`, `priceAsc`, or `priceDesc`. |
| `includeDetails` | Fetch per-item detail fields; default true. |
| `proxyConfiguration` | Optional Apify Proxy settings; off by default. |

```json
{
  "searchTerms": ["fender stratocaster", "gibson les paul"],
  "condition": "used",
  "productType": "electric-guitars",
  "priceMin": 500,
  "priceMax": 2000,
  "sortBy": "priceAsc",
  "maxItems": 40,
  "includeDetails": true
}
```

The example searches both phrases. The item cap applies to their combined output, and listing IDs seen in both searches appear only once. A request can use `startUrls` instead of `searchTerms`. The Actor also accepts the older single-text `query` or `search` input when no `searchTerms` array was provided. If neither a term nor a URL is supplied, it searches `fender stratocaster` and logs a warning so an empty API call does not silently produce unrelated output.

A start URL can be a plain string or a `{ "url": "..." }` object. Supported web paths include `/marketplace`, `/cat/...`, `/brand/...`, `/p/...`, `/shop/...`, and `/item/...`. HTTP links and www or mobile Reverb hosts are normalized to HTTPS on reverb.com. Locale prefixes and tracking parameters are removed. Other Reverb paths use their filters or final path segment as a search; non-Reverb hosts are skipped with a warning recorded in `RUN_SUMMARY`. Product and category slugs should match those used by Reverb in its own URLs or search parameters.

### Output

Here is a shortened real record from a local `fender stratocaster` search. The full dataset row also contains shipping rates, nullable detail fields, listing timestamps, and other fields listed above.

```json
{
  "id": "36356670",
  "sourceUrl": "https://reverb.com/item/36356670-fender-stratocaster-knob-set-black",
  "title": "Fender Stratocaster Knob Set Black",
  "price": 7.99,
  "currency": "USD",
  "condition": "Brand New",
  "state": "live",
  "make": "Fender Stratocaster Knob Set Black",
  "model": "Fender Stratocaster Knob Set Black",
  "category": "Parts / Knobs",
  "originalPrice": null,
  "priceDropPercent": null,
  "photoUrls": [
    "https://rvb-img.reverb.com/i/s--NHwwCtQL--/quality=medium-low,height=800,width=800,fit=contain/lmzpht1a8tglbmjvb58h.jpg"
  ],
  "shippingPrice": 5.5,
  "sellerName": "Mantova's Two Street Music"
}
```

If you need to compare listings across dates, store each run's dataset with its `scrapedAt` timestamp and retain the listing `id` as the join key.

### How much does it cost?

The Actor is charged per result pushed to the dataset. Check the Actor's Pricing tab for the current terms. `maxItems` is a direct way to bound the number of results. A zero-result search pushes no listing rows. The result event is applied once to each pushed item; duplicate IDs skipped within a run are not pushed again.

Turning off details can reduce the number of requests and shorten a run. It does not change which dataset fields exist, but fields that require item details are `null`. Search pages and item detail calls are requests to the same public Reverb API. If you enable Apify Proxy, its usage follows your Apify account's configuration.

### Use with AI agents (MCP)

An AI agent can call this Actor through Apify MCP when the Actor is available in your account. Configure the server with the Store path and ask for a bounded set of listings. A concrete prompt helps the agent choose the filters and interpret the price field correctly.

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=axiomworks/reverb-listings-scraper"
    }
  }
}
```

Example prompts: “Find 20 used Boss DS-1 listings and show title, price, condition, sellerName, and sourceUrl.” “Collect sold Fender Stratocaster listings and compare listed prices with the live results.” “Get public listing details for this Reverb item URL and report its condition and shippingPrice.” Agents should use `maxItems` to keep the requested result set bounded and use `sourceUrl` when citing a listing.

The Actor description, input descriptions, and dataset field names are intended to make selection straightforward for an agent. The schema exposes search terms and start URLs, filter options, the item cap, and optional detail fetching. An agent receiving `null` should report that the API did not provide that value. It should not infer a missing seller rating or shipping quote from unrelated fields.

### Integrations and API

You can run the Actor in a workflow and retrieve its default dataset using the Apify API. The snippets below use placeholder identifiers and your own configured API access. Keep credentials in your environment or secret store, not inside code that you publish. The run input is the same JSON object used in the input form.

Python:

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("axiomworks/reverb-listings-scraper").call(run_input={
    "searchTerms": ["boss ds-1"], "condition": "used", "maxItems": 20
})
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('axiomworks/reverb-listings-scraper').call({
  searchTerms: ['boss ds-1'], condition: 'used', maxItems: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

cURL:

```bash
curl -X POST \
  'https://api.apify.com/v2/acts/axiomworks~reverb-listings-scraper/runs?waitForFinish=120' \
  -H 'Authorization: Bearer YOUR_APIFY_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"searchTerms":["boss ds-1"],"condition":"used","maxItems":20}'
```

The run response identifies its default dataset. Read that dataset's items endpoint to retrieve rows. The Actor also writes `RUN_SUMMARY` to the default key-value store. That record is useful when a source produced zero matches or an input URL was skipped, because it separates search totals and errors from actual listing rows.

### FAQ

**Can I use a Reverb search URL?** Yes. Paste a public `/marketplace` URL into `startUrls`. Its query parameters are copied to the listings API. Explicit filter inputs fill parameters that the URL did not set.

**Can I collect sold gear?** Yes. Set `listingStatus` to `sold`, or provide a start URL with `show_only_sold=true`. The output `state` identifies the listing state. The price is the value exposed in the public listing record and may not reveal an accepted offer.

**Why is a field null?** Public listings are uneven. A seller may not enter a year or finish, a shipping rate may be unavailable, or the detail endpoint may not provide a metric. Detail-only fields are also null when `includeDetails` is false.

**Why did I get zero rows?** The search may have no matches, an item ID may no longer exist, or the URL may have been unsupported. Read the run status and `RUN_SUMMARY` for source totals and errors. A zero-result run does not create placeholder listing records.

**Does this download photos?** No. `imageUrl` is the main image address returned by the API, and `photoCount` is the number of listed photos. The Actor does not fetch image bytes.

**Can I combine several searches?** Yes. Provide several `searchTerms` and/or `startUrls`. The Actor processes them under one `maxItems` cap and removes duplicate IDs in the same run. The `searchTerm` field identifies the first source that produced each row.

### Is it legal to scrape Reverb?

The Actor reads public listing API responses and does not use a login. Whether a particular use is lawful depends on your jurisdiction, the site terms, and how you use or redistribute the data. Review the current rules that apply to your project before storing or republishing listing information. This Actor has no affiliation with Reverb and does not grant any rights in Reverb content or seller materials.

Keep request volumes modest and use `maxItems` for bounded collection. The Actor spaces calls and backs off after temporary blocks or rate limits. If you are building a long-running monitor, choose intervals that fit your actual research need. Listing data can change or disappear, so retain extraction dates and verify important decisions against the public item page.

### Feedback

If a field is missing, a supported URL produces no records unexpectedly, or a Reverb API response has changed shape, share the input settings, run ID, and a short description of the discrepancy through the Actor's feedback channel. Do not include private credentials. Reports with a public `sourceUrl` and the affected field name make it easier to reproduce and fix an issue. Suggestions for clearer field descriptions and practical filter combinations are welcome as well.

# Actor input Schema

## `searchTerms` (type: `array`):

List of gear keywords, one search per entry, e.g. \["boss ds-1","fender stratocaster"]. Each term runs separately; results share the maxItems budget and duplicates are removed. Leave empty when startUrls is given. A term with no matches adds no rows; the run still succeeds. With neither target supplied, searches fender stratocaster. Blocked targets return zero items and a status message.

## `startUrls` (type: `array`):

Reverb pages to collect from, as URL strings or {"url":...} objects, e.g. \["https://reverb.com/marketplace?query=ds-1","https://reverb.com/shop/some-shop","https://reverb.com/item/100291942-boss-ds-1"]. Accepts marketplace, category, brand, product, shop, item and listings API URLs. Unsupported or dead URLs are skipped.

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

Total unique listings to return across all searchTerms and startUrls combined, 1-10000, default 50. Example: 20. The run stops as soon as this many are pushed.

## `condition` (type: `string`):

Listing condition filter. One of any (default, no filter), used, new, brand-new, b-stock, mint, excellent, very-good, good, fair, poor, non-functioning. Example: used.

## `listingStatus` (type: `string`):

live (default) returns listings currently for sale; sold returns completed sales, whose price is the final listing price. Example: sold.

## `make` (type: `string`):

Brand name or slug to filter by, e.g. fender or boss. Combine with searchTerms to narrow results. Leave empty for all brands.

## `productType` (type: `string`):

Top-level Reverb category slug, e.g. electric-guitars, effects-and-pedals, amps. Leave empty for all types.

## `category` (type: `string`):

Subcategory slug used together with productType, e.g. distortion-and-overdrive with productType effects-and-pedals. Ignored when empty.

## `priceMin` (type: `number`):

Lowest listing price in USD to include, e.g. 50. Leave empty for no lower bound.

## `priceMax` (type: `number`):

Highest listing price in USD to include, e.g. 500. Leave empty for no upper bound.

## `yearMin` (type: `integer`):

Earliest instrument year to include, e.g. 1990. Leave empty for no lower bound.

## `yearMax` (type: `integer`):

Latest instrument year to include, e.g. 2005. Leave empty for no upper bound.

## `publishedWithinDays` (type: `integer`):

Only listings published in the last N days (1-3650). Results are sorted newest first and the search stops at the first older listing. Leave empty for no date filter.

## `itemRegion` (type: `string`):

Two-letter ISO country code where the item is located, e.g. US or DE. Leave empty for anywhere.

## `shipsTo` (type: `string`):

Two-letter ISO country code of the shipping destination, e.g. US or GB. Only listings that ship there are returned.

## `sortBy` (type: `string`):

relevance (default), newest (most recently published first), priceAsc (cheapest first) or priceDesc (most expensive first). Example: newest.

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

true (default) fetches each listing detail page to add location, country code, seller feedback, views, watchers, offer count and sold-as-is status; false is faster and leaves those fields null.

## `proxyConfiguration` (type: `object`):

Use Apify Proxy when requests are rate limited or blocked; disabled by default.

## Actor input object example

```json
{
  "searchTerms": [
    "boss ds-1"
  ],
  "startUrls": [],
  "maxItems": 20,
  "condition": "used",
  "listingStatus": "live",
  "sortBy": "relevance",
  "includeDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `listings` (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 = {
    "searchTerms": [
        "boss ds-1"
    ],
    "maxItems": 20,
    "condition": "used"
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/reverb-listings-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 = {
    "searchTerms": ["boss ds-1"],
    "maxItems": 20,
    "condition": "used",
}

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/reverb-listings-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 '{
  "searchTerms": [
    "boss ds-1"
  ],
  "maxItems": 20,
  "condition": "used"
}' |
apify call axiomworks/reverb-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,axiomworks/reverb-listings-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/eoZqELb9VppNuH9da/builds/6gXAR2XhbObjug09X/openapi.json
