# Sam Ash Music Scraper (`crawlerbros/sam-ash-music-scraper`) Actor

Scrape Sam Ash Music (samash.com) - search or browse musical instruments and gear by category, brand, price, and stock status, or look up exact products by SKU. Returns price, brand, stock status, sale badges, images, and product URLs.

- **URL**: https://apify.com/crawlerbros/sam-ash-music-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** E-commerce, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Sam Ash Music Scraper

Scrape [Sam Ash Music](https://www.samash.com) — search or browse musical instruments and gear by keyword, category, brand, price, stock status and sale/new-arrival badges, or look up exact products by SKU / model number. No login, no cookies, no paid proxy required.

### What this actor does

- **Two modes:** `search` (keyword and/or category/brand browse) and `bySkus` (exact SKU/model-number lookup)
- **Full department coverage:** Guitars, Bass Guitars, Drums & Percussion, Live Sound & Lighting, Microphones & Wireless, Recording, Band & Orchestra, Pianos & Keyboards, Cables, DJ & Production, Music Education & Gifts, Used Instruments, Sale, and more
- **300+ brand filter:** exact-match dropdown covering every brand carried by Sam Ash, from Yamaha and Gibson down to boutique pedal and accessory makers
- **6 sort orders:** best match, most popular, price (both directions), newest, best sellers
- **Price, stock, sale, new-arrival, and condition filters** — including `condition` (New / Used / Open Box / B-Stock / Demo) for gear-marketplace and secondhand-inventory use cases
- **Empty fields are omitted** — every record only contains data that was actually found

### Output per product

- `sku` — Sam Ash SKU
- `productId` — internal product ID
- `title` — product name
- `brand`
- `price` — current selling price (USD)
- `msrp` — list price, only included when it reflects a genuine discount
- `inStock` — boolean
- `onSale` — boolean
- `isNewArrival` — boolean
- `isPriceDrop` — boolean, true when the product carries a recent price-drop flag (distinct from `onSale`)
- `hasPromotion` — boolean, true when the product is eligible for an additional merchandising promotion
- `badges[]` — merchandising badges (e.g. financing offers)
- `description` — cleaned plain-text description (only when the catalog carries real copy)
- `imageUrl` — product photo (800×800)
- `productType`
- `condition` — `New` / `Used` / `Open Box` / `B-Stock` / `Demo`, only included when the catalog listing declares one (most regular new-stock items don't carry this facet)
- `department` — top-level category
- `categoryPath[]` — full category breadcrumb
- `sourceUrl` — canonical Sam Ash product page
- `recordType: "product"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `bySkus` |
| `searchQuery` | string | – | Free-text keyword search (mode=search) |
| `category` | string (select) | – | Top-level department filter |
| `brand` | string (select) | – | Exact brand/manufacturer filter (300+ options) |
| `condition` | string (select) | – | Exact condition filter: `New` / `Used` / `Open Box` / `B-Stock` / `Demo` (mode=search) |
| `sortBy` | string (select) | `relevance` | `relevance` / `popularity` / `priceLowToHigh` / `priceHighToLow` / `newest` / `bestSelling` |
| `minPrice` | integer | – | Drop products priced below this (USD) |
| `maxPrice` | integer | – | Drop products priced above this (USD) |
| `inStockOnly` | boolean | `false` | Only in-stock products |
| `onSaleOnly` | boolean | `false` | Only on-sale products |
| `newArrivalsOnly` | boolean | `false` | Only new-arrival products |
| `priceDropOnly` | boolean | `false` | Only products with a recent price-drop flag (distinct from `onSaleOnly`) |
| `skus` | array | – | Exact SKUs / model numbers (mode=bySkus) |
| `maxItems` | integer | `50` | Hard cap on emitted records (1–500) |

#### Example: keyword search with filters

```json
{
  "mode": "search",
  "searchQuery": "electric guitar",
  "brand": "Fender",
  "minPrice": 200,
  "maxPrice": 1500,
  "inStockOnly": true,
  "sortBy": "priceLowToHigh",
  "maxItems": 100
}
```

#### Example: browse a category without a keyword

```json
{
  "mode": "search",
  "category": "Drums & Percussion",
  "onSaleOnly": true,
  "sortBy": "bestSelling",
  "maxItems": 50
}
```

#### Example: exact SKU lookup

```json
{
  "mode": "bySkus",
  "skus": ["GES35500N", "TM80VTGXX"]
}
```

### Use cases

- **Price monitoring** — track prices and sale status for specific gear over time
- **Inventory intelligence** — check stock availability across brands/categories
- **Competitive research** — benchmark musical-instrument retail pricing
- **Catalog enrichment** — pull structured product data (brand, category, images) for a list of SKUs
- **Deal discovery** — surface on-sale or new-arrival products in a category

### FAQ

**Is a login or cookie required?** No. The actor uses Sam Ash's public product-search API and requires no account, cookies, or paid proxy.

**Why is `msrp` sometimes missing?** It's only included when it's genuinely higher than the current `price` (i.e., a real discount). When `msrp` equals `price`, it's omitted to avoid a redundant field.

**Why is `description` missing on some products?** Some catalog entries only reference an internal content block rather than carrying real descriptive text; those are omitted rather than emitting placeholder markup.

**Can I combine category and brand and keyword search together?** Yes — `searchQuery`, `category`, `brand`, and `condition` all combine (AND) in `search` mode, along with any of the price/stock/sale/new-arrival filters.

**How is `condition` different from the "Used Musical Instruments" `category`?** `category: "Used Musical Instruments"` is a merchandising department that groups a curated set of secondhand listings. `condition` is a per-product attribute (`New` / `Used` / `Open Box` / `B-Stock` / `Demo`) that appears across many departments — e.g. an open-box guitar amp still lives under "Live Sound & Lighting", not "Used Musical Instruments". Use `condition` when you want every non-new listing regardless of department; only a minority of catalog items carry this attribute at all (most standard new-stock products omit it, and the field is omitted from their output records).

**What if a SKU in `bySkus` doesn't exist?** It's skipped silently; the actor still returns any SKUs that do match.

**Are product page URLs (`sourceUrl`) safe to open?** Yes — they're the real, canonical Sam Ash product pages and resolve with a normal 200 response for any visitor or link-checker.

**How fresh is the data?** Prices and stock status reflect Sam Ash's live product-search index at the time the actor runs.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `searchQuery` (type: `string`):

Free-text keyword search (mode=search). Leave empty to browse the catalog / a category using only the filters below.

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

Restrict results to a top-level department/category.

## `brand` (type: `string`):

Restrict results to an exact brand/manufacturer.

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

Restrict results to an exact product condition.

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

Result ordering (mode=search).

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

Drop products priced below this amount.

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

Drop products priced above this amount.

## `inStockOnly` (type: `boolean`):

Only emit products currently marked in stock.

## `onSaleOnly` (type: `boolean`):

Only emit products currently marked on sale.

## `newArrivalsOnly` (type: `boolean`):

Only emit products marked as new arrivals.

## `priceDropOnly` (type: `boolean`):

Only emit products currently marked with a recent price drop (distinct from `onSaleOnly` — a product can have a price drop without being flagged as an official sale item).

## `skus` (type: `array`):

Exact Sam Ash SKUs or manufacturer model numbers, e.g. `GES35500N`.

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "electric guitar",
  "category": "",
  "brand": "",
  "condition": "",
  "sortBy": "relevance",
  "inStockOnly": false,
  "onSaleOnly": false,
  "newArrivalsOnly": false,
  "priceDropOnly": false,
  "skus": [
    "GES35500N"
  ],
  "maxItems": 50
}
```

# Actor output Schema

## `products` (type: `string`):

Dataset containing all scraped Sam Ash Music products.

# 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 = {
    "mode": "search",
    "searchQuery": "electric guitar",
    "category": "",
    "brand": "",
    "condition": "",
    "sortBy": "relevance",
    "inStockOnly": false,
    "onSaleOnly": false,
    "newArrivalsOnly": false,
    "priceDropOnly": false,
    "skus": [
        "GES35500N"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/sam-ash-music-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 = {
    "mode": "search",
    "searchQuery": "electric guitar",
    "category": "",
    "brand": "",
    "condition": "",
    "sortBy": "relevance",
    "inStockOnly": False,
    "onSaleOnly": False,
    "newArrivalsOnly": False,
    "priceDropOnly": False,
    "skus": ["GES35500N"],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/sam-ash-music-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 '{
  "mode": "search",
  "searchQuery": "electric guitar",
  "category": "",
  "brand": "",
  "condition": "",
  "sortBy": "relevance",
  "inStockOnly": false,
  "onSaleOnly": false,
  "newArrivalsOnly": false,
  "priceDropOnly": false,
  "skus": [
    "GES35500N"
  ],
  "maxItems": 50
}' |
apify call crawlerbros/sam-ash-music-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/sam-ash-music-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/MYJj3oBLGrfmdXyPu/builds/RqX6zgTCxnfsXhQ2s/openapi.json
