# Canada Car Scraper: AutoTrader.ca, Kijiji & CarGurus in One (`fayoussef/canada-car-scraper`) Actor

Search AutoTrader.ca, Kijiji and CarGurus.ca at once with one filter form. Duplicates are merged into one row per car, with VIN, each site's price and link, the price gap, CarGurus deal rating and market value, dealer phone and private sellers.

- **URL**: https://apify.com/fayoussef/canada-car-scraper.md
- **Developed by:** [Youssef Farhan](https://apify.com/fayoussef) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.70 / 1,000 vehicles

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

## Canada Car Scraper: AutoTrader.ca, Kijiji and CarGurus in One Dataset

Search **AutoTrader.ca, Kijiji and CarGurus.ca at the same time** with one filter form, and get **one row per car** instead of three copies of the same vehicle. When a dealer lists the same truck on all three sites, this Actor merges it into a single record with the **VIN, the price on each site, the price gap, the CarGurus deal rating and market value**, the dealer's phone and a link to every listing.

It is the fastest way to export the Canadian used car market: no URLs to build, no duplicate cleanup, no matching spreadsheets by hand.

### What you get

- **One search, three sites.** Make and model, condition, dealer or private seller, year, price, mileage, postal code and radius, applied on AutoTrader.ca, Kijiji and CarGurus.ca.
- **Duplicates merged.** The same car found on two or three sites becomes one row (`listing_count`, `listed_on`). In a typical city search, about half of the cars are on more than one site.
- **VINs AutoTrader.ca hides.** AutoTrader.ca search results show no VIN. When the same car is on Kijiji or CarGurus, its VIN is filled in (`vin`, `vin_source`).
- **Price comparison across sites.** `autotrader_price`, `kijiji_price`, `cargurus_price`, the lowest `price`, `cheapest_on` and `price_gap`. Dealers do not always post the same price everywhere.
- **Deal rating and market value.** CarGurus' instant market value (`market_value`), `price_vs_market` and a deal rating (`great`, `good`, `fair`, `high`, `overpriced`).
- **Seller details.** Dealer name, phone, address, city, province and postal code, plus private sellers from Kijiji and AutoTrader.ca.
- **Monitoring mode.** Turn on *Only new vehicles since the last run* and schedule the Actor to get a daily feed of fresh inventory.

### Who uses it

- **Dealers and wholesalers**: watch competitors' inventory and prices in your market, and spot cars priced under market.
- **Car buyers and flippers**: find the cheapest copy of a car and the sites where a dealer lists it for less.
- **Private seller lead lists**: dealers' acquisition teams pull private sellers from Kijiji and AutoTrader.ca in one run.
- **Market research and analytics**: clean, de-duplicated Canadian used car data by make, model, year, price and region.
- **Lenders, insurers and appraisers**: comparable listings with VIN and market value for a given vehicle.

### How to use it

1. Type the vehicles you want, one per line: `Toyota RAV4`, `Ford F-150`, or just a make like `Honda`. Leave empty for all makes.
2. Enter a postal code (`M5V 3L9` or `M5V`) and a radius in km. Set the radius to `0` for all of Canada.
3. Add filters if you need them (condition, seller type, years, price, max km) and set **Max vehicles**.
4. Run it, then export the dataset to Excel, CSV, JSON or Google Sheets, or connect it to your tools through the Apify API.

#### Input example

```json
{
    "vehicles": ["Toyota RAV4", "Honda CR-V"],
    "postal_code": "M5V 3L9",
    "radius_km": 100,
    "condition": "used",
    "seller_type": "any",
    "year_from": 2019,
    "price_max": 40000,
    "max_results": 500,
    "sort_by": "newest"
}
```

### Output example

```json
{
    "title": "2022 Honda Civic",
    "year": 2022,
    "make": "Honda",
    "model": "Civic",
    "trim": "Touring FWD",
    "mileage_km": 142483,
    "price": 25322,
    "currency": "CAD",
    "cheapest_on": null,
    "price_gap": 0,
    "listed_on": ["autotrader", "kijiji", "cargurus"],
    "listing_count": 3,
    "vin": "2HGFE1F96NH001486",
    "vin_source": "cargurus",
    "stock_number": "3P00185",
    "seller_type": "dealer",
    "seller_name": "Calgary Honda",
    "seller_phone": "(888) 356-2454",
    "city": "Calgary",
    "province": "AB",
    "postal_code": "T2J7J5",
    "deal_rating": "fair",
    "market_value": 24416,
    "price_vs_market": 906,
    "days_on_market": 18,
    "autotrader_url": "https://www.autotrader.ca/offers/honda-civic-touring-...",
    "autotrader_price": 25322,
    "kijiji_url": "https://www.kijiji.ca/v-cars-trucks/calgary/2022-honda-civic-touring-.../1743800720",
    "kijiji_price": 25322,
    "cargurus_url": "https://www.cargurus.ca/Cars/inventorylisting/viewDetailsFilterViewInventoryListing.action?inventoryListing=459576734",
    "cargurus_price": 25322
}
```

#### All output fields

| Field | What it is |
|---|---|
| `vehicle_id` | Stable id of the car (from its VIN when known) |
| `title`, `year`, `make`, `model`, `trim`, `body_type`, `condition` | The vehicle |
| `mileage_km` | Odometer in km |
| `price`, `currency` | Lowest asking price across the sites, in CAD |
| `cheapest_on`, `price_gap` | Which site is cheapest (empty on a tie) and the difference between the highest and lowest price |
| `listed_on`, `listing_count` | Sites listing this car |
| `autotrader_url`, `autotrader_price`, `kijiji_url`, `kijiji_price`, `cargurus_url`, `cargurus_price` | Link and price on each site |
| `vin`, `vin_source`, `stock_number` | Identifiers, and the site the VIN came from |
| `seller_type`, `seller_name`, `seller_phone` | Dealer or private seller, and contact |
| `address`, `city`, `province`, `postal_code`, `latitude`, `longitude`, `distance_km` | Location, and distance from your postal code |
| `transmission`, `drivetrain`, `fuel_type`, `exterior_color` | Specs |
| `deal_rating`, `market_value`, `price_vs_market`, `days_on_market` | Price analysis (CarGurus first, then Kijiji, then AutoTrader.ca) |
| `listed_at`, `price_drop` | Listing date and recent price drop flag, when a site publishes them |
| `headline`, `image_url`, `image_count` | Dealer headline and main photo |
| `new_since_last_run` | Only in monitoring mode |

### How duplicates are merged

A car counts as the same vehicle on two sites when one of these matches, strongest first:

1. The **same VIN**.
2. The **same dealer stock number**, make and model year.
3. The **same make, model year and exact odometer reading at the same place** (same postal area, same city or within 25 km). Round readings like 150,000 km also need prices within 3%.

Two listings with different VINs are never merged. In testing, every AutoTrader.ca + CarGurus.ca pair merged this way had the same dealer.

### Monitoring new inventory

Turn on **Only new vehicles since the last run** and schedule the Actor (Apify Schedules, daily or hourly). Each run returns only the cars that the previous run of the same search did not see. The first run returns everything and becomes the baseline. Give the search a **Watchlist name** if you want to keep that memory when you change the filters.

### Pricing

This Actor is billed **per vehicle** saved to the dataset (pay per event). A car listed on two or three sites is one row, so you pay for it **once**. There is no charge for listings merged away as duplicates. The current rate, with a small discount on bigger Apify plans, is shown on this Actor's Store page.

Proxy traffic and compute are included in the per-vehicle price.

**Free plan:** each run returns up to 25 vehicles, so you can check the data before you subscribe. An [Apify plan](https://apify.com/pricing?fpr=youssef) unlocks up to 20,000 vehicles per run.

### Good to know

- **CarGurus.ca lists used cars from dealers only.** A new-car or private-seller search covers AutoTrader.ca and Kijiji.
- **Coverage differs by region.** Kijiji is strong in Atlantic Canada, Quebec and the Prairies, and thin in British Columbia. AutoTrader.ca and CarGurus.ca cover every province.
- **Big searches:** each site is asked for up to *Max vehicles* listings per vehicle line, so merging has the full picture. AutoTrader.ca serves at most 4,000 listings per search; narrow the filters (years, price, radius) to go deeper.
- **Order matters on big searches.** With *Newest first* or *Lowest price first*, the cars kept are the newest or cheapest on each site.
- **No proxy setup needed:** all three sites only answer Canadian visitors, and the Actor picks Canadian proxies by itself.

### FAQ

**Can I scrape only one site?** Yes, pick it under *Sites*. You still get the same clean output format.

**Does it open every listing page?** No. All data comes from each site's search results, which is why a 2,000-vehicle run takes about a minute.

**Why is the VIN empty on some cars?** AutoTrader.ca does not show VINs in search results, and private sellers often leave it out. When the same car is on Kijiji or CarGurus.ca, the VIN is filled in from there.

**Can I get phone numbers of private sellers?** No. Kijiji and AutoTrader.ca hide private sellers' phone numbers behind a contact form. Dealer phone numbers are included.

### Related Actors

- [AutoTrader Canada Car Scraper](https://apify.com/fayoussef/autotrader-canada?fpr=youssef): every field from AutoTrader.ca listing pages, with hidden VIN lookup.
- [AutoTrader.ca Price Drop Monitor](https://apify.com/fayoussef/autotrader-ca?fpr=youssef): price drops and sold cars on AutoTrader.ca.
- [CarGurus Scraper](https://apify.com/fayoussef/cargurus-listings-scraper?fpr=youssef): full CarGurus listings in the US, Canada and the UK.
- [Clutch.ca Car Scraper](https://apify.com/fayoussef/clutch-ca-scraper?fpr=youssef): Canada's online used car retailer.

Need another site or a custom feed? Reach out at youssefarhan24@gmail.com, or [suggest a site](https://automationbyexperts.com/apify).

# Actor input Schema

## `vehicles` (type: `array`):

One make or make + model per line, for example "Toyota RAV4", "Ford F-150" or just "Honda". Each line is searched on every site. Leave empty to search all makes.

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

Canadian postal code to search around, full ("M5V 3L9") or the first three characters ("M5V"). Not needed when the radius is 0.

## `radius_km` (type: `integer`):

How far from the postal code to search. 0 searches all of Canada.

## `max_results` (type: `integer`):

Stop after this many vehicles. A car listed on several sites counts once. ⚠️ Free-plan runs are capped at 25.

## `condition` (type: `string`):

Used, new or both. CarGurus.ca lists used cars only, so a new-car search covers AutoTrader.ca and Kijiji.

## `seller_type` (type: `string`):

Dealers, private sellers or both. Private sellers are on Kijiji and AutoTrader.ca (CarGurus.ca lists dealers only).

## `year_from` (type: `integer`):

Oldest model year to include.

## `year_to` (type: `integer`):

Newest model year to include.

## `price_min` (type: `integer`):

Lowest asking price in Canadian dollars.

## `price_max` (type: `integer`):

Highest asking price in Canadian dollars.

## `mileage_max_km` (type: `integer`):

Highest odometer reading in kilometres.

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

Newest listings first, or cheapest first. With a large search and a small Max vehicles, this decides which cars are kept.

## `sources` (type: `array`):

Which sites to search. All three by default.

## `only_new_listings` (type: `boolean`):

Return only cars that were not found by the previous run of the same search. Schedule the Actor (daily, hourly) to get a feed of fresh inventory. The first run returns everything and becomes the baseline.

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

Optional label for the memory of seen cars. Leave empty to tie the memory to the search filters; set a name to keep the memory when you edit the filters.

## Actor input object example

```json
{
  "vehicles": [
    "Toyota RAV4"
  ],
  "postal_code": "M5V 3L9",
  "radius_km": 100,
  "max_results": 50,
  "condition": "used",
  "seller_type": "any",
  "sort_by": "newest",
  "sources": [
    "autotrader",
    "kijiji",
    "cargurus"
  ],
  "only_new_listings": false
}
```

# Actor output Schema

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

One row per car, merged across AutoTrader.ca, Kijiji and CarGurus.ca: price on each site, price gap, VIN, deal rating, market value, specs, dealer and location.

# 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 = {
    "vehicles": [
        "Toyota RAV4"
    ],
    "postal_code": "M5V 3L9",
    "max_results": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("fayoussef/canada-car-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 = {
    "vehicles": ["Toyota RAV4"],
    "postal_code": "M5V 3L9",
    "max_results": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("fayoussef/canada-car-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 '{
  "vehicles": [
    "Toyota RAV4"
  ],
  "postal_code": "M5V 3L9",
  "max_results": 50
}' |
apify call fayoussef/canada-car-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fayoussef/canada-car-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/Avh5z4gPSH4zp6L9U/builds/Z8Kpe7aArTbE37OjJ/openapi.json
