# Canadian Tire Scraper (`crawlerbros/canadian-tire-scraper`) Actor

Scrape CanadianTire.ca products by keyword search, category browse, or exact product code. Get prices, sale discounts, ratings, images, feature bullets and specifications.

- **URL**: https://apify.com/crawlerbros/canadian-tire-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Canadian Tire Scraper

Scrape product data from [CanadianTire.ca](https://www.canadiantire.ca) -- one of Canada's largest retailers, covering tools, automotive, sports, home, and outdoor living products. Get product titles, prices, sale discounts, ratings, images, feature bullets, and specifications from keyword search, category browsing, or exact product codes.

### What does this scraper do?

- **Search by keyword** -- find products matching any search term (e.g. "hammer", "garden hose", "bbq").
- **Browse a category** -- pull every product listed under a Canadian Tire category code.
- **Get exact products** -- fetch specific products by their Canadian Tire product code.
- **Filter results** -- by price range, minimum rating, on-sale status, in-stock status, brand, deal type, availability type, and featured badge.
- **Sort results** -- by relevance, price, newest arrivals, rating, or best seller.
- **Choose a reference store** -- report stock/availability against any specific Canadian Tire store location instead of a fixed default.

No login, cookies, or paid proxy required.

### Output

Each result is a JSON record with:

| Field | Description |
|---|---|
| `productCode` | Canadian Tire's product code (e.g. `0574127P`) |
| `title` | Product name |
| `brand` | Brand name |
| `price` | Current price (CAD) |
| `priceIsStartingFrom` | `true` when `price` is the lowest price across a multi-variant product's SKUs rather than a single fixed price |
| `priceRangeMax` | Highest price across variants, when the product's price varies by SKU (size/color) and `priceIsStartingFrom` is `true` |
| `originalPrice` | Original price before discount, when the product is on sale |
| `discountPercent` | Discount percentage, when on sale |
| `currency` | Always `CAD` (Canadian dollar) |
| `isOnSale` | Whether the product is currently on sale/clearance |
| `rating` | Average customer rating (0-5) |
| `ratingsCount` | Number of customer ratings |
| `badges` | Merchandising badges (e.g. `EXCLUSIVE`, `TOPRATED`, `CLEARANCE`) |
| `partNumber` | Manufacturer part number |
| `skuId` | Canadian Tire SKU identifier |
| `stockQuantity` | Available stock quantity at the reference store |
| `onlineStockQuantity` | Available stock quantity for online/ship-to-home fulfillment |
| `sellable` / `orderable` | Whether the product can currently be sold / ordered |
| `isUrgentLowStock` | Whether the product is flagged as urgently low on stock |
| `warrantyMessage` | Manufacturer/Canadian Tire warranty terms, when provided |
| `images` | Product image URLs |
| `productUrl` | Link to the product page |
| `featureBullets` | Key product feature/benefit bullet points |
| `specifications` | Name/value technical specification pairs, when available |
| `recordType` | `product` |
| `scrapedAt` | UTC timestamp of when the record was scraped |

Only fields that Canadian Tire actually provides for a given product are included -- no blank or placeholder values.

### Input options

| Field | Mode | Description |
|---|---|---|
| `mode` | all | `search`, `category`, or `byProductCodes` |
| `searchQuery` | search | Keyword to search for |
| `categoryCode` | category | Canadian Tire category code (e.g. `DC0002027`) |
| `productCodes` | byProductCodes | Exact Canadian Tire product codes |
| `sortBy` | search/category | `relevance`, `priceAsc`, `priceDesc`, `newest`, `ratingDesc`, `bestseller` |
| `minPrice` / `maxPrice` | search/category | Price range filter in CAD |
| `minRating` | search/category | Minimum customer rating (0-5) |
| `onSaleOnly` | search/category | Only include products on sale/clearance |
| `inStockOnly` | search/category | Only include products with available stock |
| `brand` | search/category | Filter to brand names containing this text |
| `dealType` | search/category | Server-side filter to a specific deal type: `clearance`, `sale`, `limitedTimeOffer`, `specialBuy` |
| `availabilityType` | search/category | Server-side filter to a specific availability type: `inStoreOnly`, `onlineOnly`, `inStockAtMyStore` |
| `featuredType` | search/category | Server-side filter to a specific merchandising badge: `exclusive`, `topRated`, `bestSeller`, `testedForLife`, `newArrivals` |
| `storeId` | all | Canadian Tire store ID used as the stock/availability reference (default: a Toronto reference store) |
| `maxItems` | all | Maximum number of records to return |
| `maxPages` | search/category | Maximum result pages to scan |

#### Finding a category code

Open any category page on Canadian Tire, e.g. `https://www.canadiantire.ca/en/cat/tools-hardware/power-tools/drills-accessories/drills-DC0002027.html` -- the category code is `DC0002027`.

#### Finding a store ID

Open [Canadian Tire's Store Locator](https://www.canadiantire.ca/en/store-locator.html), select a store, and note the numeric ID at the end of the store-details page URL (e.g. `.../store-details/on/toronto-store-144.html` -- the store ID is `144`). Pass either the bare number or the full store-details URL as `storeId`.

#### Finding a product code

Open any product page, e.g. `.../mastercraft-claw-hammer-forged-steel-with-fibreglass-handle-16-oz-0574127p.html` -- the product code is `0574127P`.

### Example use cases

- **Price monitoring** -- track prices and sale discounts for specific products or categories over time.
- **Market research** -- analyze brand presence, ratings, and pricing across a product category.
- **Deal hunting** -- filter for on-sale products or the best-rated items in a category.
- **Catalog enrichment** -- pull full specifications, feature bullets, and images for a list of known product codes.

### FAQ

**Does this scraper require login or cookies?**
No. All data is scraped from Canadian Tire's own public product search API -- no account or Canadian Tire Triangle Rewards login needed.

**What currency are prices in?**
Canadian dollars (CAD), Canadian Tire's home market currency.

**Why do some products lack a `rating` or `originalPrice` field?**
Canadian Tire only returns rating/discount data for products that actually have it. Fields are omitted rather than filled with placeholder values, in line with real-data accuracy.

**Can I filter by my local store's stock instead of a fixed reference store?**
Yes -- set `storeId` to your store's numeric ID (see "Finding a store ID" above). `stockQuantity`, `onlineStockQuantity`, `isUrgentLowStock`, and the `inStockOnly` filter will then reflect that specific store.

**Why does `price` sometimes represent a range instead of one fixed value?**
Some Canadian Tire products come in multiple variants (size, weight, color) priced individually. For these, `price` reports the lowest variant price with `priceIsStartingFrom: true`, and `priceRangeMax` reports the highest, so price filters and sorting still work meaningfully.

**What's the difference between `onSaleOnly`/`dealType` and `availabilityType`?**
`onSaleOnly` is a broad client-side check for any current discount. `dealType` is a precise, Canadian-Tire-defined deal category (Store Clearance, Sale, Limited Time Offer, or Special Buy) applied server-side by their own search API -- use it when you need one specific deal type rather than "any deal". `availabilityType` filters by where a product can be fulfilled (in-store only, online only, or in stock at your reference store), independent of pricing.

**Does stock/availability reflect a specific store?**
Yes -- `stockQuantity` reflects a reference Canadian Tire store location. Availability can vary by store across Canada; this actor reports a representative national reference point.

**How many products can I scrape per run?**
Up to `maxItems` (default 48, max 2000) per run for search/category modes.

### Limitations

- Canadian Tire's product pages are served behind Akamai bot management, which challenges plain (non-browser-fingerprinted) HTTP clients with a 403. This actor's fetcher uses a browser-matching TLS fingerprint to reliably pass this check, so `productUrl` values in the output always resolve to the real product page in an actual browser -- a manual `curl` HEAD check from a non-browser client may show a 403 instead, which is expected Akamai behavior and not a broken link. Image URLs (`images`) are always directly accessible from any client.
- Canadian Tire's own `priceAsc`/`priceDesc` sort (confirmed directly against their raw API response) is not a strict global ascending/descending order across the full result set -- prices are correctly ordered within local runs but the sort appears to blend in relevance/product-family grouping. Every individual filter (price range, rating, sale, brand) is honored exactly; only the overall sort order across a large result set may not be perfectly monotonic. This is an upstream characteristic, not an actor defect.

# Actor input Schema

## `mode` (type: `string`):

search = keyword search. category = browse a category listing. byProductCodes = fetch exact products by their Canadian Tire product code.

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

Keyword to search for on Canadian Tire, e.g. 'hammer' or 'garden hose'.

## `categoryCode` (type: `string`):

Canadian Tire category code to browse, e.g. 'DC0002027' (Drills). Find it in a category page URL: canadiantire.ca/en/cat/.../{slug}-{categoryCode}.html.

## `productCodes` (type: `array`):

Exact Canadian Tire product codes to fetch, e.g. '0574127P'. Find it at the end of a product page URL.

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

How results are ordered by Canadian Tire before client-side filters are applied.

## `minPrice` (type: `number`):

Only include products priced at or above this amount, in Canadian dollars (CAD).

## `maxPrice` (type: `number`):

Only include products priced at or below this amount, in Canadian dollars (CAD).

## `minRating` (type: `number`):

Only include products with a customer rating at or above this value (0-5). Products with no rating data are always included.

## `onSaleOnly` (type: `boolean`):

Only include products currently marked on sale/clearance.

## `inStockOnly` (type: `boolean`):

Only include products with available stock quantity.

## `brand` (type: `string`):

Only include products whose brand name contains this text (case-insensitive), e.g. 'mastercraft'.

## `dealType` (type: `string`):

Only include products matching this specific deal type, applied server-side by Canadian Tire's own search API. Leave unset for no deal filter.

## `availabilityType` (type: `string`):

Only include products matching this availability category, applied server-side by Canadian Tire's own search API. Leave unset for no availability filter.

## `featuredType` (type: `string`):

Only include products carrying this merchandising badge, applied server-side by Canadian Tire's own search API. Leave unset for no badge filter.

## `storeId` (type: `string`):

Canadian Tire store ID to use as the reference store for stock quantity and availability fields, e.g. '144'. Find it via Canadian Tire's Store Locator (canadiantire.ca/en/store-locator.html) -- the numeric ID appears at the end of the store-details page URL. Defaults to a Toronto reference store if left blank.

## `maxItems` (type: `integer`):

Maximum number of records to return.

## `maxPages` (type: `integer`):

Maximum number of result pages (48 products/page) to walk before stopping.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "hammer",
  "categoryCode": "DC0002027",
  "productCodes": [
    "0574127P"
  ],
  "sortBy": "relevance",
  "onSaleOnly": false,
  "inStockOnly": false,
  "dealType": "",
  "availabilityType": "",
  "featuredType": "",
  "storeId": "144",
  "maxItems": 48,
  "maxPages": 20
}
```

# Actor output Schema

## `products` (type: `string`):

Dataset containing all scraped Canadian Tire products.

# 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 = {
    "mode": "search",
    "searchQuery": "hammer",
    "categoryCode": "DC0002027",
    "productCodes": [
        "0574127P"
    ],
    "sortBy": "relevance",
    "onSaleOnly": false,
    "inStockOnly": false,
    "dealType": "",
    "availabilityType": "",
    "featuredType": "",
    "storeId": "144",
    "maxItems": 48,
    "maxPages": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/canadian-tire-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 = {
    "mode": "search",
    "searchQuery": "hammer",
    "categoryCode": "DC0002027",
    "productCodes": ["0574127P"],
    "sortBy": "relevance",
    "onSaleOnly": False,
    "inStockOnly": False,
    "dealType": "",
    "availabilityType": "",
    "featuredType": "",
    "storeId": "144",
    "maxItems": 48,
    "maxPages": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/canadian-tire-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 '{
  "mode": "search",
  "searchQuery": "hammer",
  "categoryCode": "DC0002027",
  "productCodes": [
    "0574127P"
  ],
  "sortBy": "relevance",
  "onSaleOnly": false,
  "inStockOnly": false,
  "dealType": "",
  "availabilityType": "",
  "featuredType": "",
  "storeId": "144",
  "maxItems": 48,
  "maxPages": 20
}' |
apify call crawlerbros/canadian-tire-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/canadian-tire-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/UvbNQ9z8YyeGjxI0K/builds/ccrMFJQaoeap8aX4P/openapi.json
