# TractorHouse Scraper (`crawlerbros/tractorhouse-scraper`) Actor

Scrape TractorHouse.com farm equipment, tractors, construction machinery, trailers, and trucks. Search by keyword, category, manufacturer, price/year/hours range, state, and condition, or fetch full listing detail records by ID/URL.

- **URL**: https://apify.com/crawlerbros/tractorhouse-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

## TractorHouse Scraper

Scrape [TractorHouse.com](https://www.tractorhouse.com) — the leading online marketplace for tractors, farm equipment, construction machinery, trailers, and trucks. Search by keyword, category, manufacturer, price/year/hours range, US state or Canadian province, and condition — or fetch a full detail record (specs, seller contact, photos, video) for a specific listing ID or URL. No login, no cookies, no paid proxy.

### What this actor does

- **Two modes:** `search` (keyword/filter browse) and `byListingIds` (full detail lookup)
- **51 equipment categories** — tractors (by HP class), harvesters, tillage, hay & forage, dozers, excavators, skid steers, wheel loaders, telehandlers, trailers, trucks, and more
- **40 manufacturer filters** — John Deere, Case IH, New Holland, Kubota, Massey Ferguson, Caterpillar, Bobcat, and more
- **Location filter** — every US state + Canadian province
- **Price / model-year / operating-hours range filters**
- **Condition (New/Used) filter**
- **Full specs on detail lookups** — every spec the seller listed (year, hours, drivetrain, tires, etc.), seller name/phone/location, all photos, and video if present
- **Empty fields are omitted**

### Output per listing

#### Search mode

- `listingId`, `title`, `category`, `manufacturer`, `model`, `description`
- `price`, `currency`, `condition`, `availability`
- `imageUrl`, `listingUrl`
- `locationState`, `locationPostalCode`, `locationCountry`, `locationStreetAddress` (when public)
- `recordType: "listing"`, `scrapedAt`

#### Detail lookup mode (`byListingIds`)

Everything above, plus:

- `year`, `hours`, `listingType`, `priceDisplay`, `priceValidUntil`
- `specs` — every spec/attribute the seller entered (varies by equipment type)
- `sellerName`, `sellerPhone`, `sellerLocationCity`, `sellerLocationState`, `sellerLocationFull`
- `imageUrls[]` (up to 20), `videoUrl` (when the listing has a video)
- `recordType: "listingDetail"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `search` | `search` / `byListingIds` |
| `keywords` | string | – | Free-text search (mode=search). Leave blank to browse by `category`/`manufacturer`/`state`/etc. alone -- a non-blank value ANDs a keyword filter on top of any other filters set. |
| `category` | select | – | One of 51 equipment categories |
| `manufacturer` | select | – | One of 40 manufacturer brands |
| `state` | select | – | US state / Canadian province |
| `condition` | select | – | `Used` / `New` |
| `priceMin` / `priceMax` | int | – | Price range in USD |
| `yearMin` / `yearMax` | int | – | Model-year range |
| `hoursMin` / `hoursMax` | int | – | Operating-hours range |
| `listingIds` | array | – | Listing IDs or full listing URLs (mode=byListingIds) |
| `maxItems` | int | `25` | Hard cap (1–1000) |

#### Example: John Deere tractors under $60,000 in Iowa

```json
{
  "mode": "search",
  "category": "tractors",
  "manufacturer": "JOHN DEERE",
  "state": "IOWA",
  "priceMax": 60000,
  "maxItems": 50
}
```

#### Example: recent low-hour excavators

```json
{
  "mode": "search",
  "category": "crawlerExcavators",
  "yearMin": 2020,
  "hoursMax": 1500,
  "condition": "Used",
  "maxItems": 50
}
```

#### Example: full detail lookup

```json
{
  "mode": "byListingIds",
  "listingIds": [
    "257864499",
    "https://www.tractorhouse.com/listing/for-sale/241503499/some-listing-slug"
  ]
}
```

### Use cases

- **Equipment dealers** — track competitor inventory and pricing by manufacturer/category/region
- **Ag-tech & market intelligence** — analyze used-equipment pricing trends by model year and hours
- **Procurement** — monitor new listings matching a specific make/model/price band
- **Lead generation** — pull seller contact details from detail lookups for outreach

### FAQ

**Do I need a TractorHouse account or API key?** No. This actor scrapes publicly accessible listing pages — no login, cookies, or API key required.

**Why are there two modes?** `search` is fast and returns the browse-page fields (price, condition, location, thumbnail) for many listings at once. `byListingIds` fetches the full detail page per listing — richer (full specs, seller contact, photo gallery, video) but one HTTP request per listing, so use it for a shortlist rather than a full category sweep.

**What does `specs` contain?** TractorHouse lets sellers fill in category-specific attributes (e.g. tires vs. tracks for a skid steer, row spacing for a planter, drivetrain for a tractor). The actor passes through every spec key/value the listing has — the set of keys varies by equipment type.

**Can I combine filters?** Yes — `category`, `manufacturer`, `state`, `condition`, and all four range filters (`price`, `year`, `hours`) can be combined freely in `search` mode.

**Why do `search`-mode records not include `year`/`hours`?** TractorHouse's search-results cards don't expose those in their structured data — only the detail page does. Use `yearMin`/`yearMax`/`hoursMin`/`hoursMax` as server-side filters in `search` mode (they still narrow results correctly), or use `byListingIds` to get the explicit `year`/`hours` fields back per listing.

**How fresh is the data?** Listings are live at request time — TractorHouse is a real-time marketplace, not a static catalog.

**Is this actor global?** Coverage spans the US and Canada (all 50 states + 10 provinces are supported location filters); most listed equipment is located in North America.

**Why might a very large `maxItems` return fewer records than requested?** TractorHouse sits behind a Cloudflare managed challenge. The actor uses stealth-hardened Playwright with rotating proxy sessions and automatic retries per page, which reliably gets past the challenge for the first several search-result pages, but on a broad, unfiltered search Cloudflare can start rate-limiting further pagination mid-run. When that happens the actor fails soft — it keeps every listing already collected (no partial/corrupt records) and ends the run cleanly rather than erroring out. Narrowing the search (category/manufacturer/state) or re-running typically recovers full pagination.

# Actor input Schema

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

What to fetch.

## `keywords` (type: `string`):

Free-text search across listing titles/descriptions (mode=search).

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

Restrict to an equipment category (mode=search). Leave unset to search all categories.

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

Restrict to a specific manufacturer/brand (mode=search).

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

Restrict to listings located in a specific US state or Canadian province (mode=search).

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

Restrict to new or used equipment (mode=search).

## `priceMin` (type: `integer`):

Drop listings priced below this amount.

## `priceMax` (type: `integer`):

Drop listings priced above this amount.

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

Drop listings with a model year below this.

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

Drop listings with a model year above this.

## `hoursMin` (type: `integer`):

Drop listings with fewer operating hours than this.

## `hoursMax` (type: `integer`):

Drop listings with more operating hours than this.

## `listingIds` (type: `array`):

TractorHouse listing IDs (e.g. `257864499`) or full listing URLs to fetch full detail records for.

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

Hard cap on emitted records.

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

TractorHouse's Cloudflare protection blocks direct datacenter requests; this actor uses Apify's free AUTO datacenter proxy group to reach it. No paid/residential proxy is required.

## Actor input object example

```json
{
  "mode": "search",
  "keywords": "tractor",
  "category": "",
  "manufacturer": "",
  "state": "",
  "condition": "",
  "listingIds": [],
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset containing all scraped TractorHouse 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": "search",
    "keywords": "tractor",
    "listingIds": [],
    "maxItems": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/tractorhouse-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",
    "keywords": "tractor",
    "listingIds": [],
    "maxItems": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/tractorhouse-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",
  "keywords": "tractor",
  "listingIds": [],
  "maxItems": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/tractorhouse-scraper --silent --output-dataset

```

## MCP server setup

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