# Bring a Trailer Auctions Scraper (`muhammadafzal/bring-a-trailer-auctions-scraper`) Actor

Scrape public live Bring a Trailer auction listings or enrich public listing URLs with structured auction and vehicle details.

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

## Pricing

from $10.00 / 1,000 auction records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## Bring a Trailer Auctions Scraper

> **Free-plan limit:** Apify free-plan runs can return at most **5 dataset records per run** from this Actor, even if you request more.

Export public Bring a Trailer auction data as clean JSON, CSV, Excel, XML, or RSS. The Actor can monitor the current live-auction page or extract specific public listing URLs, including completed listings.

It is designed for vehicle-market research, auction monitoring, valuation workflows, and data pipelines that need structured public BaT listing data without browser automation.

### What you can collect

Each dataset item represents one validated auction listing and can include:

- Listing ID, canonical URL, title, year, make, and model
- Live, sold, unsold, ended, or unknown auction status
- Current or final public bid, formatted bid, and currency
- Auction end timestamp and public bid count
- No Reserve, Premium, and repeat-listing flags
- BaT category IDs plus readable category names
- Country, country code, coordinates, and listing location label
- Thumbnail, public description, and optional JSON-LD vehicle details
- Scrape timestamp and record-level warnings

Fields that are not publicly available are returned as `null` or an empty array. The Actor never invents placeholder auction records: an unavailable or invalid listing produces a diagnostic summary and no billable result event.

### Input modes

#### Live-auction discovery

Leave `listingUrls` empty to read Bring a Trailer's public live-auction page. You can filter the currently available listings with `searchQuery`, keep only No Reserve listings, choose a sort order, and cap the output with `maxResults`.

```json
{
  "searchQuery": "Porsche 911",
  "maxResults": 25,
  "noReserveOnly": false,
  "sortBy": "endingSoonest",
  "includeDetails": true
}
```

`includeDetails` opens each selected listing page and adds public fields such as make, model, origin, location label, bid count, and JSON-LD. It is slower than the embedded live-auction feed, so leave it disabled when the summary fields are enough.

#### Direct listing URLs

Pass up to 100 public `https://bringatrailer.com/listing/.../` URLs to extract specific live or completed auctions. Duplicate URLs are processed once.

```json
{
  "listingUrls": [
    { "url": "https://bringatrailer.com/listing/1970-ferrari-365-gt-22-7/" }
  ],
  "maxResults": 10
}
```

For safety and predictable billing, other domains and non-listing BaT URLs are rejected. Direct URL mode does not use `searchQuery`, `noReserveOnly`, or live-page sorting because the URLs already define the requested records.

### Input reference

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `listingUrls` | array | `[]` | Public Bring a Trailer listing URLs; maximum 100 |
| `searchQuery` | string | `""` | Case-insensitive all-terms filter for current live listings |
| `maxResults` | integer | `10` | Maximum records to save, from 1 to 100; Apify free-plan runs are capped at 5 |
| `includeDetails` | boolean | `false` | Enrich selected live records from their public listing pages |
| `noReserveOnly` | boolean | `false` | Keep only current listings marked No Reserve |
| `sortBy` | string | `endingSoonest` | `endingSoonest`, `endingLatest`, `bidHighest`, or `bidLowest` |

### Example output

```json
{
  "recordType": "auction",
  "listingId": "121073054",
  "url": "https://bringatrailer.com/listing/1970-ferrari-365-gt-22-7/",
  "title": "1970 Ferrari 365 GT 2+2",
  "auctionStatus": "live",
  "isLive": true,
  "currentBid": 101000,
  "currentBidFormatted": "USD 101,000",
  "currency": "USD",
  "endsAt": "2026-09-09T18:53:00.000Z",
  "year": "1970",
  "make": "Ferrari",
  "model": "365 GT 2+2",
  "categories": [],
  "categoryNames": [],
  "noReserve": false,
  "bidCount": 18,
  "scrapedAt": "2026-09-03T10:00:00.000Z",
  "warnings": []
}
```

The default dataset holds auction records. The `OUTPUT` key-value-store record holds a run summary with the terminal status, record and charge counts, access diagnostics, warnings, runtime, and estimated primary-event cost.

### API example

```bash
curl -X POST 'https://api.apify.com/v2/acts/muhammadafzal~bring-a-trailer-auctions-scraper/runs' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"searchQuery":"Ferrari","maxResults":5,"includeDetails":true}'
```

After the run succeeds, download its default dataset through the Apify API or use an integration such as webhooks, Google Sheets, Make, or Zapier.

### Pricing and billing behavior

This Actor uses **pay-per-event** pricing. These are the current Apify Store event prices:

| Event | Price (USD) | When it is charged |
|---|---:|---|
| `apify-actor-start` | $0.006251 | Actor Start — Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). — Charged once per run. |
| `auction-record` | $0.014 | Auction Record — Charged once per schema-valid public Bring a Trailer auction record delivered. |

For Apify free-plan users, this Actor processes and delivers no more than 5 unique auction records per run, even when `maxResults` is higher. Paid-plan runs retain the requested `maxResults` limit, up to 100.

Apify platform usage for this Actor run is included alongside the event prices above; no separate per-run platform-usage fee is passed to users.

This covers Apify platform usage for this Actor run. Other Apify products or usage outside this Actor run may still follow your account plan.

### Reliability and responsible use

The Actor uses public pages only, bounded retries, request timeouts, small enrichment concurrency, output validation, deduplication, and explicit blocked/failed/empty run summaries. It does not log in, place bids, access private account data, solve access challenges, or bypass target controls.

Bring a Trailer can change its public markup at any time. A blocked or structurally changed response is reported instead of being converted into misleading data. Review the source site's terms and applicable law for your use case, and avoid overly frequent schedules.

This Actor is best for current-auction monitoring and known listing URLs. It is not a full-text archive search for every completed Bring a Trailer auction.

### Pricing

This Actor uses **pay-per-event** pricing. These are the current Apify Store event prices:

| Event | Price (USD) | When it is charged |
|---|---:|---|
| `apify-actor-start` | $0.00005 | Actor Start — Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). — Charged once per run. |
| `auction-record` | $0.003 | Auction Record — Charged once per schema-valid public Bring a Trailer auction record delivered. |

Apify platform usage for this Actor run is included alongside the event prices above; no separate per-run platform-usage fee is passed to users.

This covers Apify platform usage for this Actor run. Other Apify products or usage outside this Actor run may still follow your account plan.

# Changelog

This Actor's version history is a separate document: https://apify.com/muhammadafzal/bring-a-trailer-auctions-scraper/changelog.md

# Actor input Schema

## `listingUrls` (type: `array`):

Use for specific public Bring a Trailer listing pages. Example: https://bringatrailer.com/listing/1967-porsche-911-2/. These URLs may be live or completed listings.

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

Use only to filter the public live-auction page locally by title, summary, year, country, or category terms. Example: Porsche 911. It does not search BaT's completed-auction archive.

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

Request 1-100 auction records. Apify free-plan users are capped at 5 records per run; paid-plan runs may return up to the requested limit. One schema-valid record is one primary result event.

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

Use this when make, model, origin, bid count, listing status, and public JSON-LD product data are needed. Default false. Supplied listing URLs are always parsed in detail.

## `noReserveOnly` (type: `boolean`):

Use this to keep only live listings marked No Reserve. Default false. It does not filter supplied listing URLs.

## `sortBy` (type: `string`):

Use this to order live-page results before maxResults is applied. Default endingSoonest. It does not reorder supplied listing URLs.

## Actor input object example

```json
{
  "listingUrls": [],
  "searchQuery": "",
  "maxResults": 10,
  "includeDetails": false,
  "noReserveOnly": false,
  "sortBy": "endingSoonest"
}
```

# Actor output Schema

## `auctions` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/bring-a-trailer-auctions-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 = { "maxResults": 10 }

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/bring-a-trailer-auctions-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 '{
  "maxResults": 10
}' |
apify call muhammadafzal/bring-a-trailer-auctions-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,muhammadafzal/bring-a-trailer-auctions-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/fl0HrzR9cNhj67x8X/builds/t6qOVzBL31C5LPwGo/openapi.json
