Bring a Trailer Car Scraper
Pricing
from $2.98 / 1,000 results
Bring a Trailer Car Scraper
Collect Bring a Trailer auction records, including live and completed listings, with title, status, year, make, model, bids, prices, mileage, seller and location. Search by keyword, use model pages to find listings, or provide individual listing URLs. No login or API key is required.
Pricing
from $2.98 / 1,000 results
Rating
0.0
(0)
Developer
Axiom Works
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
6 days ago
Last modified
Categories
Share
Bring a Trailer Auctions Scraper
Returns: one row per auction with title, status, year, currentBid, soldPrice, mileage, engine and transmission.
Input: {"searchTerms": ["porsche 911"], "auctionStatus": "completed", "result": "sold", "maxItems": 10}
Best for: collector-car price history, tracking live auctions that are about to end, and building dealer or buyer research lists from public Bring a Trailer listings.
{"id": "123054328","sourceUrl": "https://bringatrailer.com/listing/1996-porsche-911-turbo-222/","title": "1996 Porsche 911 Turbo 6-Speed","status": "sold","soldPrice": 239000,"currency": "USD","engine": "Turbocharged 3.6L Flat-Six","transmission": "Six-Speed Manual Transaxle"}
What does Bring a Trailer Auctions Scraper do?
This Bring a Trailer scraper turns the public auction pages of bringatrailer.com into a clean dataset. Think of it as a Bring a Trailer API for people who need rows instead of web pages. It collects live auctions that are still running and completed auctions with their final result, for any make, model or keyword.
You can start from a keyword such as "porsche 911", from a make or model page such as /porsche/911/, from the live auctions page, from a results search URL, or from individual listing URLs. For every auction the Actor returns the headline facts (title, year, status, bids, sold price) and, when listing details are switched on, the facts that only live on the listing page: make, model, bid count, mileage, VIN, seller, location, lot number, views, watchers and comments.
It works without a login, an API key or a browser. The data comes from public pages and the public listings endpoint that the site itself uses, so runs need no browser. The Actor is not affiliated with or endorsed by Bring a Trailer.
Typical jobs:
- Pull the sold history of one model to see how prices moved over time.
- Watch live auctions for a model and see the current bid, bid count and end time.
- Compare reserve-not-met results with sold results for the same car.
- Export seller usernames and locations to see who lists which cars.
What data can you get?
Each row has the fields below. Fields that need the listing page are empty when you turn off includeDetails. Live-only fields such as latitude and longitude are empty for completed auctions.
| Field | Type | Description |
|---|---|---|
| id | string | Stable record id, the Bring a Trailer post id as text |
| sourceUrl | string | Listing page the record came from |
| listingId | integer | Bring a Trailer post id |
| title | string | Listing title with HTML entities decoded |
| status | string | live, sold, reserve_not_met, withdrawn or ended |
| year | integer | Model year taken from the listing data or title |
| make | string | Vehicle make from the listing page |
| model | string | Bring a Trailer model label, for example Porsche 991 911 Targa 4 GTS |
| era | string | Decade label such as 2010s |
| origin | string | Country-of-origin group such as German |
| categories | array | Category labels, often empty |
| currentBid | number | Live: current high bid. Ended: final high bid |
| soldPrice | number | Final sale price from the result text when status is sold (usually equals currentBid; differs when a post-auction deal changed the price), otherwise empty |
| currency | string | Currency code (USD, EUR or GBP), amounts are never converted |
| bidCount | integer | Number of bids |
| highBidder | string | Public username of the high bidder or buyer |
| commentCount | integer | Number of comments on the listing |
| viewCount | integer | Listing views |
| watcherCount | integer | Number of watchers |
| mileage | integer | Odometer number parsed from the listing details |
| mileageText | string | The raw mileage line, for example 32k Miles or TMU |
| vin | string | Chassis or VIN line from the listing details |
| location | string | Seller location |
| countryCode | string | Two-letter country code |
| seller | string | Public seller username |
| sellerUrl | string | Seller profile link (the profile page is never fetched) |
| sellerType | string | Private Party or Dealer |
| lotNumber | integer | Lot number |
| noReserve | boolean | True for no-reserve auctions |
| endDate | string | ISO 8601 end time, scheduled for live and actual for ended |
| resultText | string | Result line for ended auctions, such as a sold-for line with the amount and date |
| engine | string | First matching engine specification line from Listing Details, or null. |
| transmission | string | First matching transmission specification line from Listing Details, or null. |
| listingDetails | array | The bullet list from the Listing Details block |
| thumbnailUrl | string | Thumbnail image link |
| excerpt | string | Short listing summary |
| imageUrls | array | Full-size gallery photo URLs (needs includeDetails) |
| imageCount | integer | Number of gallery photos found |
| description | string | Seller summary paragraph from the listing page (needs includeDetails) |
| latitude | number | Live auctions only |
| longitude | number | Live auctions only |
| scrapedAt | string | ISO timestamp of the scrape |
The mileage number keeps the unit of the listing. A line such as "12k Kilometers Shown" gives 12000 and the text stays in mileageText, so you can tell kilometers from miles.
Engine and transmission are separate nullable columns copied verbatim from the first matching Listing Details line. They preserve the seller's wording, including modifications; they are not decoded from the VIN or inferred from the title. Location and seller type also support the older listing essentials layout. Engine matching accepts ordinary and typographic hyphens while preserving the original listing text. Unrecognized or absent specifications stay null. The original listingDetails array remains available, and includeDetails=false leaves both columns null. No additional requests or enrichment service are used.
How to use Bring a Trailer Auctions Scraper
- Open the Actor in Apify Console and go to the Input tab.
- Enter one or more search terms, or paste start URLs. If you enter neither, the Actor searches for "porsche 911" so a first run always returns data.
- Choose which auctions you want: completed, live, or both.
- Optionally filter by result, time frame and model year range, and pick a sort order.
- Set Max items. The default is 50.
- Click Start. Results appear in the Output tab and can be downloaded as JSON, CSV or Excel.
A few practical tips:
- Start small. Ten items finish in well under a minute and show you the exact shape of the data.
- For bulk price history, turn off
includeDetails. The run then needs only one request per 60 auctions instead of one per auction. - Use make or model pages (such as
/mercedes-benz/190sl/) when you want every auction for one model without guessing the right keyword. - For monitoring, schedule the Actor with
auctionStatusset to live and compare runs bylistingId.
Speed matters here: the Actor keeps to about one request per second to be polite to the site. Fetching the listing page for each auction therefore takes about one second per item, so 1,000 items with details take roughly 17 minutes. List-only runs are much faster.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
| searchTerms | array of strings | empty | Keywords such as "porsche 911". Completed auctions use the site search, live auctions need every word to appear in the title or description. |
| startUrls | array | empty | Listing, make, model, category, live list or results search URLs. Plain strings and {"url": ...} objects both work. |
| auctionStatus | string | completed | completed, live or all (live first, then completed) |
| result | string | any | Completed only: sold, unsold (reserve not met) or any |
| timeFrame | string | all | Completed only: all, 7D, 30D, 1Y, 2Y or 5Y |
| yearFrom | integer | none | Earliest model year |
| yearTo | integer | none | Latest model year |
| sortBy | string | recent | recent, oldest, highestBid or popular |
| vehiclesOnly | boolean | true | Skip parts, wheels and automobilia |
| includeDetails | boolean | true | Fetch each listing page for the detail fields |
| maxItems | integer | 50 | Total auctions to return, 1 to 100000 |
| maxConcurrency | integer | 3 | Parallel listing page fetches, 1 to 10 |
| proxyConfiguration | object | no proxy | Optional Apify Proxy settings |
Supported start URL shapes:
| URL | Result |
|---|---|
https://bringatrailer.com/listing/{slug}/ | That single listing, whatever its status |
https://bringatrailer.com/porsche/911/ | Auctions for that model or make, honouring auctionStatus |
https://bringatrailer.com/auctions/ | All live auctions |
https://bringatrailer.com/auctions/results/?search=land%20cruiser&result=sold&timeFrame=1Y | Completed auctions for that search |
Unsupported URLs are skipped with a warning and listed in the RUN_SUMMARY record.
Example input:
{"searchTerms": ["bmw m3", "toyota supra"],"auctionStatus": "completed","result": "sold","yearFrom": 1985,"yearTo": 2002,"sortBy": "highestBid","maxItems": 20}
When you pass several terms or URLs, the same auction is only returned once. Max items is a total across everything you provide.
Output
Results are stored in the default dataset, one item per auction. The overview view shows title, status, year, make, model, bids, price, mileage, location, seller and end date. Here is a live auction from a real run:
{"id": "119269832","sourceUrl": "https://bringatrailer.com/listing/1982-amc-eagle-13/","listingId": 119269832,"title": "1982 AMC Eagle Standard Wagon","status": "live","year": 1982,"make": "AMC","model": "AMC Eagle","era": "1980s","origin": "American","categories": ["Station Wagons", "Truck & 4x4"],"currentBid": 6666,"soldPrice": null,"currency": "USD","bidCount": 7,"highBidder": "r32fan","mileage": 111000,"mileageText": "111k Miles Shown","location": "Elmsford, New York 10523","seller": "JD65DartGT","sellerType": "Private Party","lotNumber": 266403,"noReserve": true,"endDate": "2026-10-03T17:03:00.000Z"}
Two extra records are written to the key-value store. RUN_SUMMARY lists, for every input, how many auctions were found, pushed and skipped as parts, plus any warnings. If you used the verification option, SNAPSHOTS holds the source text for the first records.
How much does it cost?
The Actor is charged per result: you pay for each auction row it returns, and nothing for requests that return no rows. See the Pricing tab on the Actor page for the current rate. Apify's free plan credit is usually enough for a first test run.
To keep cost down, set Max items to what you need, and turn off includeDetails when list-level fields are enough.
Use with AI agents (MCP)
You can call this Actor from any MCP-compatible assistant through the Apify MCP server. Use this configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=axiomworks/bringatrailer-auctions-scraper"}}}
Example prompts:
- "Get the last 30 sold Porsche 911 auctions on Bring a Trailer from the past year and tell me the median sold price."
- "List the live Ford Bronco auctions on Bring a Trailer with their current bid and end time."
- "Find reserve-not-met results for the Mercedes-Benz 190SL and show the high bids."
Integrations and API
Run the Actor from code with the Apify API clients.
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("axiomworks/bringatrailer-auctions-scraper").call(run_input={"searchTerms": ["porsche 911"],"auctionStatus": "completed","result": "sold","maxItems": 20,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item["soldPrice"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('axiomworks/bringatrailer-auctions-scraper').call({searchTerms: ['ford bronco'],auctionStatus: 'live',maxItems: 15,});const { items } = await client.dataset(run.defaultDatasetId).listItems();items.forEach((i) => process.stdout.write(`${i.title}: ${i.currentBid}\n`));
cURL:
curl -X POST "https://api.apify.com/v2/acts/axiomworks~bringatrailer-auctions-scraper/run-sync-get-dataset-items" \-H "Authorization: Bearer $APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"searchTerms": ["porsche 911"], "maxItems": 10}'
The Actor also works with Apify schedules, webhooks, and integrations such as Make, Zapier and Google Sheets, so you can push new sold prices into a spreadsheet every day.
FAQ
Does it need a proxy? Normally no. The Actor works from a datacenter address with a modest request rate. If the site answers with a block page repeatedly, the Actor switches to Apify datacenter proxy by itself. You can also turn on a proxy in the input.
Why is a run with details slower? Make, model, bid count, mileage, seller, location and lot number exist only on the listing page, so the Actor fetches one page per auction at about one request per second. Turn off includeDetails for a fast list-level run.
What does an empty result mean? No auction matched. The run still succeeds, the status message names the search, and RUN_SUMMARY records the details. Check the spelling of the term or loosen the filters.
Why are some fields empty? Not every listing has every detail. Mileage can be TMU (true mileage unknown), VIN may be absent on old cars, and high bidder is empty when there are no bids or the reserve was not met. Live-only fields stay empty for completed auctions.
Are amounts converted to dollars? No. Amounts are in the listing's own currency, shown in the currency field. Most listings use USD, a few use EUR or GBP.
Why did I get fewer items than Max items? Only that many auctions matched your filters, or listing pages were not found. Direct listing URLs that no longer exist are skipped.
Does it include parts and wheels? Not by default. vehiclesOnly drops parts and wheels lots. Motorcycles and boats are Bring a Trailer auctions and are kept.
Can I get bid-by-bid history or comments? No. The Actor returns one row per auction with bid, view, watcher and comment counts, not the individual bids or comment text.
Does it scrape member profiles? No. Seller and bidder usernames are shown as they appear on the listing, and the profile pages are never requested.
Is it legal to scrape Bring a Trailer?
The Actor collects only data that any visitor can see without logging in, and it keeps to a low request rate. It does not log in, solve CAPTCHAs or reach private data. The output contains public usernames shown on the listings, and no emails or phone numbers.
Whether your use is lawful depends on your jurisdiction, your purpose and the site's terms of use, which may restrict automated collection. Check the terms yourself, avoid republishing copyrighted photos or descriptions, and handle any personal data according to the privacy rules that apply to you, such as GDPR. This is general information, not legal advice.
Feedback
Found a missing field, a wrong value or a page shape that does not work? Open an issue from the Actor page in Apify Console, with the input you used and the listing URL involved. Reports with a concrete example are the quickest to fix.