# Agriaffaires Scraper — Used Farm Machinery Europe (`crawloop/agriaffaires-scraper`) Actor

Scrape Agriaffaires used farm machinery: tractors, harvesters, prices (HT), hours, power, tires, dealer info, images. Category or startUrls. Listings or details mode. Optional phones. Camoufox + Apify Residential for DataDome.

- **URL**: https://apify.com/crawloop/agriaffaires-scraper.md
- **Developed by:** [Andrej Kiva](https://apify.com/crawloop) (community)
- **Categories:** E-commerce, Other
- **Stats:** 2 total users, 1 monthly users, 75.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 scraped agriaffaires details

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Agriaffaires Scraper — Used Farm Machinery Europe

> **Disclaimer:** Unofficial integration for publicly accessible Agriaffaires listings. Not affiliated with, sponsored by, or endorsed by Agriaffaires, MB Diffusion, or Leboncoin. Trademarks belong to their respective owners.
>
> This Actor is provided **for informational and research purposes only** (market research, inventory monitoring, pricing workflows). You are solely responsible for ensuring your use complies with applicable laws (including GDPR/DSGVO), platform terms of use, and your organization's policies. Phone numbers are **off by default** and must only be processed with a lawful basis.
>
> No warranty is given as to accuracy, completeness, or continued availability of third-party data. Use at your own risk.

Scrape **used agricultural machinery** from Agriaffaires — tractors, harvesters, tillage, sprayers, livestock equipment, and more — into clean JSON on Apify. Built for European dealer intelligence, price benchmarking, and inventory monitoring.

Supports **category / filtered start URLs** and **direct listing pages**. Choose `listings` for fast card-level catalogs or `details` for full product pages with technical specs, tire wear, image galleries, and seller company context.

Uses **Camoufox** (anti-detect Firefox) inside Apify with **residential proxies** (FR recommended) to handle DataDome. No external unlocker service required.

### When to use this Actor

Use the **Agriaffaires Scraper** when you need:

- **Asking prices (HT)** and currency for used farm machinery across Europe
- **Technical attributes** — year, hours, power (ch / HP / kW), drive wheels, tire size and wear, serial / reference
- **Dealer context** — company name, type, store URL, member since, listing count
- **Geography** — country, region, department (including featured “À la Une” dealer cards)
- **Bulk category coverage** — paste any Agriaffaires search or category URL (apply filters on-site first)

Ideal for farm equipment dealers, market analysts, and data teams tracking the European used agricultural machinery market.

### Data pipeline

```
Input                              Mode                         Output
─────────────────────────         ────────────────────         ──────────────────────────

  Category / filtered URL    ──►   listings (fast cards)  ──►  price, year, hours, power, location
  Direct listing URL         ──►   details  (full PDP)   ──►  specs, tires, images, seller
                                                          ──►  phones (opt-in only)
```

### Key Features

- **Two extraction modes** — `listings` (category cards) or `details` (PDP + JSON-LD + specs table)
- **Ag specs** — hours, HP/kW, 4 RM drive, tire wear %, reference, condition, offer type
- **Seller block** — dealer name, type, account id, store link, contact names, languages
- **Location from cards** — standard localisation block and featured dealer logoPro fallback
- **Optional phone decode** — `includePhones` (default `false`); numbers embedded in HTML (`data-p` / `data-pdisplay`)
- **Camoufox + Apify Residential** — DataDome-aware session warmup and retries; prefer country `FR`

### Input Parameters

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `startUrls` | Array | sample tractors URL | Category, filtered search, or detail URLs. |
| `runMode` | String | `"listings"` | `"listings"` or `"details"`. Default listings keeps Store QA under 5 minutes. |
| `includePhones` | Boolean | `false` | Decode seller phones (details mode only). |
| `maxItems` | Integer | `5` | Max listings (`0` = unlimited). Raise for production. |
| `maxPagesPerUrl` | Integer | `1` | Pagination depth (`/occasion/{page}/…`). |
| `concurrencyLimit` | Integer | `1` | Parallel detail workers (kept low; browser session). |
| `proxyConfiguration` | Object | Residential | **Required** against DataDome — use Apify Residential, country FR. |

#### Input example

```json
{
  "startUrls": [
    { "url": "https://www.agriaffaires.com/occasion/1/tracteur-agricole.html" }
  ],
  "runMode": "listings",
  "includePhones": false,
  "maxItems": 50,
  "maxPagesPerUrl": 3,
  "concurrencyLimit": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "FR"
  }
}
```

### Output Format

Each row is pushed to the default dataset.

#### Details mode (enriched)

| Field | Description |
| :--- | :--- |
| `id`, `url`, `title` | Listing identifiers |
| `brand`, `model`, `category`, `breadcrumbs` | Machine identity |
| `priceHt`, `currency`, `priceStatus` | Asking price (HT) / on request |
| `year`, `hours`, `powerHp`, `powerKw`, `driveWheels` | Core machine facts |
| `frontTiresSize/Wear`, `rearTiresSize/Wear` | Tire data when published |
| `reference`, `condition`, `offerType`, `serialNumber` | Listing metadata |
| `country`, `region`, `department`, `location` | Geography |
| `sellerName`, `sellerType`, `sellerAccountId`, `sellerStoreUrl` | Dealer company |
| `memberSince`, `sellerTotalListings`, `contactPersons` | Seller context |
| `phoneNumbers` | Only when `includePhones=true` |
| `description`, `specs`, `images` | Free text, spec map, gallery |

#### Listings mode (cards)

Card-level fields include `id`, `url`, `title`, `brand`, `model`, `category`, `priceHt`, `currency`, `priceStatus`, `year`, `hours`, `powerHp`, `location`, `country`, `region`, `department`, `latitude`, `longitude`, `imageUrl`, `imageCount`, `isTop`.

#### Example record

```json
{
  "id": "40838192",
  "title": "Fiat / Fiatagri 955C",
  "brand": "Fiat / Fiatagri",
  "model": "955C",
  "category": "Tracteur agricole",
  "year": 2008,
  "driveWheels": "4 RM",
  "frontTiresWear": 25,
  "rearTiresWear": 30,
  "reference": "A15907",
  "currency": "EUR",
  "priceStatus": "on_request",
  "country": "Italie",
  "sellerName": "Volatile Bernardo srl",
  "sellerType": "Concessionnaire / Distributeur",
  "sellerAccountId": "153018"
}
```

### Typical Workflow

1. Open a filtered category on Agriaffaires (brand, year, country, price).
2. Paste the URL into `startUrls`.
3. Set `runMode` to `listings` for a fast index or `details` for full enrichment.
4. Enable Apify Residential proxies with country `FR`.
5. Leave `includePhones` off unless you have a lawful basis to process phone numbers.
6. Export the dataset as JSON, CSV, or Excel from the Apify run.

### Limitations

- Agriaffaires is protected by **DataDome**. Datacenter IPs are often blocked; use **Apify Residential** (FR).
- Browser sessions (Camoufox) cost more CU and time than pure HTTP scrapers; expect retries when challenges appear.
- Field coverage depends on what the seller published (hours / power / tires may be missing).
- Multi-language labels are normalized best-effort from FR / EN / DE tables.
- Phone extraction is opt-in and details-mode only.

# Actor input Schema

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

Category, filtered search, or listing detail URLs on agriaffaires.com (and country TLDs). Example: https://www.agriaffaires.com/occasion/1/tracteur-agricole.html or a detail page /occasion/{category}/{id}/{slug}.html. Filters (brand, year, price, country) should be applied on the site, then paste the resulting URL here.

## `runMode` (type: `string`):

listings = fast card-level data from category pages. details = visit each listing for full specs, images, seller, and optional phones. Default is listings so Apify Store QA finishes within the 5-minute health-check limit (Camoufox + DataDome).

## `includePhones` (type: `boolean`):

When true and runMode is details, decode seller phone numbers embedded in the listing HTML. Off by default (GDPR / responsible use). You are responsible for lawful processing of any personal data.

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

Maximum listings to return. 0 = unlimited. Keep low for Store QA (5-minute limit); raise for production runs.

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

Pagination depth per category URL. Page number is in the path (/occasion/{page}/slug.html). 0 = until exhausted.

## `concurrencyLimit` (type: `integer`):

Parallel detail-page workers. Keep low (1–3) — Agriaffaires uses DataDome / Camoufox.

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

Residential proxies required (DataDome). Prefer country FR.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.agriaffaires.com/occasion/1/tracteur-agricole.html"
    }
  ],
  "runMode": "listings",
  "includePhones": false,
  "maxItems": 5,
  "maxPagesPerUrl": 1,
  "concurrencyLimit": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FR"
  }
}
```

# Actor output Schema

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

Dataset of scraped Agriaffaires listings (price HT, year, hours, power, seller, images).

# 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.agriaffaires.com/occasion/1/tracteur-agricole.html"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawloop/agriaffaires-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.agriaffaires.com/occasion/1/tracteur-agricole.html" }] }

# Run the Actor and wait for it to finish
run = client.actor("crawloop/agriaffaires-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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.agriaffaires.com/occasion/1/tracteur-agricole.html"
    }
  ]
}' |
apify call crawloop/agriaffaires-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=crawloop/agriaffaires-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/hryEaMr5XL632r9Ey/builds/lWmB4OS4XY09VQQaj/openapi.json
