# Bring a Trailer Scraper — Auction Results and Sold Prices (`s-r/bringatrailer-scraper`) Actor

Get Bring a Trailer auction results as rows: sold prices, last bids, year, make, model, end date, lot country and photo for completed and live auctions. Built for dealers, insurers and appraisers who need comparable classic car sales.

- **URL**: https://apify.com/s-r/bringatrailer-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** E-commerce, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 auction listings

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/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 Auction Results Scraper

Bring a Trailer auction results in one dataset: this Bring a Trailer Scraper collects completed and live auctions with sold prices, last bids, model years, makes, models, currencies, end dates, lot countries and photos. Use it to build comparable classic car sales for valuations, monitor current auctions or compare sold vehicles with lots that did not meet reserve.

Every result is one public auction lot. The Actor supports a free search term or separate manufacturer and model fields, completed auction outcomes, recent time periods, model year bounds and a result limit. Results are delivered to your Apify dataset so you can export them as JSON, CSV, Excel or another supported dataset format.

### Who uses Bring a Trailer auction results

- **Classic and collector car dealers** price stock against recent sold results for the same model and era, and check how often comparable cars fail to meet reserve.
- **Insurers and agreed-value underwriters** document the market value of a vehicle with dated, public sale prices instead of guide estimates.
- **Appraisers and valuation services** pull every sold Porsche 911, Jaguar E-Type or Ferrari in a period and attach the original listing URL to each comparable.
- **Market analysts and journalists** follow how sold prices, bids and the share of unsold lots move over months for a make or model.
- **Buyers and sellers** watch live auctions closing soon and compare the current bid with what similar cars sold for.

### What the Bring a Trailer Scraper collects

Completed auctions include vehicles that sold, auctions whose reserve was not met and withdrawn lots. Live auctions contain the currently visible listings and their scheduled closing times. The title, lot identifier and public listing URL make it possible to revisit each result and inspect its description before using it as a comparable sale.

The completed collection can also contain memorabilia, components and accessories. A keyword search for a manufacturer does not guarantee that every result is a complete vehicle. Check the title and the year, make and model fields before including a row in a valuation analysis. Names and model descriptions follow the source title; they are not a separate vehicle specification catalogue.

### Input

Start with a search such as:

```json
{"query":"porsche 911","status":"completed","result":"sold","limit":60}
```

This search was used during source research. It selects completed sold auctions matching the words Porsche and 911. For a manufacturer and model search, you can instead supply `make` and `model`; the Actor combines them with any `query` you also provide.

| Field | Default | Meaning |
|---|---|---|
| `query` | Empty | Free search text, maximum 200 characters |
| `make`, `model` | Empty | Manufacturer and model text added before the query |
| `status` | `completed` | `completed` or `live` |
| `result` | `all` | `all`, `sold` or `unsold`, for completed auctions |
| `period` | `all` | `all`, `7d`, `30d`, `1y`, `2y` or `5y` |
| `year_min`, `year_max` | Unset | Inclusive model year bounds, 1800–2100 |
| `sort` | `recent` | `recent`, `oldest`, `highest_bid` or `popular` |
| `limit` | `100` | Requested auction count, 1–10,000 |

Live results are always sorted by scheduled end time, soonest first. The `result` and `period` options apply to completed auctions and produce a warning when supplied for live auctions. Live keyword searches require all supplied words to appear in the title or the source's searchable listing text. Year filters exclude live lots whose year is unavailable.

### Output

The dataset includes the listing identifier, public URL, decoded title, primary image URL, year, make, model, auction status, bid, sale price, currency, end time and lot country. Each row also carries `source`, `fetched_at` and `position`, making it easier to combine exports and trace the collection time.

`auction_status` is `sold`, `reserve_not_met`, `withdrawn` or `live`. The `sold` field is true for a sale, false for an unsold or withdrawn lot, and null while the auction remains live. `sale_price` is populated only for sold lots and follows the amount explicitly displayed as “Sold for”. It excludes buyer fees. That amount may differ from the last bid, for example when a sale is agreed after bidding closes.

The research response for [this 1999 Ferrari 360 Modena](https://bringatrailer.com/listing/1999-ferrari-360-modena-70/) displayed a USD 82,000 last bid and “Sold for USD $85,000”. The Actor therefore preserves `high_bid: 82000`, `price: 82000` and `sale_price: 85000`, instead of treating the bid as the final sale price.

`price` and `high_bid` are the last or current bid in the row's `currency`. For live auctions, `sale_price` is null. For unsold and withdrawn lots, an existing bid is retained without implying that the vehicle sold. No currency conversion is performed: USD, EUR and GBP amounts remain in their original currencies.

`country` describes the US marketplace. `location_country` describes the country where the lot is located, which may be different. `ended_at` is the completed auction end time or the scheduled end time of a live auction. All timestamps use UTC. `no_reserve`, `premium` and `bat_alumni` preserve the corresponding auction flags.

#### Example output: Bring a Trailer auction results

Two real rows from collections on 5 October 2026. A sold lot, from the search `{"query":"ferrari","result":"sold","period":"30d","limit":10}`:

```json
{
  "source": "bringatrailer-scraper",
  "fetched_at": "2026-10-05T21:55:24.814Z",
  "country": "US",
  "listing_id": "123130331",
  "url": "https://bringatrailer.com/listing/1999-ferrari-360-modena-70/",
  "title": "1999 Ferrari 360 Modena",
  "price": 82000,
  "currency": "USD",
  "brand": "Ferrari",
  "image_url": "https://bringatrailer.com/wp-content/uploads/2026/09/JCZ7373-scaled-copy-2026-09-28-43z-08935.jpg",
  "position": 1,
  "year": 1999,
  "make": "Ferrari",
  "model": "360 Modena",
  "auction_status": "sold",
  "sold": true,
  "sale_price": 85000,
  "high_bid": 82000,
  "price_text": "USD $82,000",
  "ended_at": "2026-10-05T20:37:24.000Z",
  "location_country": "US",
  "no_reserve": false,
  "premium": false,
  "bat_alumni": false,
  "excerpt": "This Grigio Titanio 1999 Ferrari 360 Modena has 37k miles and is powered by a 3.6-liter V8 that received a timing belt service in 2026. ..."
}
```

And a lot whose reserve was not met, from the search `{"result":"unsold","limit":10}`. The bid is kept, `sale_price` stays null:

```json
{
  "listing_id": "122119000",
  "url": "https://bringatrailer.com/listing/1997-aston-martin-db7-volante-9/",
  "title": "1997 Aston Martin DB7 Volante",
  "year": 1997,
  "make": "Aston Martin",
  "model": "DB7 Volante",
  "auction_status": "reserve_not_met",
  "sold": false,
  "sale_price": null,
  "high_bid": 18620,
  "price": 18620,
  "currency": "USD",
  "ended_at": "2026-10-05T21:14:42.000Z",
  "location_country": "US"
}
```

The `excerpt` is shortened here; the dataset holds the full text. Every row also carries the image URL and the three auction flags.

### Bring a Trailer scraper compared with other sources

- **The Bring a Trailer website** shows auction results page by page for people. It has no public export or API for collecting hundreds of results into a spreadsheet.
- **Valuation guides and price trackers** publish averages and estimates per model. They are useful context, but an appraiser or insurer often needs the individual sales behind a number, with a date and a link to the lot.
- **Copying results by hand** works for five cars, not for every sold 911 of the last two years. It also makes it easy to mistake the last bid for the sale price.
- **Writing your own scraper** means handling pagination, duplicates, HTML entities, currencies and the difference between a bid and a negotiated sale yourself.
- **Other Bring a Trailer scrapers in the Store** differ in scope and price model; some also open every detail page for VIN or mileage at a higher price per row. This one focuses on listing rows with an explicit sale price, and you pay only per delivered auction, with no start fee.

### Collection limits and completeness

A completed search can expose at most 10,000 rows for one filter combination, even if the source reports many more matches. Narrow the recency or model year bounds to collect different portions of the history. `total_results` is the source matching count, while `window_capped` indicates that the completed result window is limited.

Large Actor runs continue automatically in smaller portions. Dataset rows are deduplicated by their auction identifier. The output record and summary retain warnings when a collection cannot finish, and a remaining `next_cursor` indicates a resumable collection. A changing auction catalogue can affect which rows are visible between requests; the result is a collection of observations, not a historical database snapshot.

### Pricing

Pricing is per delivered auction listing. The list price is USD 0.004 per listing (USD 4 per 1,000 auction results); the Actor's pricing tab always shows the active rate. There is no separate start event in this Actor's charge map. Empty searches and requests that return no usable auction listings incur no listing charge. Each delivered row is counted once after collection and deduplication.

Non-paying Apify users receive at most ten dataset rows per run. A larger requested `limit` is capped before collection for those users. Paying users can request the full supported result range, subject to the source's matching count and search window. The run summary records delivered rows and collection limitations so that a short collection remains visible.

### FAQ

#### Can I use this to find comparable classic car sales?

Yes. Select `status: completed` and `result: sold`, then filter by model, year and recency. Use `sale_price` and `currency` for the observed sale amount. Inspect the original lot description before considering condition, specification and provenance comparable.

#### Does an unsold auction have a sale price?

No. `sale_price` is null when the reserve was not met or the lot was withdrawn. A last bid can still be present in `price` and `high_bid`; that bid is not evidence of a sale.

#### Why are year, make or model sometimes null?

Completed listings rely on the title for those fields. Parts, signs and other memorabilia often have no vehicle year or manufacturer directly after a year. The Actor preserves unknown fields as null rather than guessing a vehicle identity.

#### Are VIN, mileage and seller details included?

This version collects listing rows. It does not enrich every lot from its detail page, so VIN, mileage, seller identity and full bid histories are outside the promised output.

#### Can I download the entire auction history in one run?

A single completed filter combination is limited to 10,000 visible results. Split a larger research collection into narrower year or recency searches and deduplicate identifiers across your exported datasets.

#### Does the sale price include the buyer's fee?

No. `sale_price` is the amount displayed as "Sold for" on the lot, without the buyer's premium. Add the fee yourself if your valuation needs the total cost to the buyer.

#### Can I track live auctions?

Yes. Set `status: live` to get the currently running auctions sorted by closing time, soonest first. `sold` is null and `sale_price` is empty until the auction has ended; run the same search later with `status: completed` to collect the outcomes.

#### Which currencies appear in the results?

Most lots are in USD, but auctions can also run in EUR or GBP. The Actor never converts amounts: compare rows in the same `currency`, or convert them with your own exchange rate for the end date.

# Actor input Schema

## `query` (type: `string`):

Free search text. Combined after make and model; maximum 200 characters.

## `make` (type: `string`):

Manufacturer name, such as Porsche. Added before model and query.

## `model` (type: `string`):

Model name, such as 911. Added after make.

## `status` (type: `string`):

Completed auctions or all current live auctions.

## `result` (type: `string`):

Completed auction outcome. Ignored for live auctions with a warning.

## `period` (type: `string`):

Completed auction recency. Ignored for live auctions with a warning.

## `sort` (type: `string`):

Completed auction order. Live auctions always close soonest first.

## `year_min` (type: `integer`):

Inclusive model year bound. year_min must not exceed year_max.

## `year_max` (type: `integer`):

Inclusive model year bound. year_min must not exceed year_max.

## `limit` (type: `integer`):

Total requested auctions. Large collections return next_cursor; the Apify Actor follows it automatically. Maximum source window is 10,000 per completed search.

## `cursor` (type: `string`):

Opaque continuation returned as next_cursor. Keep the original search filters and limit when resuming.

## Actor input object example

```json
{
  "status": "completed",
  "result": "all",
  "period": "all",
  "sort": "recent",
  "limit": 100
}
```

# Actor output Schema

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

One row per delivered auction lot.

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

Delivered rows, warnings and billing status.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/bringatrailer-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("s-r/bringatrailer-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 '{}' |
apify call s-r/bringatrailer-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/bringatrailer-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/YH91t5DjNQ29kG6XZ/builds/ftDTMDrGMMtwZ1QVy/openapi.json
