Kijiji.ca Scraper - Listings, Prices & Seller Details
Pricing
from $1.00 / 1,000 results
Kijiji.ca Scraper - Listings, Prices & Seller Details
Scrape Kijiji.ca listings across property, vehicles, jobs, electronics, furniture, services, and more. Search by keyword and location or use any Kijiji URL. Extract titles, descriptions, prices, photos, GPS coordinates, seller details, and category-specific attributes.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
9 minutes ago
Last modified
Categories
Share
Kijiji.ca Scraper: Listings, Prices, Photos and Seller Contacts
Kijiji.ca Scraper pulls classified listings from Kijiji.ca across every category: property, vehicles, jobs, furniture, electronics, services and more. Search by keyword and location, or paste any Kijiji search, category or single-listing URL. A search result record carries the title, a description preview, price, the search page's own photo thumbnails, GPS coordinates, seller details and the category-specific attributes Kijiji shows on the listing; a pasted single-listing URL, or a search with Fetch listing details on, gets the full description text and the complete photo set instead. Switch on Incremental mode for recurring monitoring, download to JSON, CSV or Excel, or pull results straight into your app through the API.
Why This Scraper?
- Every category, one actor. The extractor adapts automatically to property, vehicles and general classifieds, so the same run handles an apartment search and a car search alike.
- Rich records from the search page alone. 20+ fields per listing straight off the results page, including a description preview, the search page's own photo thumbnails and GPS coordinates, no extra fetch required. Turn on Fetch listing details, or paste a single-listing URL, for the full description text and the complete photo set.
- Optional detail enrichment. Switch on view counts, seller phone and website, listing status, virtual tour or video, and dealer profile per run.
- Two ways in. Search by keyword and location across any Canadian city, region or province, or paste Kijiji search, category or single-listing links directly.
- Price and sort filters that actually narrow. Minimum and maximum price apply to a keyword search and a pasted URL alike, and a run walks the whole result set with no artificial page ceiling unless you set one.
- Built for recurring monitoring. Turn on Incremental mode to get only new, updated or reappeared listings on a schedule, or paste a previous run's id to collect just what's new since then.
- Recovers on its own. A run resumes from where it stopped after a platform migration or a manual restart, with no duplicate rows or duplicate charges, and automatically retries with a different connection when one is refused.
Use Cases
- Marketplace resellers and pickers: track new and price-dropped listings across categories to source inventory worth flipping.
- Rental and real estate research: monitor new property listings in a neighbourhood, with price, layout attributes and photos, and get alerted only when something changes.
- Car shopping and dealer tracking: filter listings by price and body type, then watch a saved search for new inventory instead of refreshing the site by hand.
- Local services and gig marketplaces: pull job or services listings for a city to track posting volume and going rates.
- Market and pricing analysts: build a historical price dataset per category and region for trend analysis.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
id | "1700000000" |
listingType | "AutosListing" (also "RealEstateListing", "StandardListing", ...) |
title | "Sample listing title" |
description | "Full listing description appears here." |
url | "https://www.kijiji.ca/v-cars-trucks/city-of-toronto/sample-listing/1700000000" |
price / priceType | 12500.0 / "FIXED" |
currency | "CAD" |
categoryId | 174 |
locationName | "Toronto" |
address | "1 Placeholder Crescent, Toronto, ON, M0M 0M0" |
latitude / longitude | 43.65 / -79.4 |
imageUrls / imageCount | one URL per photo (thumbnails from the search page, or the full set with Fetch listing details on) / 8 |
posterId | "1700000001" |
sellerType | "PVT" |
posterRating / posterVerified | 4.5 / false |
activationDate | "2026-01-01T00:00:00.000Z" |
isTopAd | false |
attr_carmake / attr_noofseats | "ford" / "4" |
views | 342 |
phoneNumber | "4165550123" |
sellerWebsiteUrl | "https://example.com" |
Category-specific facts arrive as attr_* keys (for example attr_carmake, attr_numberbedrooms, attr_dateavailable), plus the complete raw attribute list in attributesRaw, so no field is ever dropped; a property, vehicle or general-classifieds listing carries the same shell shape, only the attr_* keys differ. With detail enrichment on, a listing can also carry status, listingTypeOffer, endDate, virtualTourUrl, youtubeVideoId, requestViewingUrl, mlsAd and, for a dealer or agency account, a commercialProfile object (business name, listing count, website, verification). In Incremental mode, every record also carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields, firstSeenAt and lastSeenAt.
How to Use
- Pick a mode:
search(keyword + location) orurl(paste links). - Fill in the fields for that mode, and set any price filter or sort order you need.
- Set Max listings (and, optionally, Max pages) to control run size and cost, then click Start.
- Download the dataset as JSON, CSV or Excel, or read it through the API.
Search a keyword in one city:
{"mode": "search","keywords": ["iphone"],"location": "city-of-toronto","maxListings": 50}
Search with a price range and sort order:
{"mode": "search","keywords": ["laptop"],"location": "vancouver","minPrice": 200,"maxPrice": 800,"sortBy": "priceAsc","maxListings": 20}
Browse every listing in a location, no keyword, with details on:
{"mode": "search","keywords": [],"location": "calgary","fetchDetails": true,"maxListings": 30}
Paste Kijiji category or listing URLs directly:
{"mode": "url","urls": ["https://www.kijiji.ca/b-apartments-condos/city-of-toronto/c37l1700273","https://www.kijiji.ca/b-cars-trucks/city-of-toronto/c174l1700273"],"maxListings": 100}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/kijiji-scraper").call(run_input={"mode": "search","keywords": ["iphone"],"location": "city-of-toronto","maxListings": 50,})for listing in client.dataset(run["defaultDatasetId"]).iterate_items():print(listing["title"], listing["price"], listing["url"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/kijiji-scraper').call({mode: 'search',keywords: ['iphone'],location: 'city-of-toronto',maxListings: 50,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
How Max pages and Max listings shape a run
Max pages bounds how many result pages are walked per search or pasted URL (40 listings per page); 0 walks until the run stops on its own, at the reported total, an empty page, or a page that returns nothing new to that walk. Max listings is the one setting that bounds how many listings are saved for the whole run; 0 collects everything available (paid plans only), limited only by Max pages and the natural end of results. A pasted single-listing URL returns at most one record (a price filter, a Resume-seeded id, or an UNCHANGED classification in Incremental mode can drop it to zero). With Fetch listing details on (the default), the full description text and complete photo set are always included; a handful of search-only fields are not available from the listing page itself and come back null, including imageCount (the photos in imageUrls are still complete), posterRating, nearestIntersection, hasVirtualTour, and every attr_*_label field (the labels for category-specific attributes, which only the search page's own filter metadata supplies). With detail off, a pasted single-listing URL still returns the full description and photo set, since the listing page has to be read either way to identify the listing; it drops the flat detail-only fields (views, status, and similar), but the nested posterInfo object, which can include the seller's phone number and website, is still copied through in full either way, so switching detail off does not withhold seller contact info for a pasted listing link the way it does for a search result.
Resume, automatic recovery, and Incremental mode
These are three separate features:
-
resumeFromRunIdcontinues one specific prior run (or dataset) as a delta: paste its run or dataset id and this run skips every listing already collected there, walking the full search again but returning, and charging for, only what's new. A page made entirely of listings you already have does not stop the walk early; it keeps going until it reaches genuinely new listings or the natural end of the search. -
Automatic recovery needs no input at all: if the platform migrates the run or it is manually restarted, the run picks its checkpoint back up (same search position, same collected ids) and continues, so a restart never re-collects or re-charges a listing already pushed.
-
Incremental mode (
incrementalMode) is for a search or URL list you run on a schedule. Each listing is classified against the actor's own memory of the last run for that search:changeTypeWhen it fires NEWNot seen in any previous run for this search. UPDATEDSeen before, and at least one field genuinely changed ( changedFieldslists which).UNCHANGEDSeen before, nothing changed. Not returned by default; turn on emitUnchangedto get it anyway.REAPPEAREDThe listing was previously marked gone by an EXPIRED run for this search, and has now been scraped again. EXPIREDPreviously seen, not found in this run, and this run reached the natural end of every tracked search/URL. Only produced when emitExpiredis on.emitExpiredgates more than which rows you see: only a run withemitExpiredon, that also scans its whole tracked search or URL list to the natural end (nomaxListings/maxPagescap reached, noresumeFromRunId, no page that failed to load), ever marks a listing as gone in the actor's memory. If that condition is never met, a listing that stops appearing simply keeps its last-known status; it is never silently marked gone, andREAPPEAREDcan therefore never fire for it either.REAPPEAREDonly exists at all for a listing that some earlier run had already marked gone this way, and is now back.viewsandsortingDatenever trigger a falseUPDATED(Kijiji advances both independently of any real edit); every other field, includingpriceanddescription, participates.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape; the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | Search by keyword + location, or paste Kijiji URLs directly. |
keywords | array | (none; prefilled with ["iphone"]) | Search terms (Search mode). Each term runs as its own all-category search. Empty browses everything in the location. |
location | string | canada (prefilled with city-of-toronto) | City, region, or province name, a Kijiji location slug, or a numeric location id. |
sortBy | string | relevance | Result ordering: relevance, newest first, price low to high, or price high to low. Search mode only; Kijiji still inserts a few promoted ads at the top regardless of sort. |
urls | array | (none; prefilled with a sample URL) | Kijiji search, category or single-listing URLs (URL mode). Multiple supported; pagination walks forward from the page in each URL. |
minPrice | integer | (none) | Minimum price in Canadian dollars. Applies to Search mode and URL mode alike. Once either bound is set, a listing with no numeric price (e.g. "Please Contact", "Free", "Swap") is dropped. |
maxPrice | integer | (none) | Maximum price in Canadian dollars. Applies to Search mode and URL mode alike; see minPrice for the no-price-listing behavior. |
fetchDetails | boolean | true | Open each listing's detail page for view count, seller phone + website, listing status, virtual tour / video, and dealer profile. |
maxPages | integer | 0 | Optional bound on result pages walked per search/URL (40 listings per page). 0 walks until the run stops on its own: the reported total is reached, a page comes back empty, or a page returns nothing new to that walk. Does not cap how many listings are saved; use Max listings for that. |
maxListings | integer | 20 | Maximum listings to save across the whole run. 0 collects every available listing (paid plans only), bounded only by Max pages and the natural end of results. |
resumeFromRunId | string | (none) | ID of a previous run (or dataset) of this actor. Listings already there are skipped, so this run returns only new listings (a delta). |
incrementalMode | boolean | false | Recurring monitoring: remembers the listings seen last time for this search and, by default, returns only NEW, UPDATED or REAPPEARED ones. |
stateKey | string | (none; derived automatically from your filters) | Optional label for the tracked search when Incremental mode is on. |
emitUnchanged | boolean | false | Incremental mode only: also return UNCHANGED listings (the full snapshot every run). |
emitExpired | boolean | false | Incremental mode only: also return EXPIRED listings, and only when this run reached the natural end of every tracked search/URL. |
proxy | object | Apify Residential, country CA | Connection settings. Kijiji.ca works most reliably on a Canadian residential connection. |
mcpConnectors | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which records are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. Does not affect the dataset. |
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"id": "1700000000","listingType": "AutosListing","title": "Sample listing title","description": "Full listing description appears here.","url": "https://www.kijiji.ca/v-cars-trucks/city-of-toronto/sample-listing/1700000000","price": 12500.0,"priceRaw": 1250000,"priceType": "FIXED","currency": "CAD","categoryId": 174,"locationName": "Toronto","address": "1 Placeholder Crescent, Toronto, ON, M0M 0M0","latitude": 43.65,"longitude": -79.4,"nearestIntersection": ["Sample Road", "Example Avenue"],"imageUrls": ["https://media.kijiji.ca/api/v1/ca-prod-fsbo-ads/images/00/00000000-0000-0000-0000-000000000000?rule=kijijica-200-jpg"],"imageCount": 8,"posterId": "1700000001","sellerType": "PVT","posterRating": 4.5,"posterVerified": false,"activationDate": "2026-01-01T00:00:00.000Z","isTopAd": false,"attr_carmake": "ford","attr_noofseats": "4","views": 342,"status": "ACTIVE","phoneNumber": "4165550123","sellerWebsiteUrl": "https://example.com"}
Plan Requirement
Kijiji.ca is most reliable over a Canadian residential connection. The default proxy setting is Apify Residential with country CA, which requires an Apify Starter plan or higher; datacenter connections are frequently refused by the site. The run automatically retries with a different connection when one is refused. A run that cannot reach Kijiji.ca at all still finishes successfully, with zero listings and a status message pointing at the proxy setting, rather than exiting as an error.
FAQ
How much does it cost?
You pay per listing returned, plus a separate detail-enrichment charge only for listings whose detail page was actually opened and pushed (turned on by Fetch listing details). Suppressed Incremental-mode rows (UNCHANGED, by default) are never billed. The Pricing tab shows the current rates; use Max listings to cap the cost of any run.
Is it legal to scrape Kijiji.ca?
This actor collects only publicly available classified-listing data. You are responsible for how you use it: follow Kijiji's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution, especially of seller contact details.
Can I get only new or changed listings on a schedule?
Yes. Schedule the actor and turn on Incremental mode. See "Resume, automatic recovery, and Incremental mode" above for exactly when REAPPEARED and EXPIRED can occur; a quiet run with nothing changed can legitimately return zero listings, which is not an error.
Why did my run return fewer listings than I expected?
Max listings and Max pages both cap a run; raise them, or set Max listings to 0, to collect more. A price filter also drops any listing with no numeric price (e.g. "Please Contact", "Free", "Swap") once either bound is set.
Why does a fully blocked run finish "succeeded" with zero listings instead of failing?
An empty result really can mean nothing matched, so a run that scans nothing still finishes successfully rather than exiting as an error; the run's status message explains what happened and recommends a Canadian residential connection. If you're automating this, check the returned listing count (or the status message) rather than only the run status.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more classifieds data?
Pair this actor with these related scrapers from the same team:
| 🏷️ Leboncoin FR Pull public leboncoin.fr listings across cars, property, jobs, electronics, furniture... | 🏷️ Mudah.my Cars, Property, Jobs & Marketplace Scraper Scrape Mudah.my listings across every category: cars, motorcycles, property, mobiles... |
| 🏷️ Subito.it Scrape Subito.it listings across cars, real estate, marketplace, jobs, and more. Search... | 🏷️ Tutti.ch Scrape listings from tutti.ch across all 23 categories, including vehicles, property... |
| 🚗 Willhaben.at Scraper From $1/1K. Scrape Willhaben.at listings into clean JSON with 40+ structured fields... | 🏷️ Daangn Scraper From $1/1K. Scrape Daangn (당근) marketplace listings by keyword and region. Returns 35+... |
💬 Support & custom scrapers
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com or message Telegram @abotapi.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.