# Wholesale Marine Parts & Pricing Scraper (`vexaloom-labs/wholesale-marine-parts-and-pricing-scraper`) Actor

Search or browse Wholesale Marine's boat parts, electronics, and outdoor gear catalog by keyword, category, or brand, with live pricing, stock status, SKUs, images, and ratings per product.

- **URL**: https://apify.com/vexaloom-labs/wholesale-marine-parts-and-pricing-scraper.md
- **Developed by:** [vexaloom-labs](https://apify.com/vexaloom-labs) (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 $0.49 / 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/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

## Wholesale Marine Parts & Pricing Scraper

Pull structured product data from [Wholesale Marine](https://www.wholesalemarine.com), a US retailer of boat engine parts, propellers, electrical components, trailer parts, watersports gear and outdoor equipment. The actor talks directly to the store's public product API, so it returns full product records rather than just listing cards.

No account, cookies, API key or proxy setup is required.

### Ways to use it

- **Keyword search** — search the catalog by product name, part number, SKU or UPC. Add several queries in one run.
- **Category browse** — walk any category, including nested paths such as `boat-anchors/claw-anchors`, or paste a category URL.
- **Brand browse** — page through all products for a brand. The dropdown covers all 322 brands on the store; extra brand slugs are accepted.
- **Product URLs** — paste product links (or slugs) and get the full record for each one.
- **Full catalog** — stream the complete 190,000+ product catalog in newest, best-selling, featured or default order.

Every enriched result can include price, list price, inventory count, SKU/MPN/UPC/GTIN, brand, variants, specifications, fitment notes, gallery images, category breadcrumbs, weight and dimensions. Ratings and review counts are optional.

### Output fields

| Field | Type | Description |
|---|---|---|
| `productId` | string | Store product ID |
| `title` | string | Product name |
| `productUrl` | string | Canonical product page |
| `brand`, `brandUrl` | string | Brand name and brand page |
| `sku`, `mpn`, `upc`, `gtin` | string | Identifiers where the store publishes a valid value |
| `price`, `priceFormatted` | number/string | Current selling price (USD) |
| `listPrice`, `listPriceFormatted` | number/string | Original price when the item is discounted |
| `discountAmount`, `discountPercent` | number | Discount versus list price |
| `priceMin`, `priceMax` | number | Variant price range |
| `currency` | string | `USD` |
| `inStock` | boolean | Inventory availability |
| `stockQuantity` | integer | Units available to sell |
| `stockTracked` | boolean | Whether the store tracks inventory for the item |
| `availabilityText` | string | The store's own shipping/lead-time text (for example "Special Order") |
| `description` | string | Clean plain-text description |
| `descriptionHtml` | string | Cleaned description HTML, including spec/fitment tables (optional) |
| `images`, `primaryImage`, `imageUrl` | array/string | Gallery, main image and listing thumbnail |
| `categoryPath`, `categories` | array | Primary breadcrumb and all category assignments |
| `categorySlug` | string | Category used for a category run |
| `variantOptions` | array | Purchasable option names and values |
| `variantCount` | integer | Total number of variants (1 for simple products) |
| `variants` | array | Per-variant SKU, identifiers, price, list price, stock and selected options |
| `specifications` | object | Product attributes such as Material, Pitch, Voltage or Style |
| `fitmentNotes` | array | Free-text application/fitment notes published by the store |
| `replacesPartNumbers` | array | Interchangeable/replacement part numbers |
| `weight`, `weightUnit`, `dimensions` | number/string/object | Shipping weight and L×W×H dimensions |
| `condition` | string | Product condition when the store publishes one (for example `NEW`) |
| `warranty` | string | Warranty text when published in a dedicated field |
| `videos` | array | Product video title/URL pairs |
| `specificationTables` | array | Structured headers/rows from specification and application charts in the description |
| `ratingValue`, `reviewCount`, `ratingDistribution` | number/object | Customer rating summary from the store's review widget |
| `source`, `sourceValue` | string | Which query, category, brand or URL produced the row |
| `recordType`, `scrapedAt` | string | Always `product`; UTC scrape timestamp |

Empty values are omitted, never emitted as `null` or placeholders.

### Inputs

| Field | Type | Default | What it does |
|---|---|---|---|
| `mode` | select | `keyword_search` | `keyword_search`, `category_browse`, `brand_browse`, `direct_product_url` or `full_catalog` |
| `searchQuery` | string | `propeller` | Main keyword, part number or UPC |
| `extraSearchQueries` | array | `[]` | Additional keyword queries in the same run |
| `categoryPath` | select | — | 250 popular categories, including nested paths |
| `extraCategoryPaths` | array | `[]` | Any additional category slug, path or URL |
| `brandSlug` | select | — | All 322 store brands |
| `extraBrandSlugs` | array | `[]` | Any additional brand slug, name or URL |
| `productUrls` | array | `[]` | Product URLs or slugs for URL mode |
| `sortOrder` | select | `bestselling` | Best selling, featured, newest, A–Z, Z–A, price low/high, or best match |
| `fullCatalogSort` | select | `newest` | Order for full-catalog runs |
| `minPrice`, `maxPrice` | integer | — | USD price bounds |
| `inStockOnly` | boolean | `false` | Drop records whose inventory is out of stock |
| `includeDetails` | boolean | `true` | Enrich listing rows with API-only fields |
| `includeRatings` | boolean | `true` | Fetch rating/review summaries |
| `includeDescriptionHtml` | boolean | `false` | Include the cleaned description HTML |
| `maxItems` | integer | `20` | Total record cap (1–100,000) |
| `maxItemsPerQuery` | integer | `1000` | Cap per keyword query or category batch (1–10,000); brand/full runs use `maxItems` |

### Examples

Search by part number:

```json
{"mode":"keyword_search","searchQuery":"8M0097854","sortOrder":"relevance","maxItems":20}
```

Browse a subcategory sorted by price:

```json
{"mode":"category_browse","categoryPath":"boat-anchors/claw-anchors","sortOrder":"priceasc","inStockOnly":true,"maxItems":50}
```

Browse a brand, with a second brand and ratings:

```json
{"mode":"brand_browse","brandSlug":"Yamaha","extraBrandSlugs":["Mercury-Mercruiser"],"sortOrder":"bestselling","maxItems":100}
```

Fetch exact products:

```json
{"mode":"direct_product_url","productUrls":["https://www.wholesalemarine.com/johnson-pump-cartridge-bilge-pump/"]}
```

Pull the newest catalog slice:

```json
{"mode":"full_catalog","fullCatalogSort":"newest","maxItems":500,"includeRatings":false}
```

### Use cases

- **Price monitoring** — schedule category or brand runs and compare price, list price and discount over time.
- **MAP compliance** — compare a brand's live listings and identifiers against your own catalog.
- **Inventory and stock-out alerts** — watch `stockQuantity` and `inStock` for key SKUs.
- **Parts catalog enrichment** — fill SKU, MPN, UPC, specs, images and fitment notes in a PIM or storefront.
- **Dropshipping research** — export sellable products with live cost, stock and images.
- **Fitment-aware sourcing** — search engine parts by part number and read the store's application notes before ordering.

### FAQ

**Do I need a Wholesale Marine account or cookies?** No. The actor uses the public storefront and its public product API.

**Do I need to configure a proxy?** No. The actor handles its own connection fallbacks.

**How large is the catalog?** About 190,000 products across 1,162 categories and 322 brands.

**Why does a keyword search stop at 10,000 rows?** The store's search index has a 10,000-result ceiling. The actor partitions large requests by price to get past that ceiling when you ask for more.

**Does it return out-of-stock items?** Category and keyword pages follow the store's in-stock search index. Brand, full-catalog and URL runs can include out-of-stock items; set `inStockOnly` to drop them.

**Where do ratings come from?** From the same customer-review widget shown on product pages. Products without reviews omit the rating fields.

**How long does a full-catalog run take?** Roughly 25–30 minutes for all 190,000 products. Use `maxItems` for a smaller snapshot.

**Can I use a category or brand that is not in the dropdown?** Yes — use `extraCategoryPaths` or `extraBrandSlugs` with a slug, path, name or full URL.

**Is this affiliated with Wholesale Marine?** No. It is an independent data tool that reads publicly available storefront pages and APIs.

### Limitations

- The store's keyword and category pages expose at most 10,000 results per query; larger runs are split by price or child category.
- Full-catalog price/name sorting is not supported by the store API; use keyword, category or brand mode when you need those orders.
- `fitmentNotes` are free-text application notes. Full fitment charts are preserved in `descriptionHtml` rather than converted to a normalized table.
- Wholesale Marine is an online-only retailer, so there is no per-store inventory data.
- `availabilityText` is the store's shipping/lead-time message, not a stock flag; use `inStock` and `stockQuantity` for stock decisions.
- Price-filtered brand and full-catalog runs use the store's search index, which lists in-stock products; unfiltered brand/full runs include out-of-stock products unless `inStockOnly` is set.
- With a price range set, brand and full-catalog results follow the search index order rather than `sortOrder`/`fullCatalogSort`.
- The full catalog cursor reaches all 190,565 products, but one run is capped at 100,000 rows and the 190k pass takes longer than the default one-hour timeout. Split by category/brand for a complete snapshot, or raise the run timeout.
- `warranty` is only available when the store publishes a dedicated field; warranty prose inside a description is not converted. `condition` and `videos` are conditional (most listings are new and have no video).
- `specificationTables` and `fitmentNotes` expose the store's published charts/notes; there is no normalized fitment API.
- The category dropdown is curated to 250 paths; every one of the 1,162 storefront categories is accepted through `extraCategoryPaths`.

# Actor input Schema

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

What to fetch.

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

Free-text product, part-number or UPC search (mode=keyword_search), e.g. `propeller`, `8M0097854`, `652480100512`.

## `extraSearchQueries` (type: `array`):

Optional additional keyword queries for the same run (mode=keyword_search). Duplicates are removed.

## `categoryPath` (type: `string`):

Pick a category to browse (mode=category_browse). Full paths work, e.g. `boat-anchors/claw-anchors`.

## `extraCategoryPaths` (type: `array`):

Any additional category slug, path or URL (mode=category_browse), including subcategories not in the dropdown.

## `brandSlug` (type: `string`):

Pick a brand to browse (mode=brand_browse).

## `extraBrandSlugs` (type: `array`):

Any additional brand slug, name or URL (mode=brand_browse).

## `productUrls` (type: `array`):

Wholesale Marine product URLs or slugs to fetch in full detail (mode=direct_product_url).

## `sortOrder` (type: `string`):

Order for keyword/category/brand results. `relevance` is the site's best-match order for keyword search; category and brand use featured order for it. Ignored by full_catalog.

## `fullCatalogSort` (type: `string`):

Order for mode=full_catalog: newest, best selling, featured, or the store's default catalog order.

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

Drop products priced below this amount.

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

Drop products priced above this amount.

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

Drop products whose inventory says they are out of stock. Listing pages already show in-stock products only; this also affects brand, full-catalog and product-URL runs.

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

Enrich listing results with SKU, stock, specifications, variants, images and description. Adds Storefront API requests; turn off for a faster, card-only run.

## `includeRatings` (type: `boolean`):

Fetch each product's customer rating and review count from the store's review widget. Adds one request per product.

## `includeDescriptionHtml` (type: `boolean`):

Add the original (cleaned) product description HTML, including specification and fitment tables. Increases record size.

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

Hard cap on emitted product records.

## `maxItemsPerQuery` (type: `integer`):

Cap for each keyword query or category batch. Brand and full-catalog runs use maxItems instead.

## Actor input object example

```json
{
  "mode": "keyword_search",
  "searchQuery": "propeller",
  "extraSearchQueries": [],
  "extraCategoryPaths": [],
  "extraBrandSlugs": [],
  "productUrls": [],
  "sortOrder": "relevance",
  "fullCatalogSort": "newest",
  "inStockOnly": false,
  "includeDetails": true,
  "includeRatings": true,
  "includeDescriptionHtml": false,
  "maxItems": 3,
  "maxItemsPerQuery": 50
}
```

# Actor output Schema

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

Dataset containing all scraped Wholesale Marine 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": "keyword_search",
    "searchQuery": "propeller",
    "extraSearchQueries": [],
    "extraCategoryPaths": [],
    "extraBrandSlugs": [],
    "productUrls": [],
    "sortOrder": "relevance",
    "inStockOnly": false,
    "includeDetails": true,
    "includeRatings": false,
    "includeDescriptionHtml": false,
    "maxItems": 3,
    "maxItemsPerQuery": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("vexaloom-labs/wholesale-marine-parts-and-pricing-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": "keyword_search",
    "searchQuery": "propeller",
    "extraSearchQueries": [],
    "extraCategoryPaths": [],
    "extraBrandSlugs": [],
    "productUrls": [],
    "sortOrder": "relevance",
    "inStockOnly": False,
    "includeDetails": True,
    "includeRatings": False,
    "includeDescriptionHtml": False,
    "maxItems": 3,
    "maxItemsPerQuery": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("vexaloom-labs/wholesale-marine-parts-and-pricing-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": "keyword_search",
  "searchQuery": "propeller",
  "extraSearchQueries": [],
  "extraCategoryPaths": [],
  "extraBrandSlugs": [],
  "productUrls": [],
  "sortOrder": "relevance",
  "inStockOnly": false,
  "includeDetails": true,
  "includeRatings": false,
  "includeDescriptionHtml": false,
  "maxItems": 3,
  "maxItemsPerQuery": 50
}' |
apify call vexaloom-labs/wholesale-marine-parts-and-pricing-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vexaloom-labs/wholesale-marine-parts-and-pricing-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/3TB30kbBWMkj0uRW7/builds/pXPQOs1201uWHO0T5/openapi.json
