Realtor.ca - Property Listings, Prices, Agents & Open Houses
Pricing
from $1.00 / 1,000 results
Realtor.ca - Property Listings, Prices, Agents & Open Houses
From $1/1K. Scrape Realtor.ca property listings with prices, descriptions, images, agent and brokerage details, coordinates, open house times, building features, and more.
Pricing
from $1.00 / 1,000 results
Rating
5.0
(2)
Developer
Abot API
Maintained by CommunityActor stats
4
Bookmarked
52
Total users
3
Monthly active users
7 days ago
Last modified
Categories
Share
Realtor.ca Scraper: Canadian Property Listings, Prices & Agent Details
Realtor.ca Scraper turns Realtor.ca, Canada's national property listing site, into a clean property data feed. Search any Canadian city and province, or paste a search URL you already refined on the site, and get full listing details: price, full address with coordinates, bedrooms and bathrooms, building features, every listing photo, and the listing agent's contact and brokerage details. Covers homes for sale, for rent, and recently sold, across residential, commercial, condo, multi-family, vacant land and more, then export to JSON, CSV or Excel, or pull results straight into your app through the API.
Why This Scraper?
- Two ways to search. Pick a city and province with filters, or paste a Realtor.ca search URL already refined in a browser.
- Every property category. Residential, commercial, condo, multi-family, vacant land, recreational, agriculture and parking listings, across all 13 Canadian provinces and territories.
- Full listing depth. Price, full address with coordinates, bedrooms, bathrooms, parking, land and building size, building features, and every listing photo.
- Agent and brokerage details on every listing. Name, phone, position, profile link, brokerage name, logo, website and phone.
- Built for schedules. Incremental mode returns only new and changed listings on recurring runs, and a genuine connection failure fails loudly instead of returning an empty dataset.
- Two independent ways to avoid rescraping. Continue one interrupted run from its run or dataset ID, or track a recurring search with Incremental mode.
Use Cases
- Real estate agents and investors: track new listings, price changes and sold comparables in target neighborhoods.
- Property portals and apps: feed listing search, pricing and photos into your own site or app.
- Market research and analytics: build historical pricing datasets by city, province and property type.
- Relocation and rental services: monitor rental listings and open houses across cities.
- Lead generation: collect agent and brokerage contact details tied to active listings.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
propertyId | "12345678" |
mlsNumber | "C1234567" |
url | Full listing URL on Realtor.ca |
listingType | "buy" (also "rent", "sold") |
propertyType | "condo" (also "apartment", "house", "townhouse", "duplex", "triplex", "fourplex", "multi-family", "modular", "vacant-land", "parking", "commercial", "farm", "other") |
buildingType | "Apartment" (raw building type as published) |
ownershipType | "Condominium/Strata" |
| Listing description text | Not included. realtor.ca returns the remarks field empty in search results and only serves it on the listing-detail endpoint, which refuses requests (HTTP 403). |
dateListed / timeOnRealtor | "2026-03-19T10:00:00.000Z" / "2 hours ago" |
communityName, statusId | Extra listing attributes, present only when realtor.ca publishes them for that listing (omitted otherwise, never estimated) |
address | full, street, city, province, postalCode |
coordinates | latitude, longitude |
price | display (formatted string), value (numeric CAD) |
features | bedrooms, bathrooms, parkingSpaces, parkingType, landSize, buildingSize, stories |
propertyFeatures | Building amenities and construction details, e.g. ["Central air conditioning", "Style: Bungalow"] |
tags | Listing tags shown on the site, e.g. ["Open House"] |
media | imageCount, images (high resolution photo URLs) |
agents | One entry per listing agent: name, phone, position, profile link, brokerage name, brokerage ID (organizationId), logo, website, phone |
openHouse | Upcoming open house entries: startTime, endTime, comments |
scrapedAt | "2026-03-19T12:00:00.000Z" |
changeType / changedFields / firstSeenAt / lastSeenAt | Only present when Incremental mode is on: "NEW", "UPDATED", "UNCHANGED", "REAPPEARED" or "EXPIRED", the fields that changed, and when the listing was first and last seen |
How to Use
- Pick a mode: Location (city and province, plus filters) or URL (paste one or more Realtor.ca search URLs).
- In Location mode, add one or more cities and set the filters you need: listing type, property category, building type, price, bedrooms, bathrooms, open house. In URL mode, paste the URL(s) instead; the filter fields above are ignored because the URL already carries them, but set Listing Type to match the URL since it labels each row's
listingType. - Set Maximum Listings and Maximum Pages per Location to control run size and cost.
- Click Start. Download the dataset as JSON, CSV or Excel, or read it through the API.
Houses for sale in Toronto, with price and bed/bath filters:
{"mode": "location","locations": [{ "city": "Toronto", "province": "ON" }],"listingType": "buy","propertySearchCategory": "residential","buildingTypeFilter": "house","priceMin": 500000,"priceMax": 1500000,"bedroomsMin": 3,"bathroomsMin": 2,"maxListings": 100}
Condos for rent across two cities:
{"mode": "location","locations": [{ "city": "Vancouver", "province": "BC" },{ "city": "Calgary", "province": "AB" }],"listingType": "rent","propertySearchCategory": "condo","maxListings": 50}
Recently sold listings in the last 90 days:
{"mode": "location","locations": [{ "city": "Montreal", "province": "QC" }],"listingType": "sold","soldWithinDays": "90days","maxListings": 200}
Paste a search URL refined on the site:
{"mode": "url","urls": ["https://www.realtor.ca/map#ZoomLevel=11&Center=43.718245%2C-79.376682&LatitudeMax=43.86034&LongitudeMax=-79.12303&LatitudeMin=43.57584&LongitudeMin=-79.63033&view=list&Sort=6-D&PGeoIds=g30_dpz89rm7&GeoName=Toronto%2C%20ON&PropertyTypeGroupID=1&TransactionTypeId=2&PropertySearchTypeId=1&Currency=CAD&IncludeHiddenListings=false","https://www.realtor.ca/on/toronto/real-estate"]}
Supported URL shapes
| Shape | Example | Behaviour |
|---|---|---|
| Map search URL | https://www.realtor.ca/map#ZoomLevel=11&LatitudeMax=... | Searches the exact area and filters in the URL. |
| City page | https://www.realtor.ca/on/toronto/real-estate | Searches the built-in area for that city (the same cities as Location mode); a city not in the list is skipped with a warning. |
Single listing page (/real-estate/<id>/<slug>) | not supported | Skipped with a warning; use a search URL. The listing-detail endpoint refused (HTTP 403) every request from a cleared session when tested, so a single page cannot be fetched reliably. |
City rent pages (realtor.ca/<province>/<city>/apartments-for-rent) are supported for the same built-in cities and search rentals; their rows come back with listingType set to rent and the rent in price (for example $3,400/Monthly, with the cadence in price.period). Single-listing pages and province landing pages (no listing cards) are not searched. Any URL that is not one of the supported shapes is skipped with a warning in the run log; it never falls back to a default search area. URL mode with the URLs field left empty searches two default areas in order, a Toronto map search and then the Vancouver city page (the Console form is prefilled with those two plus a Toronto rent page), and stops as soon as Max listings is reached. With the default Max listings (20) the Toronto map search alone fills the limit, so raise Max listings (or edit the URLs) to reach the Vancouver page.
Dataset views
The dataset has five ready-made tables: Overview (price, address, key features), Agents & Brokerages, Media & Open House, Changes (incremental) and Details (community, status, ownership and building type). Turn on Flat output for one-level records.
Cities with built-in coordinates
Location mode has a built-in, precise search area for 33 major Canadian cities (Toronto, Vancouver, Montreal, Calgary, Edmonton, Ottawa, Winnipeg, Halifax and more). Any other city is searched using a default area in southern Ontario plus the city and province name as a search term, so cities outside southern Ontario may return few or unrelated listings. For those, and for an exact area anywhere in Canada, draw it on the site and use URL mode instead.
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/realtor-ca-scraper").call(run_input={"mode": "location","locations": [{"city": "Toronto", "province": "ON"}],"listingType": "buy",})for listing in client.dataset(run["defaultDatasetId"]).iterate_items():print(listing["address"]["full"], listing["price"]["display"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/realtor-ca-scraper').call({mode: 'location',locations: [{ city: 'Toronto', province: 'ON' }],listingType: 'buy',});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Resume, Incremental mode and Checkpoint
Three independent controls that are easy to mix up:
- Resume from run/dataset ID continues ONE interrupted crawl: paste its run or dataset ID and this run skips every listing it already collected, so you don't pay twice.
- Incremental mode remembers a recurring search between separate scheduled runs. Each listing is classified
NEW,UPDATED(withchangedFields),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEARED, orEXPIRED(only after a run that scans the whole search, and only withemitExpiredon).stateKeynames or shares the stored baseline. Use Ignore fields when detecting changes to name fields that should never triggerUPDATED; the relative "time on realtor.ca" text is ignored by default. - Resume from Checkpoint continues THIS SAME run after a platform migration or restart. It is on by default and does not change billing or output shape.
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 listing, 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 listing pages 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 | location | Search mode: location (city and province, plus filters) or url (paste Realtor.ca search URLs). |
locations | array | (none; prefilled with Toronto, ON) | Cities to search in Location mode. Each entry needs a city and a two-letter province code, e.g. ON. |
listingType | string | buy | buy (for sale), rent, or sold. |
propertySearchCategory | string | residential | Property category: residential, commercial, condo, multi-family, vacant-land, recreational, agriculture, or parking. |
buildingTypeFilter | string | (none) | Optional building type within the selected category: house, row-townhouse, or apartment. Location mode only. |
priceMin | integer | (none) | Minimum price in CAD. Location mode only. |
priceMax | integer | (none) | Maximum price in CAD. Location mode only. |
bedroomsMin | integer | (none) | Minimum bedrooms, 0 to 10. Location mode only. |
bedroomsMax | integer | (none) | Maximum bedrooms, 0 to 10. Location mode only; applies only together with bedroomsMin. |
bathroomsMin | integer | (none) | Minimum bathrooms, 0 to 10. Location mode only. |
sortBy | string | 6-D (Newest) | Sort order: Newest, Oldest, Lowest Price, or Highest Price. |
soldWithinDays | string | 1year | Date range for sold listings: 7days, 14days, 30days, 90days, 6months, or 1year. |
openHouseOnly | boolean | false | Only return listings with an upcoming open house. Location mode only. |
keywords | string | (none) | Not currently applied to Location mode searches, which always search by city and province. To search by keyword, add it on Realtor.ca and paste the URL in URL mode. |
urls | array | one map search URL (Toronto) and one city page URL (Vancouver) | Realtor.ca map search URLs or city pages, used in URL mode. |
maxListings | integer | 20 | Stop after this many listings (0 = unlimited). |
maxPages | integer | 0 | Maximum search result pages per location, about 12 listings each (0 = every page, with a hard cap of 1000 pages per location). |
proxyConfiguration | object | Apify residential proxy, country CA | Connection settings. |
resumeFromRunId | string | (none) | Paste a previous run or dataset ID to continue one interrupted crawl, skipping listings it already collected. |
incrementalMode | boolean | false | Track a recurring search across scheduled runs and classify each listing as NEW, UPDATED, REAPPEARED, EXPIRED or UNCHANGED. |
stateKey | string | (none) | Optional label for the Incremental mode baseline; auto-derived from your search when left empty. |
emitUnchanged | boolean | false | Incremental mode: also return (and bill) listings with no changes. |
simplifyOutput | boolean | false | Return flat records (addressCity, priceValue, featuresBedrooms, first agent as agentName/agentPhone) instead of nested objects. Same listings and billing. |
emitExpired | boolean | false | Incremental mode: also return (and bill) listings that disappeared, once, after a complete scan. |
ignoreFieldsForChanges | array | [] | Incremental mode: field names that never make a listing UPDATED (matched at any nesting depth, still returned in the output). timeOnRealtor, its mirrored entries in tags and scrapedAt are always ignored because they change every run. |
resumeFromCheckpoint | boolean | true | Resume this same run from its last checkpoint after a platform migration or restart. |
mcpConnectors | array | (none) | Optional: send a summary of each listing to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which listing pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"propertyId": "12345678","mlsNumber": "C1234567","url": "https://www.realtor.ca/listing/12345678/100-sample-street-toronto","listingType": "buy","propertyType": "condo","buildingType": "Apartment","ownershipType": "Condominium/Strata","dateListed": "2026-03-19T10:00:00.000Z","timeOnRealtor": "2 hours ago","tags": ["Open House"],"address": {"full": "100 SAMPLE STREET|Toronto, Ontario M5A 1A1","street": "100 SAMPLE STREET","city": "Toronto","province": "Ontario","postalCode": "M5A1A1"},"coordinates": {"latitude": 43.65,"longitude": -79.38},"price": {"display": "$850,000","value": 850000},"features": {"bedrooms": 2,"bathrooms": 2,"parkingSpaces": 1,"parkingType": "Underground, Garage","buildingSize": "90 m2"},"propertyFeatures": ["Storage locker","Floor Area: 900+ sqft","Parking: Underground, Garage"],"media": {"imageCount": 1,"images": ["https://cdn.realtor.ca/listings/sample/highres/1/sample_1.jpg"]},"agents": [{"name": "Sample Agent","phone": "(416) 555-0100","position": "Broker of Record","profileUrl": "https://www.realtor.ca/agent/100001/sample-agent","organization": "Sample Realty Inc.","organizationId": "100200","organizationDesignation": "Brokerage","organizationWebsite": "http://www.example-realty.ca/","organizationPhone": "(416) 555-0200"}],"scrapedAt": "2026-03-19T12:00:00.000Z"}
Plan Requirement
This site refuses datacenter connections and plain scripted requests, so the actor needs Apify residential proxies with country Canada (the default). Datacenter proxies are not expected to work: the run log says "Using a datacenter proxy. This site usually refuses datacenter connections. Use the default RESIDENTIAL proxy with country CA for reliable runs." Residential proxies are not included in the Apify free plan. Leave Proxy configuration at its default. The actor retries and rotates connections when one is refused, and stops early (keeping what it collected) with "Too many consecutive upstream refusals, stopping this run early" when the site keeps refusing.
FAQ
How much does it cost?
You pay per listing returned. The Pricing tab on the actor page shows the current rate. Use Maximum Listings to cap the size, and cost, of any run.
Is it legal to scrape Realtor.ca?
This actor collects only publicly available property listing data. You are responsible for how you use it: follow Realtor.ca's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Agent and brokerage names are included because that information is published alongside each listing.
Can I get only new or changed listings on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run classifies every listing as NEW, UPDATED, REAPPEARED, EXPIRED or UNCHANGED against the last committed run for that search, and unchanged listings are not billed unless you turn on Emit unchanged listings.
What is the difference between Resume from run/dataset ID, Incremental mode, and Resume from Checkpoint?
They solve three different problems. Resume from run/dataset ID continues one specific interrupted run so you don't rescrape listings it already collected. Incremental mode tracks the same search across separate scheduled runs and reports what changed. Resume from Checkpoint (on by default) simply lets one run recover its own progress after a platform migration or restart. Use any combination, or none.
Why did my run fail instead of returning an empty dataset?
Apart from invalid input or a resume ID that can't be read, the run fails only when nothing could be collected and the site could not be reached at all: either connection setup was rejected on every available proxy tier, or a search's result page never came back readable. In that case it exits with an error and a clear status message; wait a few minutes and try again, or switch Connection to residential with country CA. If the site was reachable but genuinely has no listings matching your search and filters, the run finishes successfully with an empty dataset and a "No results found" status message instead.
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 listing summaries into Notion, Linear or Airtable.
🔗 Want more Realtor data?
Pair this actor with these related scrapers from the same team:
| 🏠 Realtor.com From $0.9/1K. Extract property listings from realtor.com. Get comprehensive data... | 🧩 Homes.com Scraper Scrape US property records from Homes.com. Pick a city, state or ZIP and a channel (for... |
| 🏠 Real Estate AU Extract detailed Australian real estate property listings with 30+ structured fields... | 🏠 Trulia Scraper Scrape Trulia.com property listings by location, filters, or URL. Extract prices, beds... |
| 🏠 Homes.co.nz Scraper Scrape Homes.co.nz listings by location or URL with pagination. Extract property details... | 🏠 Crexi Scraper Scrape crexi.com commercial listings: asking price, cap rate, square footage, units, year... |
💬 Support
- 🐞 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.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.