# Heavy Equipment Scraper (`crawlerbros/heavyequipment-scraper`) Actor

Scrape heavyequipment.com listings - search by keyword, browse by category or equipment type, or filter by US state / Canadian province. Get price, manufacturer, model, hours, condition, and images for construction and industrial equipment for sale.

- **URL**: https://apify.com/crawlerbros/heavyequipment-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, E-commerce, 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/actors/running/actors-in-store.md#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

## Heavy Equipment Scraper

Scrape **heavyequipment.com** — a marketplace for construction, forestry, and industrial equipment for sale. Search by keyword, browse by category or specific equipment type (excavators, dozers, cranes, wheel loaders, and more), or filter by US state / Canadian province. Get price, manufacturer, model, hours, condition, description, and photos for every listing. No login, no cookies required.

### What this actor does

- **Four modes:** `search` (keyword), `byCategory` (top-level category), `bySubCategory` (specific equipment type), `byLocation` (US state / Canadian province)
- **Two-tier filtering:** category, keyword, and location are applied on the source site itself; manufacturer, price, model year, and condition are applied after retrieval so you can narrow results by criteria the site itself doesn't support natively
- **Real prices only** — if a listing has no genuine price posted anywhere, the `price` field is simply left out rather than showing a fake `$0`
- **Empty fields are omitted** — a listing only includes the fields that were actually found on its page

### Output per listing

- `title` — listing headline
- `listingUrl` — direct link to the listing
- `price`, `currency` — numeric price and its currency (USD or CAD), when a real price is posted
- `category` — top-level category (e.g. `Heavy Equipment`), when known from the search
- `subCategory` — the specific equipment type as listed on the page (e.g. `Excavators`, `Dozers`, `Graders`)
- `manufacturer`, `model`, `serialNumber`, `series`
- `hours` — recorded operating hours, when listed
- `year` — model year, extracted from the title when present
- `condition` — one of `new`, `like_new`, `lightly_used`, `heavy_usage`, `salvage`, `repair`
- `description` — full listing description
- `images[]` — photo URLs
- `sku` — internal listing SKU
- `recordType: "listing"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `byCategory` | `search` / `byCategory` / `bySubCategory` / `byLocation` |
| `q` | string | – | Keyword search (mode=search) |
| `category` | string | `1` | Top-level category (mode=byCategory) |
| `subCategory` | string | `excavators` | Specific equipment type (mode=bySubCategory) |
| `country` | string | `233` (United States) | Country (mode=byLocation) |
| `state` | string | – | US state / Canadian province (mode=byLocation) |
| `manufacturer` | string | – | Keep only this manufacturer (partial match, e.g. `cat`, `john deere`) |
| `minPrice` / `maxPrice` | int | – | Price range in USD/CAD |
| `minYear` / `maxYear` | int | – | Model year range |
| `condition` | string | – | `new` / `like_new` / `lightly_used` / `heavy_usage` / `salvage` / `repair` |
| `maxItems` | int | `20` | Hard cap on emitted records (1–500) |
| `proxyConfiguration` | object | Apify Proxy (auto) | Optional — only used automatically as a fallback if the site starts blocking requests |

#### Example: search by keyword, filter by manufacturer

```json
{
  "mode": "search",
  "q": "excavator",
  "manufacturer": "komatsu",
  "maxItems": 25
}
```

#### Example: browse a specific equipment type with price and year filters

```json
{
  "mode": "bySubCategory",
  "subCategory": "dozers",
  "minPrice": 20000,
  "maxPrice": 100000,
  "minYear": 2010,
  "maxItems": 50
}
```

#### Example: browse all heavy equipment listed in a US state

```json
{
  "mode": "byLocation",
  "country": "233",
  "state": "1416",
  "condition": "lightly_used",
  "maxItems": 50
}
```

#### Example: browse a top-level category

```json
{
  "mode": "byCategory",
  "category": "1",
  "maxItems": 20
}
```

### Use cases

- **Equipment dealers** — monitor new listings and pricing for competitive benchmarking
- **Buyers** — filter a small marketplace quickly by manufacturer, price, and condition without manual browsing
- **Market research** — track how equipment types (excavators, cranes, dozers) are priced across regions
- **Procurement teams** — build a shortlist of available equipment matching budget and year requirements
- **Data aggregators** — feed heavy-equipment listings into a broader marketplace search tool

### FAQ

**What's heavyequipment.com?** An online marketplace for buying and selling construction, forestry, and industrial equipment, parts, attachments, and reference manuals.

**Why do `category` and `subCategory` sometimes differ from what I expected?** `category` reflects the top-level section the listing was found under (e.g. "Heavy Equipment"), while `subCategory` reflects the specific equipment type recorded on the listing itself (e.g. "Excavators", "Graders") — sellers occasionally label a listing under a type that doesn't map 1:1 to the browse menu.

**Why is `price` missing on some listings?** A small number of listings on the source site have no price entered anywhere (neither the listing page nor its structured data) — these are typically "call for price" style listings. Rather than showing a fabricated `$0`, the actor leaves the field out entirely.

**Why aren't `manufacturer`, `minPrice`/`maxPrice`, `minYear`/`maxYear`, and `condition` available as search parameters on the site itself?** They aren't — the source site's own search only supports keyword, category, and location. This actor applies those four filters itself after retrieving the listings, so results can be further narrowed by manufacturer, price, and year after retrieval, even though the site can't do that natively.

**Does `manufacturer` require an exact match?** No — it matches at the start of a word, case-insensitively, so `cat` matches `CAT` and `Caterpillar` but correctly skips unrelated brands like `Bobcat`.

**Are `location` (city/dealer) or `seller phone` available?** No — the source site doesn't display seller location, dealer name, or contact phone on listing pages; that information requires contacting the seller through the site directly.

**Is this actor affiliated with heavyequipment.com?** No — this is an independent, third-party actor that reads publicly available listing pages.

**How fresh is the data?** As fresh as the last time you ran the actor — each run reads the live site directly, there's no caching.

# Actor input Schema

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

What to fetch.

## `q` (type: `string`):

Free-text keyword search, e.g. `caterpillar` (mode=search).

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

Top-level category to browse (mode=byCategory).

## `subCategory` (type: `string`):

Specific equipment type to browse (mode=bySubCategory).

## `country` (type: `string`):

Country to browse (mode=byLocation). Combined server-side with the Heavy Equipment category.

## `state` (type: `string`):

US state or Canadian province to filter by (mode=byLocation). Leave as "(no state filter)" to browse the whole selected country.

## `manufacturer` (type: `string`):

Keep only listings whose manufacturer matches (case-insensitive, partial match allowed). Not a controlled list on the source site, so any text works — common values include CAT / Caterpillar, John Deere, Komatsu, Case, Volvo, Kubota, Bobcat, JCB, Hitachi, Sany, Doosan, Liebherr, Hyundai, Ponsse.

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

Drop listings priced below this amount. Applied after retrieval, on whichever currency the listing was posted in.

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

Drop listings priced above this amount. Applied after retrieval, on whichever currency the listing was posted in.

## `minYear` (type: `integer`):

Drop listings whose title year is earlier than this. Listings with no extractable year are kept unless this filter is set.

## `maxYear` (type: `integer`):

Drop listings whose title year is later than this. Listings with no extractable year are kept unless this filter is set.

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

Keep only listings with this condition.

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

Hard cap on emitted records.

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

Optional. The source site has no anti-bot protection, so a proxy isn't required — this is only used as an automatic fallback if the site starts blocking requests.

## Actor input object example

```json
{
  "mode": "byCategory",
  "q": "caterpillar",
  "category": "1",
  "subCategory": "excavators",
  "country": "233",
  "state": "",
  "condition": "",
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

Dataset containing all scraped heavyequipment.com listings.

# 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": "byCategory",
    "q": "caterpillar",
    "category": "1",
    "subCategory": "excavators",
    "country": "233",
    "state": "",
    "condition": "",
    "maxItems": 5,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/heavyequipment-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": "byCategory",
    "q": "caterpillar",
    "category": "1",
    "subCategory": "excavators",
    "country": "233",
    "state": "",
    "condition": "",
    "maxItems": 5,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/heavyequipment-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": "byCategory",
  "q": "caterpillar",
  "category": "1",
  "subCategory": "excavators",
  "country": "233",
  "state": "",
  "condition": "",
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/heavyequipment-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/heavyequipment-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/ZqiAEcFOjRbPnh1kq/builds/4YqRb2BaKt5NcjPd3/openapi.json
