# MachineryZone Scraper — Equipment Listings (`muhammadafzal/machineryzone-scraper`) Actor

Extract public MachineryZone equipment listings with prices, specifications, locations, professional sellers, descriptions, and images.

- **URL**: https://apify.com/muhammadafzal/machineryzone-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 equipment listing scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## MachineryZone Scraper — Equipment Listings

Extract public MachineryZone heavy-equipment listings into clean JSON, CSV, Excel, or API-ready dataset records. The Actor accepts search/category, brand, model, and individual listing URLs and returns prices, specifications, locations, professional sellers, descriptions, and image URLs.

### What it extracts

| Field group | Data |
|---|---|
| Identity | Listing ID, title, canonical URL, new/used condition, category |
| Equipment | Make, model, year, operating hours, weight in tonnes |
| Price | Numeric original-currency price, ISO currency, displayed price text |
| Location | Public location, country, region, approximate coordinates when embedded on a search card |
| Seller | Public organization name, business type, business registration number, MachineryZone profile URL |
| Detail | Ad type, availability, advertiser description, public gallery image URLs |
| Provenance | Discovery search URL and UTC scrape timestamp |

Nullable fields stay `null` when an advertiser did not publish them. Price-on-request ads are preserved with `price: null` and their visible `priceText`.

### Good uses

- Monitor used construction-equipment inventory and asking prices.
- Build equipment-market research and valuation datasets.
- Compare makes, models, years, hours, weights, sellers, and regions.
- Feed public listings into lead qualification, procurement, or availability workflows.

This Actor is not for account pages, posting ads, sending seller inquiries, revealing hidden phone numbers, bypassing CAPTCHA, or collecting private user data. It only reads public search and listing pages.

### Input

| Input | Default | Notes |
|---|---:|---|
| `startUrls` | Mini excavators search | One or more public MachineryZone search/category, brand, model, or listing URLs |
| `maxResults` | `5` | Strict dataset and billable result cap; range 1–1000. The small default keeps the prefilled run inside Apify's five-minute quality check. |
| `maxPagesPerUrl` | `5` | Pagination cap per search input; range 1–50 |
| `scrapeDetails` | `true` | Open detail pages for original-currency price, description, seller, and gallery enrichment |
| `includeImages` | `true` | Return public image URLs without downloading files |
| `maxConcurrency` | `1` | Browser concurrency, deliberately capped at 3 |
| `proxyConfiguration` | US residential | Proxy route used to keep a coherent browser session |

Example input:

```json
{
  "startUrls": [
    { "url": "https://www.machineryzone.com/used/1/mini-excavator.html" },
    { "url": "https://www.machineryzone.com/used/1/wheeled-loader.html" }
  ],
  "maxResults": 50,
  "maxPagesPerUrl": 3,
  "scrapeDetails": true,
  "includeImages": true,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  }
}
```

Run through the Apify API by posting that JSON to the Actor run endpoint, then read records from the run's default dataset. The output schema exposes direct links to both the dataset items and the `OUTPUT` summary.

### Output example

```json
{
  "listingId": "45193032",
  "title": "Bobcat E26",
  "listingUrl": "https://www.machineryzone.com/used/mini-excavator/45193032/bobcat-e26.html",
  "condition": "used",
  "category": "Mini Excavators",
  "make": "Bobcat",
  "model": "E26",
  "year": 2016,
  "hours": 3070,
  "weightTonnes": 3,
  "price": 18500,
  "priceCurrency": "EUR",
  "priceText": "21,488 $",
  "adType": "For sale / Offers",
  "availability": "InStock",
  "location": "France, Occitanie",
  "country": "France",
  "region": "Occitanie",
  "latitude": 43.3,
  "longitude": 1.25,
  "sellerName": "TP ZONE",
  "sellerType": "Vehicle/equipment Wholesale",
  "businessLicenseNumber": "80413556400040",
  "sellerProfileUrl": "https://www.machineryzone.com/pros/list/402382-0/1/tp-zone.html",
  "description": "Mini excavator in very good condition.",
  "imageUrls": ["https://example-cdn.invalid/equipment.jpg"],
  "sourceSearchUrl": "https://www.machineryzone.com/used/1/mini-excavator.html",
  "scrapedAt": "2026-09-05T12:00:00.000Z"
}
```

### Pricing

The Actor uses Pay per event. Apify charges the start event automatically, and the Actor charges a result only after the validated listing has been stored.

| Event | Price |
|---|---:|
| Actor start | $0.0005 per GB of run memory; two events ($0.001) at the 2 GB default |
| Equipment listing scraped | $0.004 per stored unique listing |

At the 2 GB default, five listings cost up to `$0.021`, ten listings cost up to `$0.041`, and 100 listings cost up to `$0.401`, excluding any platform-usage pass-through if the owner later enables it. `maxResults` caps listing events, and the Actor stops when Apify reports that the user's event spending limit has been reached.

### Reliability and failure behavior

MachineryZone protects its public pages with DataDome and commonly rejects ordinary HTTP clients. The Actor uses a Camoufox/Firefox browser, persistent cookies, coherent low-concurrency sessions, residential-proxy defaults, bounded retries, session retirement on challenges, and structured JSON-LD plus visible-selector fallbacks. If a detail page is blocked after its search card loaded, the Actor preserves the valid card record and reports the missing enrichment in `OUTPUT`.

An honest empty search returns zero dataset rows and an `EMPTY` summary. A systemic challenge returns `BLOCKED`, zero fabricated rows, and zero result charges. Invalid URLs are rejected before crawling. The Actor does not solve CAPTCHA, access authenticated content, or submit forms.

### Responsible use

Scrape only public data you are allowed to collect. Follow MachineryZone's terms, robots guidance, applicable privacy law, and reasonable request rates. Seller fields are limited to publicly displayed professional-business information; the Actor intentionally excludes contact-person names, WhatsApp links, email addresses, and hidden phone numbers. You are responsible for your downstream retention and outreach rules.

For support, include the Actor run ID, a redacted input example, and whether the failure affected search pages, detail pages, or both. Never send account credentials or proxy passwords.

# Actor input Schema

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

Use this for public MachineryZone search/category, brand, model, or individual listing pages. Enter full machineryzone.com URLs, for example https://www.machineryzone.com/used/1/mini-excavator.html. Defaults to mini excavators. Account, advertiser-contact, and ad-creation pages are not accepted.

## `maxResults` (type: `integer`):

Use this to set a strict stored-listing and billable result-event cap across all URLs. Defaults to 5 so the prefilled run completes within Apify's five-minute quality check; accepts 1 through 1000. Search pages, retries, and skipped duplicates do not count.

## `maxPagesPerUrl` (type: `integer`):

Use this to bound pagination for each search/category URL. Defaults to 5 and accepts 1 through 50. It does not create pagination for an individual listing URL.

## `scrapeDetails` (type: `boolean`):

Use this for full descriptions, model, condition, original-currency price, seller business details, and gallery images. Defaults to true. Set false for a faster search-card export. The Actor never opens contact forms or reveals hidden phone numbers.

## `includeImages` (type: `boolean`):

Use this to return public equipment gallery URLs. Defaults to true. Set false for smaller agent responses and CSV exports; it does not download image files.

## `maxConcurrency` (type: `integer`):

Use this to balance speed, target load, and DataDome session stability. Defaults to 1 and accepts 1 through 3. Keep the default unless you have permission and measured evidence for a higher rate.

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

Use this to select an Apify or custom proxy. MachineryZone protects public pages with DataDome, so the default uses a sticky US residential route. Disabling it commonly returns an access challenge.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.machineryzone.com/used/1/mini-excavator.html"
    }
  ],
  "maxResults": 5,
  "maxPagesPerUrl": 5,
  "scrapeDetails": true,
  "includeImages": true,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Validated listing records in the default dataset.

## `dataset` (type: `string`):

Default dataset overview.

## `output` (type: `string`):

Outcome, counts, billing, warnings, and source URLs.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.machineryzone.com/used/1/mini-excavator.html"
        }
    ],
    "maxResults": 5,
    "maxPagesPerUrl": 5,
    "scrapeDetails": true,
    "includeImages": true,
    "maxConcurrency": 1,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/machineryzone-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 = {
    "startUrls": [{ "url": "https://www.machineryzone.com/used/1/mini-excavator.html" }],
    "maxResults": 5,
    "maxPagesPerUrl": 5,
    "scrapeDetails": True,
    "includeImages": True,
    "maxConcurrency": 1,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/machineryzone-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 '{
  "startUrls": [
    {
      "url": "https://www.machineryzone.com/used/1/mini-excavator.html"
    }
  ],
  "maxResults": 5,
  "maxPagesPerUrl": 5,
  "scrapeDetails": true,
  "includeImages": true,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call muhammadafzal/machineryzone-scraper --silent --output-dataset

```

## MCP server setup

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