# AutoTrader.ca Price Drop Monitor & Car Scraper (`fayoussef/autotrader-ca`) Actor

Monitor AutoTrader Canada searches and get only new listings, price drops and sold cars since the last run, with previous price and price history. Schedule it daily. Or scrape every listing: price, VIN, mileage, specs, dealer phone and photos.

- **URL**: https://apify.com/fayoussef/autotrader-ca.md
- **Developed by:** [Youssef Farhan](https://apify.com/fayoussef) (community)
- **Categories:** Automation, E-commerce, Developer tools
- **Stats:** 69 total users, 1 monthly users, 100.0% runs succeeded, 3 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.45 / 1,000 results

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

## AutoTrader.ca Price Drop Monitor and Car Scraper

Track AutoTrader Canada listings and get only what changed: **new listings, price drops, and sold or removed vehicles**, each with the previous price, the size of the drop, and a price history. Schedule it daily and stop re-downloading the same thousand cars to find the three that moved.

Need everything instead? Switch the monitor off and it is a full AutoTrader.ca scraper: price, mileage, VIN, specs, dealer details, and photos from any search as JSON, CSV, or Excel. No coding required: paste a search URL, or build your search with 30+ built-in filters.

### What does this AutoTrader.ca monitor do?

It watches any AutoTrader.ca search (a pasted URL or the built-in filter form) and runs in one of two modes:

- **Monitor mode:** compares the search with the previous run and outputs only the changes: new listings, price drops, price increases, and sold or removed vehicles. Built for a daily schedule.
- **Scraper mode (monitor off):** outputs every listing in the search, with **127 fields per vehicle**, including numeric price and mileage values that are ready for analysis without cleanup.

Both modes read the JSON that AutoTrader.ca embeds in its own pages instead of scraping HTML, so records stay complete and rarely break when AutoTrader changes its page layout.

#### At a glance

| | |
|---|---|
| **Source** | autotrader.ca (cars, RVs, bikes, boats, trailers, trucks, and more) |
| **Fields per vehicle** | 127 (about 85 populate on a typical dealer listing) |
| **Monitor mode** | New listings, price drops, price increases, sold or removed vehicles since the last run, with price history |
| **Best run as** | A daily schedule (monitor), or a one-off run (full scrape) |
| **Input** | AutoTrader.ca search URL, direct listing URL, or the built-in filter form |
| **Filters** | 30+, including make, model, price, year, mileage, body type, fuel, features, and location |
| **Output** | JSON, CSV, Excel, XML, JSONL |
| **Proxies** | Included and automatic, no setup and no Apify Proxy subscription needed |
| **Coding needed** | None |

### How to track AutoTrader.ca price drops in 4 steps

1. **Choose your vehicles.** Paste an AutoTrader.ca search URL into **Start URLs**, or leave it empty and fill in the **Search filters** section instead.
2. **Turn on Price-drop monitor.** Pick which changes to report and, optionally, a minimum price change.
3. **Save it as a task and schedule it.** Daily is typical. The first run saves the baseline; every later run returns only what changed.
4. **Get notified (optional).** Add a Slack, email, or webhook integration to the task so each run's changes reach you.

Just want every listing once? Leave the monitor off, set **Max results** if you want an exact number, and click Start. Results download as JSON, CSV, or Excel.

### Price-drop and new-listing monitor

Turn on **Price-drop monitor** and schedule the run (daily is typical). Every run compares the search with the previous run and outputs one row per change:

| `change_type` | What happened |
|---|---|
| `new` | The listing appeared since the last run |
| `price_drop` | The asking price went down |
| `price_increase` | The asking price went up (off by default) |
| `removed` | The listing is gone from AutoTrader.ca: sold, expired, or taken down |
| `baseline` | First run only: the current listings, when **Export all listings on the first run** is on |

Each change row carries the full vehicle record (VIN, specs, dealer, photos) plus:

- `previous_price_cad`, `price_change_cad`, `price_change_pct` for price changes
- `price_history`, every price the listing has had while monitored, with dates
- `first_seen_at` and `days_tracked`, so you can see how long a car sat before it dropped or sold
- `watchlist` and `change_detected_at`

**How it stays fast and cheap.** AutoTrader search pages already show every listing's price, so the monitor reads the search pages (100 listings each) and only opens the listings that changed. A search of 650 vehicles is checked in about 7 requests instead of 650. Unchanged vehicles are never output, so you are not billed for them.

**Sold detection is careful.** A listing that leaves the search is checked directly before it is reported as removed. If its page still loads (for example the price moved outside your price filter), it is not reported. Removals are only judged when every page of the search was read, so keep monitored searches under the 4,000 results AutoTrader shows per search. Narrow by make, model, price band or postal code if needed.

**Example monitor input:**

```json
{
  "monitor_mode": true,
  "makes": ["Toyota"],
  "models": ["RAV4"],
  "conditions": ["used"],
  "postal_code": "M5V 3L9",
  "radius_km": "100",
  "report_changes": ["new", "price_drop", "removed"],
  "min_price_change_cad": 500
}
```

**Useful settings:**

- **Changes to report**: pick any of new, price drops, price increases, and sold or removed.
- **Minimum price change (CAD / %)**: skip small adjustments, for example only drops of $1,000 or 5% and more.
- **Export all listings on the first run**: start with the full picture, or switch it off to only save the baseline.
- **Watchlist name**: optional. Each search keeps its own history automatically; name one to run two watchlists on the same search.

The history lives in a key-value store named `autotrader-ca-monitor-...` in your own Apify account, and each run also writes a `MONITOR_SUMMARY` record with the counts. To get alerts, add a Slack, email or webhook integration to the scheduled task.

### Two ways to tell it what to scrape

Point the scraper at a URL **or** use the built-in filters.

**Start URLs win.** If you enter anything in Start URLs, the Search filters section is ignored for that run and a note appears in the log. To search by filters, leave Start URLs empty.

#### Option 1: Paste an AutoTrader.ca search URL

Set your filters on autotrader.ca, copy the address bar, and paste it into **Start URLs**. Direct listing URLs (`/offers/...` or `/a/...`) also work and skip straight to that vehicle, in scraper mode only: the monitor watches searches, not single listings.

```json
{
  "start_urls": [
    { "url": "https://www.autotrader.ca/cars/on/toronto/?rcp=100&rcs=0&srt=35" }
  ],
  "max_items": 500
}
```

#### Option 2: Use the filter form (no URL needed)

Fill in the **Search filters** section and the scraper builds the matching AutoTrader search for you, exactly as if you had set the filters on the site.

```json
{
  "makes": ["Audi"],
  "models": ["A4"],
  "conditions": ["used"],
  "price_from": 10000,
  "price_to": 40000,
  "model_year_from": 2015,
  "body_types": ["sedan", "wagon"],
  "transmission": ["automatic"],
  "equipment": ["backup-camera"],
  "postal_code": "M5V 3L9",
  "radius_km": "400",
  "sort_by": "price"
}
```

Filters combine. Every one you add narrows the results further.

### What filters are available?

| Filter | Options |
|---|---|
| **Vehicle type** | Cars, Bikes & ATVs, RVs, Boats, Watercraft, Snowmobiles, Trailers, Commercial & heavy trucks, Heavy equipment, Farm equipment |
| **Make and model** | 120 makes. Model names match forgivingly, so `CR-V`, `crv`, and `CR V` all work |
| **Condition** | New, Used, Employee's car, Antique / classic, Demonstration, Pre-registered |
| **Seller type** | Dealer or private seller |
| **Price** | From / to, in CAD |
| **Model year** | From / to |
| **Mileage** | From / to, in km |
| **Body type** | Sedan, SUV, Pick-up truck, Hatchback, Coupe, Convertible, Wagon, Minivan, Other |
| **Fuel type** | Gasoline, Diesel, Electric, Hybrid, Flex fuel, Natural gas, Propane (LPG), Other |
| **Transmission** | Automatic or manual |
| **Engine** | Cylinder count, power range in hp or kW |
| **Doors and seats** | From / to |
| **Colours** | Exterior (14), interior (11), upholstery material |
| **Features** | 51 options, all required at once: backup camera, heated seats, sunroof, Apple CarPlay, adaptive cruise control, panoramic roof, and more |
| **Location** | Canadian postal code or place name, plus a radius from 10 km to 400 km |
| **Freshness** | Only listings posted within the last N days |
| **Damaged vehicles** | Excluded by default, matching the site |
| **Sorting** | Price, model year, mileage, date posted, power, make/model, or distance, ascending or descending |

### How do I limit how many results I get?

| Input | What it does |
|---|---|
| **Max results** (`max_items`) | Hard cap on vehicles. Set 250 and you get exactly 250. |
| **Start page / End page** | Page range. Pages hold **100 listings each** here, while autotrader.ca shows 20 per page, so page 3 here covers the site's pages 11 to 15. |

Use **Max results** when you want an exact number, because page ranges can only limit output in steps of 100. Setting `end_page: 2` with `max_items: 150` returns exactly 150 vehicles, not 200.

Leave all three empty to scrape every available page.

In monitor mode, **Max results** caps the change rows per run. Every search page is still read, and changes beyond the cap are held back and reported on the next run rather than lost. Leave Start page and End page empty when monitoring: sold vehicles can only be detected when the whole search is read.

### What data do you get?

Every record carries the same 127 keys. Which of them are filled depends on what the dealer published, so check [Field coverage](#field-coverage) before you build against a specific field.

**Monitor fields** (monitor mode only, added to every change row)

- `change_type`: `new`, `price_drop`, `price_increase`, `removed`, or `baseline`
- `previous_price_cad`, `price_change_cad`, `price_change_pct`: the price before, and the change in dollars and percent
- `price_history`: every price seen while the listing was monitored, with dates
- `first_seen_at`, `last_seen_at` (removed rows), `days_tracked`: how long the listing has been watched
- `watchlist`, `change_detected_at`
- `detail_error`: set only when the listing page could not be loaded; the row then carries the fields shown in the search results

**Listing info**

- `listing_url`: direct link to the vehicle listing
- `ad_id`: unique AutoTrader ad identifier
- `data_source`: origin of the record (AutoTrader Canada)
- `status` / `vehicle_status`: Used or New
- `listing_status`: listing state (for example, Active)
- `created_timestamp`: exact date and time the listing went up (ISO-8601)
- `posted_age_days`: how many days it has been listed, for freshness and stale-inventory filters
- `leads_range`: bucketed buyer-interest signal ("Zero" / "Some")
- `description`: full vehicle description text

**Vehicle specs**

- `make`, `model`, `year`, `trim`
- `vin`: vehicle identification number (used vehicles, see coverage)
- `stock_number`: dealer stock reference
- `body_type`, `transmission`, `drivetrain`, `fuel_type`
- `cylinders`, `displacement`, `doors`, `seats`
- `exterior_color`, `interior_color`

**Pricing and market position**

- `price_formatted`: formatted string (for example, "$ 29,873")
- `price_cad`: numeric CAD value for direct calculations
- `market_median_price`: AutoTrader's median price for comparable vehicles
- `price_vs_market`: dollars above or below that median (negative means cheaper than market)
- `price_vs_market_pct`: the same gap as a percentage, ready to sort on
- `suggested_retail_price`, `suggested_retail_price_raw`: MSRP when new (see coverage)
- `price_evaluation`: AutoTrader's price rating
- `price_is_final`, `price_is_negotiable`, `price_is_conditional`: pricing flags
- `financing_available`, `leasing_available`, `warranty_exists`

**Mileage and fuel economy**

- `mileage_formatted`: formatted (for example, "11,213 km")
- `mileage_km`: numeric km value
- `fuel_city_l_100km`, `fuel_highway_l_100km`: numeric consumption

**History and condition**

- `accident_free`: accident-history flag
- `carfax_available`: whether a Carfax report is offered
- `carfax_url`: link to the report (the free report link where the dealer provides one)
- `carfax_mode`: how the report is offered, and the reason `vin` is or is not present
- `has_full_service_history`, `non_smoking`, `new_inspection`, `is_rental`

**Seller and dealer**

- `seller_name`, `is_private_seller`, `dealer_is_dealer`, `dealer_type`, `dealer_id`
- `dealer_phone`, `dealer_phone_call_to`: display and dial-ready formats
- `dealer_sms_number`: the dealer's SMS line where enabled
- `dealer_address_full`, `dealer_address_street`, `dealer_city_province`
- `dealer_inventory_url`, `dealer_logo_url`

**Location**

- `city`, `province`, `country`, `zip_code`, `full_location`
- `latitude`, `longitude`: precise coordinates for mapping and radius analysis

**Media**

- `image_urls`: array of full-resolution photo URLs
- `image_count`: number of photos
- `header_image`: thumbnail URL
- `video_urls`, `has_360_view`

### Field coverage

The Actor emits 127 keys per record and reads only what AutoTrader publishes on the page. It never guesses or backfills. Around 85 fields populate on a typical dealer listing and the rest return `null`. The ones worth knowing before you build:

- **`vin`** is published only for used vehicles whose listing carries a *purchasable* Carfax report, typically 55 to 75% of a mixed new/used search. AutoTrader does not print the VIN anywhere on the page in the other cases: new vehicles (no Carfax), listings offering a free Carfax report, and listings where the buyer must request the report from the dealer. For those, `vin` is `null`, because the data is not on the page to take and no setting changes that. VINs are returned exactly as the dealer published them, including the occasional typo, rather than being silently dropped or "corrected".
- **`suggested_retail_price`** is the manufacturer's suggested retail price **when the vehicle was new**. It is not a previous asking price. On a used vehicle, MSRP minus the asking price is depreciation, not a discount. AutoTrader does not publish listing price history, so the scraper's own `price_drop` field stays `null`. For real price drops, use monitor mode: it records each listing's price every run and reports the change in `price_change_cad`, with the full `price_history`. To judge whether a listing is priced well today, use `market_median_price` and `price_vs_market`. MSRP is present on roughly 40% of listings.
- **`posted_age_days`** and **`province`** are computed rather than published: the age from `created_timestamp`, and the province from the postal code (Canada Post assigns the first letter by province). Both are exact, not estimates.
- **Equipment lists** (`comfort_equipment`, `safety_equipment`, `all_equipment`, and similar) populate only when the dealer fills in the structured equipment section. Many dealers put this in `description` free text instead.
- **`removed` rows** are built from the last search results the monitor saw, since the listing page no longer exists: make, model, year, price, mileage, seller, dealer phone, city, and price history, but no VIN or specs.
- Fields such as `engine`, `power_hp`, `average_market_price`, `price_drop`, and `dealer_google_rating` are kept in the schema for compatibility but are not currently published by AutoTrader and return `null`.

If a field you need is `null` across your results, it is missing from the source page rather than dropped by the scraper. Reach out via the Issues tab and it can often be derived from another field.

### Sample output

**A monitor change row** (example, abridged: the full vehicle record follows the monitor fields):

```json
{
  "change_type": "price_drop",
  "previous_price_cad": 40668,
  "price_change_cad": -3000,
  "price_change_pct": -7.4,
  "price_history": [
    { "date": "2026-09-20", "price_cad": 40668 },
    { "date": "2026-09-26", "price_cad": 37668 }
  ],
  "first_seen_at": "2026-09-20T08:00:00Z",
  "days_tracked": 6,
  "watchlist": "search-3f9c2a71b0de",
  "change_detected_at": "2026-09-26T17:46:44Z",
  "make": "Toyota",
  "model": "Highlander",
  "year": 2021,
  "price_cad": 37668,
  "mileage_km": 113492,
  "seller_name": "Northland Nissan",
  "dealer_phone": "604-239-3401",
  "city": "PRINCE GEORGE",
  "province": "BC"
}
```

**A full vehicle record**, real and abridged (127 keys are returned in full):

```json
{
  "ad_id": "6abe52b0-9bc8-416f-9a71-03f0cae48952",
  "listing_url": "https://www.autotrader.ca/offers/ford-escape-awd-panoramic-roof-tech-package-low-km-gasoline-white-cat_ma29gr18589tr11414-6abe52b0-9bc8-416f-9a71-03f0cae48952",
  "data_source": "AutoTrader Canada",
  "make": "Ford",
  "model": "Escape",
  "year": 2024,
  "trim": "AWD | PANORAMIC ROOF | TECH PACKAGE | LOW KM",
  "vin": "1FMCU9MNXRUA61773",
  "stock_number": "N6350A",
  "status": "Used",
  "price_formatted": "$ 29,873",
  "price_cad": 29873,
  "market_median_price": 31300,
  "price_vs_market": -1427,
  "price_vs_market_pct": -4.6,
  "price_evaluation": 1,
  "price_is_negotiable": false,
  "mileage_formatted": "11,213 km",
  "mileage_km": 11213,
  "body_type": "SUV",
  "transmission": "Automatic",
  "drivetrain": "All Wheel Drive",
  "fuel_type": "Gasoline",
  "cylinders": 3,
  "displacement": "1,500 cc",
  "doors": 4,
  "seats": 5,
  "exterior_color": "White",
  "interior_color": "Black",
  "fuel_city_l_100km": 9.2,
  "fuel_highway_l_100km": 7.4,
  "accident_free": true,
  "carfax_mode": "BuyCarFax",
  "carfax_available": true,
  "carfax_url": "https://www.carfax.ca/order?vin=1FMCU9MNXRUA61773&report=verified&ref=trader&refID=5_70436986_ON20080213110737382&refdomain=2",
  "city": "Scarborough",
  "province": "ON",
  "country": "CA",
  "zip_code": "M1L 2N1",
  "full_location": "Scarborough, CA",
  "latitude": 43.72814,
  "longitude": -79.28359,
  "is_private_seller": false,
  "seller_name": "Donway Ford Inc",
  "dealer_phone": "437-889-2758",
  "dealer_address_full": "1975 Eglinton Avenue East, Scarborough, M1L 2N1",
  "financing_available": true,
  "image_count": 11,
  "image_urls": [
    "https://prod.pictures.autoscout24.net/listing-images/6abe52b0-9bc8-416f-9a71-03f0cae48952_4358cf4f-9b2b-47a4-b9a7-1cbeaaef68e8.jpg/1280x960.webp",
    "https://prod.pictures.autoscout24.net/listing-images/6abe52b0-9bc8-416f-9a71-03f0cae48952_b987bc9a-3448-4f93-beb2-e917edced353.jpg/1280x960.webp"
  ],
  "listing_status": "Active",
  "created_timestamp": "2026-06-11T09:10:50.665Z",
  "posted_age_days": 36,
  "leads_range": "Some",
  "description": "Experience style, performance, and advanced technology in this exceptionally low-kilometre 2024 Ford Escape ST-Line AWD..."
}
```

### Who uses this AutoTrader.ca monitor?

- **Used car dealers** getting a daily list of competitors' price drops, new stock, and sold units by make, model, and region
- **Car flippers and wholesalers** catching underpriced vehicles the day they appear or drop, and filtering accident-free, low-kilometre stock across regions
- **Car shoppers** watching one model in their area without refreshing the site
- **Automotive market researchers** measuring days on market and markdowns, or building Canadian vehicle pricing datasets with clean numeric fields
- **Insurance and fintech teams** valuing vehicle portfolios from targeted listing subsets
- **Inventory aggregators** feeding car-search platforms with fresh AutoTrader Canada data
- **Data scientists** who need ready-to-use `price_cad` and `mileage_km` values without post-processing
- **Analysts** matching listings to their own VIN records, or mapping inventory density by `latitude` and `longitude`

### How does it work?

- You provide AutoTrader.ca search URLs or fill in the filter form.
- The Actor requests 100 listings per page and handles all pagination automatically.
- **In monitor mode**, each search page's listing prices are compared with the previous run's snapshot, and only the listings that changed are opened in full. Listings that left the search are checked one by one before being reported as sold. The snapshot is saved only after a run finishes, so a failed run never corrupts your history.
- Each vehicle detail page is fetched and the embedded `__NEXT_DATA__` JSON is parsed directly. No HTML scraping and no headless browser, which is why it is fast and stable.
- Up to 200 detail pages are fetched in parallel through rotating proxies.
- Runs are resumable. Progress is saved, so an interrupted run picks up where it left off instead of starting over.
- Failed pages retry automatically with capped exponential backoff.
- Results land in the Apify dataset, exportable as JSON, CSV, Excel, XML, or JSONL.

### Why choose this Actor?

- **Only what changed.** Monitor mode reports new listings, price drops, and sold vehicles instead of the whole search again, so you are not billed for cars that did not move.
- **Real price history.** AutoTrader does not publish past prices; the monitor records them run after run.
- **No false "sold" alerts.** A vanished listing is checked before it is reported, and removals are skipped when the search was not fully read.
- **More complete records.** It parses the listing JSON that AutoTrader itself uses, instead of scraping HTML, so fields are not lost to layout changes.
- **Analysis-ready numbers.** Both formatted strings and numeric values are returned for price and mileage, so data drops straight into Excel or a database.
- **No proxy setup.** Rotating proxies are built in. You do not need an Apify Proxy subscription.
- **Search without URLs.** A full filter form covers make, model, price, year, mileage, body type, fuel, features, and location.
- **Exact result limits.** Max results caps the output at any number you choose.
- **Automatic pagination.** No manual page incrementing in your URLs.
- **Resumable.** Large runs survive interruptions without re-scraping.

### Frequently asked questions

#### How do I get alerts when a car's price drops on AutoTrader.ca?

Turn on **Price-drop monitor**, set your search, save it as a task, and schedule it (daily is typical). Each run returns only new listings, price drops, and sold vehicles. Add a Slack, email, or webhook integration to the task to be notified when a run finds changes.

#### How does the monitor know a car was sold?

When a listing that was in your search disappears, the Actor opens its page. If AutoTrader no longer serves it, the listing is reported as `removed` with its last known price and how many days it was tracked. If the page still loads, nothing is reported.

#### Do I pay for listings that did not change?

No. Unchanged listings are compared but never output, and billing is per result row. A run with no changes produces an empty dataset.

#### What happens on the first monitor run?

There is nothing to compare against yet, so the first run saves the current listings as the baseline. With **Export all listings on the first run** on (the default), it also outputs them, marked `baseline`. Switch that off if you only want changes from day two on.

#### Can I change the search on an existing monitor?

Yes, but a changed search starts a new history: each search keeps its own snapshot, so the first run after the change is a new baseline. If you set a **Watchlist name** and reuse it for a different search, its old history is replaced.

#### Why were sold vehicles not checked on my run?

Removals are only judged when every page of the search was read. The log names the reason when they are skipped: a search over AutoTrader's 4,000-result limit, a page that failed to load, an End page setting, or the free plan's one-page limit. New listings and price changes are still reported on those runs.

#### How do I scrape AutoTrader Canada without coding?

Open the Actor, paste an AutoTrader.ca search URL into Start URLs, and click Start. If you would rather not build a URL, leave Start URLs empty and use the Search filters section to pick make, model, price, year, and location. Results download as JSON, CSV, or Excel.

#### Is scraping AutoTrader.ca legal?

This Actor collects only publicly available listing data, the same information any visitor sees on autotrader.ca without logging in. It does not access private accounts or personal data. You are responsible for how you use the output, so review AutoTrader's terms and any laws that apply to your use case, and consult a lawyer if you are unsure.

#### How many listings can I scrape at once?

AutoTrader itself caps **any single search at 4,000 listings**, no matter how many results it reports. That is a limit of the website, not of this scraper. To collect more, split your search and run it several times: by price band, by model year, by province using postal code and radius, or one make at a time. Each narrowed search gets its own 4,000-listing allowance.

#### Why do I get 4,000 listings when the search says there are more?

Same reason as above. AutoTrader stops serving results past 4,000 for a single search. Split the search into narrower ones and run each separately.

#### Do all listings include a VIN?

No. AutoTrader publishes a VIN only for used vehicles carrying a purchasable Carfax report, roughly two thirds of a mixed new/used search. New vehicles do not have one, and listings with a free Carfax report do not expose it on the page, so `vin` is `null` there. See [Field coverage](#field-coverage).

#### What should I put in the Postal code field?

Use either a Canadian postal code on its own (`V2N 0A3`, `V2N0A3`, or just the first three characters `V2N`), or a place name with or without a province (`Prince George`, `Prince George, BC`, `Toronto, ON`).

**Do not combine the two.** `V2N0A3, BC` is the one format AutoTrader's own search cannot read. The scraper strips the province off a postal code for you, and if a location cannot be resolved at all it stops the run with an error rather than quietly scraping the entire country.

If you leave the radius empty, AutoTrader applies its own default of 100 km.

#### Can I filter by drivetrain (AWD, FWD, RWD)?

No, and neither can AutoTrader. The site shows drivetrain on each listing, but its search backend does not filter on it, so the option is ignored even on autotrader.ca itself. The drivetrain of every scraped vehicle is included in the output, so you can filter the dataset afterwards.

#### I filled in the filters but it scraped something else. Why?

You almost certainly had something in Start URLs. Start URLs always take precedence, and the Search filters section is ignored whenever they are set. The run log says so explicitly. Clear Start URLs to search by filters.

#### Can I limit how many results I get?

Yes, in two ways. **Max results** caps the number of vehicles outright, so setting 250 returns exactly 250. **Start page** and **End page** scrape a page range instead, but pages hold 100 listings each here, so they only limit output in steps of 100. Leave all three blank to fetch everything.

#### Can I scrape a single vehicle URL instead of a search?

Yes, in scraper mode. Pass a direct listing URL in Start URLs. Both the current `https://www.autotrader.ca/offers/...` form and the older `https://www.autotrader.ca/a/...` form are supported, and the Actor scrapes just that vehicle. Monitor mode skips single listing URLs; paste the search the vehicle appears in instead.

#### Does it handle proxies and anti-bot protection?

Yes, with nothing to set up. Every run goes through a built-in rotating proxy network with browser-like request fingerprinting and automatic retries. You do not need an Apify Proxy subscription or a proxy of your own.

#### Can I scrape RVs, motorcycles, boats, or trucks too?

Yes. Set **Vehicle type** in the filter section to RVs, Bikes & ATVs, Boats, Watercraft, Snowmobiles, Trailers, Commercial & heavy trucks, Heavy equipment, or Farm equipment. Every other filter applies within the type you pick.

#### What output formats are available?

JSON, CSV, Excel, XML, and JSONL, all available from the Apify dataset UI and the REST API.

#### Is the data live?

Yes. Every run fetches current listings directly from AutoTrader.ca. Nothing is cached or served from an old copy.

#### Does it support scheduling and webhooks?

Yes, and monitor mode is built for it. Use Apify's built-in scheduler for cron-based runs (hourly, daily, weekly), and webhooks or the Slack and email integrations to act on each run's changes.

#### Can you add more fields?

The embedded JSON contains extensive vehicle data, so most additional fields can be added on request. Reach out via the Issues tab.

### Pricing

Billing is **pay per result**: every row in the dataset is one result. The current rate is shown on this Actor's Store page.

- In **monitor mode**, only changes are rows, so unchanged listings cost nothing, and a run with no changes produces no rows. The optional first-run export (`baseline` rows) is billed like any other result; switch it off to skip it.
- In **scraper mode**, every vehicle scraped is a row.
- Free-plan runs are limited to the first page of each search (100 listings). An [Apify plan](https://apify.com/pricing?fpr=youssef) unlocks every page.

### Use via API or MCP

Run this Actor programmatically via the Apify REST API, or connect it as an MCP server for AI agents like Claude, ChatGPT, and Cursor.

API run endpoint:

```
POST https://api.apify.com/v2/acts/fayoussef~autotrader-ca/runs?token=YOUR_TOKEN
```

MCP server URL:

```
https://mcp.apify.com/actors/fayoussef~autotrader-ca
```

To run the monitor through the API, send the same input you would schedule, for example:

```json
{
  "monitor_mode": true,
  "start_urls": [{ "url": "https://www.autotrader.ca/cars/honda/civic/qc/montreal/?ustate=U" }],
  "report_changes": ["new", "price_drop", "removed"]
}
```

Each run's counts are also written to the `MONITOR_SUMMARY` record in the run's key-value store.

Full API docs: <https://docs.apify.com/api/v2>

### Need a custom scraper?

Need a different automotive site, extra fields, alerts sent straight to your team, or a fully managed data pipeline? Visit [automationbyexperts.com](https://automationbyexperts.com) for custom builds, retainers, and data-as-a-service.

# Actor input Schema

## `start_urls` (type: `array`):

Search or listing URLs copied from autotrader.ca. Set your filters on the site, copy the address bar, paste it here. Direct listing URLs (/offers/... or /a/...) also work and skip straight to that vehicle, but only with the monitor off: the monitor watches searches. This field takes precedence: anything here means the Search filters section below is ignored. Leave it empty to search by filters instead.

## `max_items` (type: `integer`):

Stop after this many vehicles, even if more pages match. Leave empty for no limit. Use this for an exact number: pages hold 100 listings each, so End page can only limit the output in steps of 100. With the monitor on, this caps change rows per run; changes over the cap are reported on the next run.

## `monitor_mode` (type: `boolean`):

Turn this on and schedule the run (daily is typical). The first run saves the current listings as a baseline. Every later run returns only what changed since the previous run: new listings, price drops, price increases and sold or removed vehicles, each with the previous price, the change and a price history. Off: a normal full scrape of every listing.

## `report_changes` (type: `array`):

Which changes become rows. Price increases are off by default. Changes that are not selected are still tracked, so the comparison stays accurate.

## `min_price_change_cad` (type: `integer`):

Ignore price changes smaller than this many dollars. Leave empty to report every change.

## `min_price_change_pct` (type: `integer`):

Ignore price changes smaller than this percentage of the previous price. Leave empty to report every change. If both minimums are set, a change must pass both.

## `export_baseline` (type: `boolean`):

On: the first run also outputs every current listing (marked "baseline"), so you start with the full picture. Off: the first run only saves the baseline and outputs nothing.

## `watchlist_name` (type: `string`):

Leave empty: each search keeps its own history automatically. Set a name to keep two watchlists apart on the same search, or to start a fresh history. Reusing a name for a different search replaces its history.

## `vehicle_type` (type: `string`):

Which part of AutoTrader to search. Every other filter applies within it.

## `makes` (type: `array`):

Vehicle makes to include. Leave empty for all makes.

## `models` (type: `array`):

Model names to narrow the makes above, for example "A4" or "CR-V". Spelling is forgiving (case, spaces and hyphens are ignored). Requires at least one make, since model names are only unique within a make. A name that matches no model is reported in the log and ignored.

## `conditions` (type: `array`):

New, used, or one of AutoTrader's other offer types. Leave empty for all.

## `seller_type` (type: `array`):

Dealer or private seller. Leave empty for both.

## `price_from` (type: `integer`):

Lowest asking price, in CAD.

## `price_to` (type: `integer`):

Highest asking price, in CAD.

## `model_year_from` (type: `integer`):

Earliest model year.

## `model_year_to` (type: `integer`):

Latest model year.

## `mileage_from_km` (type: `integer`):

Lowest odometer reading, in kilometres.

## `mileage_to_km` (type: `integer`):

Highest odometer reading, in kilometres.

## `body_types` (type: `array`):

Body styles to include. Leave empty for all.

## `fuel_types` (type: `array`):

Fuel or powertrain types to include. Leave empty for all.

## `transmission` (type: `array`):

Automatic or manual. Leave empty for both.

## `cylinders` (type: `array`):

Engine cylinder counts to include.

## `power_from` (type: `integer`):

Minimum engine power, in the unit selected below.

## `power_to` (type: `integer`):

Maximum engine power, in the unit selected below.

## `power_unit` (type: `string`):

Unit for the power range above. Only used when a power range is set.

## `doors_from` (type: `integer`):

Minimum number of doors.

## `doors_to` (type: `integer`):

Maximum number of doors.

## `seats_from` (type: `integer`):

Minimum number of seats.

## `seats_to` (type: `integer`):

Maximum number of seats.

## `exterior_colors` (type: `array`):

Exterior colours to include. Leave empty for all.

## `interior_colors` (type: `array`):

Interior colours to include. Leave empty for all.

## `upholstery` (type: `array`):

Seat material. Leave empty for all.

## `equipment` (type: `array`):

Only listings that have ALL of the selected features. Dealers fill these in by hand, so picking several at once narrows results sharply.

## `postal_code` (type: `string`):

Search around this location. Use a Canadian postal code on its own ("M5V 3L9", "M5V") or a place name with or without a province ("Prince George", "Prince George, BC"). Do not put a province after a postal code: "V2N0A3, BC" is the one format AutoTrader's search cannot read. Required for the search radius below to apply.

## `radius_km` (type: `string`):

How far from the location above to search. Leave empty and AutoTrader applies its own default of 100 km, so a location always limits the search whether or not you pick a radius. Ignored when no location is set.

## `listed_within_days` (type: `integer`):

Only listings posted within this many days.

## `include_damaged` (type: `boolean`):

Off by default, matching the site: damaged and salvage listings are excluded.

## `sort_by` (type: `string`):

Order results are returned in. Matters when a search hits AutoTrader's 4,000-listing ceiling, since it decides which 4,000 you get.

## `sort_descending` (type: `boolean`):

Reverse the sort order: highest price, newest year, most kilometres first.

## `start_page` (type: `integer`):

Page number to start from (1-indexed). Leave empty to start at page 1. NOTE: this Actor reads 100 listings per page, while autotrader.ca shows 20 by default, so page 3 here covers the same vehicles as pages 11 to 15 on the site.

## `end_page` (type: `integer`):

Page number to stop at (1-indexed, inclusive). Leave empty to scrape all pages.

## Actor input object example

```json
{
  "start_urls": [
    {
      "url": "https://www.autotrader.ca/cars/ot_used?priceto=16000&modelyearto=2007&cy=CA&damaged_listing=exclude&desc=0&pricefrom=10000&sort=standard&ustate=N%2CU&atype=C&size=20"
    }
  ],
  "monitor_mode": false,
  "report_changes": [
    "new",
    "price_drop",
    "removed"
  ],
  "export_baseline": true,
  "vehicle_type": "cars",
  "power_unit": "hp",
  "include_damaged": false,
  "sort_by": "standard",
  "sort_descending": false
}
```

# Actor output Schema

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

Complete vehicle listing data including pricing, specifications, images, dealer information, and vehicle details from AutoTrader Canada

# 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 = {
    "start_urls": [
        {
            "url": "https://www.autotrader.ca/cars/ot_used?priceto=16000&modelyearto=2007&cy=CA&damaged_listing=exclude&desc=0&pricefrom=10000&sort=standard&ustate=N%2CU&atype=C&size=20"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fayoussef/autotrader-ca").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 = { "start_urls": [{ "url": "https://www.autotrader.ca/cars/ot_used?priceto=16000&modelyearto=2007&cy=CA&damaged_listing=exclude&desc=0&pricefrom=10000&sort=standard&ustate=N%2CU&atype=C&size=20" }] }

# Run the Actor and wait for it to finish
run = client.actor("fayoussef/autotrader-ca").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 '{
  "start_urls": [
    {
      "url": "https://www.autotrader.ca/cars/ot_used?priceto=16000&modelyearto=2007&cy=CA&damaged_listing=exclude&desc=0&pricefrom=10000&sort=standard&ustate=N%2CU&atype=C&size=20"
    }
  ]
}' |
apify call fayoussef/autotrader-ca --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fayoussef/autotrader-ca"
        }
    }
}
```

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/3ejzL1PlGlgnscRJ5/builds/esZ6H7newQX4dc50W/openapi.json
