# Centris Scraper \[💰$1.3/1K] | Quebec MLS | Property Leads (`ahmed_jasarevic/centris-scraper`) Actor

Scrape Centris.ca — the Quebec real-estate MLS — for sale and rental listings with full property detail pages: Centris/MLS number, price, address and coordinates, room counts, living and lot area, year built, municipal assessment, taxes, listing broker contact details and photos.

- **URL**: https://apify.com/ahmed_jasarevic/centris-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 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

## Centris Scraper — Quebec MLS Listings, Property Details & Broker Data

Scrape **Centris.ca** — the Quebec real-estate MLS — for sale and rental listings with full property detail pages: Centris/MLS number, price, address and coordinates, room counts, living and lot area, year built, municipal assessment, taxes, listing broker contact details and photos, plus the complete raw characteristics and financial grids as label → value objects. Search by region, city, category and property type, or paste a Centris search URL directly.

Built for Quebec brokerages and lead-generation agencies, proptechs, mortgage and appraisal teams running CMA comps, and investors screening plexes and multi-unit buildings.

### Scrape Quebec MLS Listings For Market Research & Lead Generation

- **Quebec property lead generation** — broker name, title, agency and phone numbers on every listing
- **CMA comps and appraisal data** — price, municipal assessment, taxes, living area, lot area and year built in one row
- **Rental market research** — sale and rental listings side by side with `sellingType` filtering
- **Plex and multi-unit screening** — `propertyTypes` includes `Plex`, `MultiFamily` and `Intergenerational`
- **Building a Quebec property database** — the full raw `characteristics` and `financials` grids plus the mapped fields
- **Commercial market coverage** — `category: Commercial` with office, industrial and commercial property types

### How It Works

![How the Centris Scraper works: Quebec filters become listing rows with prices, assessments, taxes and broker contacts.](https://api.apify.com/v2/key-value-stores/oeuA0kLOyhbRM4fzt/records/how-it-works-centris.webp)

The Actor builds Centris's gzip and base64url q parameter from your filters, resolves regions through autocomplete and walks stateless search pages 20 listings at a time. Each listing page then supplies the characteristics, assessment, tax and broker details.

Each row combines the search card with the detail page: price, property type, address, room counts, areas, year built, taxes, broker contacts and photos. Use it to compare Quebec sale and rental inventory.

Centris.ca is an ASP.NET Core site behind Cloudflare. The public search UI is **server-rendered**, so the Actor reads the same requests the site's own frontend makes — no browser and no JavaScript rendering:

1. **Search query (`q` parameter).** Centris encodes its search state as a gzip + base64url JSON blob in the `q` URL parameter. The Actor builds that object directly (geography filters, `Category`, `SellingType`, `GeographicArea`).
2. **Region resolution.** Free-text regions are resolved to Centris geography IDs through the site's own autocomplete endpoint (`POST /Property/GetSearchAutoCompleteData`).
3. **Search results (stateless GET).** `GET https://www.centris.ca/en/<slug>?q=<q>&pageSize=20&page=N` returns plain HTML with 20 listing cards (`div.property-thumbnail-item`), each carrying schema.org microdata (`meta[itemprop=sku]`, `meta[itemprop=price]`, `meta[itemprop=name]`), address, beds/baths and coordinates. No cookies or session are required.
4. **Property detail pages.** Each card links to a server-rendered detail page with schema.org microdata, the characteristics grid (`.carac-container`), the financial-details tables (municipal assessment, taxes), the broker card (`.realtor-name`, `.realtor-type`, `.broker-info__agency-name`, `tel:` links) and the photo list (`#property-roomvo-data[data-photo-urls]`).

The search and detail endpoints return HTTP 200 to a normal desktop User-Agent — no Cloudflare challenge is encountered. Everything is stateless: no cookie jar, no session pool, no tokens.

### Input Parameters

| Field | Type | Required | Default | Notes |
| --- | --- | --- | --- | --- |
| `sellingType` | enum | No | `Sale` | `Sale`, `Rent` or `Both`. |
| `category` | enum | No | `Residential` | `Residential` or `Commercial`. |
| `regions` | array | No | whole province | Region or city names, e.g. `["Montreal", "Laval"]`. Empty means the whole province. |
| `propertyTypes` | array | No | all | e.g. `["Plex"]` for multi-unit buildings. |
| `searchUrls` | array | No | — | Centris.ca search-result URLs copied from your browser (the ones with the `q=` parameter). Scraped directly with automatic pagination; overrides the filters above. French `/fr/` URLs are switched to `/en/`. |
| `maxItems` | integer | No | `100` | Max listings to scrape. Search pages (20 listings each) are walked automatically until this many are collected. |
| `proxy` | object | No | off | Standard Apify proxy configuration; off by default. |

### Output Fields

One row per listing, combining the search card and the property detail page.

| Field | Description |
| --- | --- |
| `centrisNumber` / `mlsNumber` | Centris / MLS number. |
| `price`, `priceCurrency` | Asking price in CAD. |
| `category`, `propertyType`, `sellingType` | e.g. Residential / House / Sale. |
| `fullAddress`, `streetAddress`, `city`, `region` | Full address, city and administrative region. |
| `latitude`, `longitude` | Coordinates. |
| `bedrooms`, `bathrooms`, `rooms` | Room counts (plus raw text). |
| `livingArea`, `lotArea` | Living area and lot area. |
| `yearBuilt` | Year built. |
| `municipalAssessment` | Municipal assessment (lot / building / total). |
| `taxes` | Municipal and school taxes. |
| `brokerName`, `brokerTitle`, `brokerAgency`, `brokerPhones` | Listing broker details. |
| `photos`, `photosFull` | Photo URLs (thumbnail size and full size). |
| `characteristics`, `financials` | Full raw grids for anything not mapped above, as label → value objects. |

Free-plan runs return a 10-listing preview; paying runs return the full result set up to `maxItems`.

### Example Input

Scrape plexes (multi-unit buildings) in Montreal for sale:

```json
{
  "sellingType": "Sale",
  "category": "Residential",
  "regions": ["Montreal"],
  "propertyTypes": ["Plex"],
  "maxItems": 200
}
```

### Example Output

```json
{
  "centrisNumber": "24192056",
  "mlsNumber": "24192056",
  "price": 899000,
  "priceCurrency": "CAD",
  "category": "Residential",
  "propertyType": "Plex",
  "sellingType": "Sale",
  "fullAddress": "5423 Avenue du Parc, Montréal (Le Plateau-Mont-Royal), QC H2T 1X5",
  "streetAddress": "5423 Avenue du Parc",
  "city": "Montréal (Le Plateau-Mont-Royal)",
  "region": "Montréal",
  "latitude": 45.5241,
  "longitude": -73.5967,
  "bedrooms": 5,
  "bathrooms": 3,
  "rooms": 10,
  "livingArea": "2,500 sq. ft.",
  "lotArea": "2,500 sq. ft.",
  "yearBuilt": "1927",
  "municipalAssessment": {
    "lot": 612300,
    "building": 388400,
    "total": 1000700
  },
  "taxes": {
    "municipal": 6245,
    "school": 986
  },
  "brokerName": "Marie Tremblay",
  "brokerTitle": "Residential Broker",
  "brokerAgency": "Agence Immo Plateau",
  "brokerPhones": ["+1 514 555 0123"],
  "photos": ["https://media.centris-centris.ca/thumb/24192056_1.jpg"],
  "photosFull": ["https://media.centris-centris.ca/24192056_1.jpg"],
  "characteristics": {
    "Room": "5 bedrooms",
    "Bathroom": "3 washrooms",
    "Zoning": "Residential",
    "Parking": "Outdoor x 2"
  },
  "financials": {
    "Municipal assessment (lot)": "$612,300",
    "Municipal assessment (building)": "$388,400",
    "Municipal assessment (total)": "$1,000,700",
    "Municipal taxes": "$6,245 (2026)",
    "School taxes": "$986 (2025-2026)"
  }
}
```

### Automate Quebec Real Estate Monitoring With Schedules & Webhooks

- **Schedule the Actor** to re-crawl a region weekly and detect new listings, price changes and withdrawn properties.
- **Webhooks** — configure a run-success webhook so each finished run POSTs to n8n, Make or Zapier and lands in a CRM or spreadsheet.
- **Apify API** — pull the dataset programmatically with the JavaScript or Python client, or export JSON / CSV / Excel from the console.
- Recurring runs keep a Quebec property database current; new listings appear and prices change constantly.

### Related Actors

- [Centris.ca Scraper — Quebec Real Estate Data & MLS API](https://apify.com/sian.agency/centris-ca-property-scraper) — Centris listings with region, city and polygon search.
- [Centris Scraper — Quebec Real Estate (MLS) by Region](https://apify.com/trepanat0r/centris-quebec) — Centris listings organized by Quebec region.
- [Centris.ca Scraper: Quebec Real Estate Listings & Photos](https://apify.com/fayoussef/centris-property-scraper) — Centris listings with photos at a low per-result price.
- [Zillow Scraper](https://apify.com/ahmed_jasarevic/zillow-scraper) — US listings, rentals and sold data from Zillow.
- [Rightmove Scraper](https://apify.com/ahmed_jasarevic/rightmove-scraper) — UK property listings with sold-price history from Rightmove.

### Frequently Asked Questions

#### Why use this Actor instead of the official Centris API?

Centris does operate a data-distribution service, but access is gated behind an OData-based API (`datadistributionqc.centris.ca`) that requires a Token and a signed authorization from a licensed brokerage — one agreement per brokerage. There is also a SOAP "service de diffusion" for the same authorized partners. This Actor instead reads the publicly visible search and detail pages, so anyone can start extracting Quebec MLS listings without a brokerage agreement, an API contract or a developer setup.

#### What are alternatives to Centris for Quebec real-estate data?

Three routes exist. First, Centris itself — it is the province's MLS and the canonical source for active Quebec listings, but it publishes no sold or historical prices. Second, licensed IDX/VOW data feeds resold by real-estate data aggregators, which are contractually limited to authorized brokerages. Third, self-serve scraping of the public search (this Actor and the ones in Related Actors). Zillow, Rightmove and Idealista cover other markets; nothing replaces Centris for Quebec specifically.

#### Can I get sold or historical listing prices from Centris?

No — Centris publishes active listings only. There is no sold-price history on Centris.ca, and this Actor returns what is currently listed. For sold-price history you would need a provincial land-registry source or a licensed data feed that aggregates them. The Actor does return `municipalAssessment` and `taxes` on every listing, which are useful for valuation work on active inventory.

#### Does Centris have an API I can call directly?

Centris has no open public API. Its data-distribution endpoints (the OData service and the SOAP "service de diffusion") require a Token issued to an authorized brokerage, and each brokerage must sign its own authorization agreement. The public website has no published developer documentation, so the search state must be reconstructed from the `q` parameter — which is exactly what this Actor does.

#### Can an AI agent call this Actor?

Yes. It is a standard Apify Actor, so any MCP client or agent can start a run through the Apify API or the Apify MCP server, wait for it to finish, and read the dataset items. The minimal input and output field list are in the next section.

#### How much does it cost?

Pay-per-event: one `result` event per listing returned ($1.30 per 1,000 listings), plus a small Actor-start event scaled by memory. There is no charge for search pages that return no listing.

### For AI Agents & LLM Apps

Purpose: return structured Quebec MLS listings (price, address, coordinates, room counts, areas, municipal assessment, taxes, broker contact, photos) from centris.ca as JSON rows.

Minimal input (residential sale listings in Montreal):

```json
{
  "sellingType": "Sale",
  "category": "Residential",
  "regions": ["Montreal"],
  "maxItems": 100
}
```

Variant — a browser-copied Centris search URL (the Actor recovers and applies its filters):

```json
{
  "searchUrls": ["https://www.centris.ca/en/properties~for-sale?query=..."],
  "maxItems": 200
}
```

Output fields (default dataset): `centrisNumber`, `mlsNumber`, `price`, `priceCurrency`, `category`, `propertyType`, `sellingType`, `fullAddress`, `streetAddress`, `city`, `region`, `latitude`, `longitude`, `bedrooms`, `bathrooms`, `rooms`, `livingArea`, `lotArea`, `yearBuilt`, `municipalAssessment`, `taxes`, `brokerName`, `brokerTitle`, `brokerAgency`, `brokerPhones`, `photos`, `photosFull`, `characteristics`, `financials`.

Behaviors an agent should know:

- There is no keyword-search input. The Actor builds the search state from `sellingType` + `category` + `regions` + `propertyTypes`, resolving region names to Centris geography IDs itself. An empty `regions` array means the whole province.
- `searchUrls` overrides every other filter — use it when you have a browser-built Centris search URL, especially for complex filters the typed inputs do not cover. A URL without a `q=` parameter still works: the state is recovered from the page's own links.
- `maxItems` defaults to 100; search pages are walked automatically at 20 listings per page. There is no page input.
- For exhaustive province-wide coverage, split the run by region — Centris caps how deep the paginated gallery goes for very large result sets.
- `characteristics` and `financials` are label → value objects with arbitrary keys, so read them generically.
- `municipalAssessment` and `taxes` are nested objects (lot/building/total; municipal/school) — they exist on detail pages, not on search cards.
- Free-plan runs are capped at a 10-listing preview.
- The per-room detail table (individual room dimensions) is loaded by a separate AJAX call and is not included; room/bedroom/bathroom counts and the characteristics grid are.

Billing: pay-per-event — one `result` event per listing returned ($1.30 / 1,000). Budget by listing count, not by page count, since search pages that yield no listing bill nothing.

### Legal & Compliance Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Centris or the Quebec Professional Association of Real Estate Brokers. It reads only publicly visible search and detail pages on centris.ca — no login, no account and no access to private or member-only data. Listing broker names, titles, agency affiliations and phone numbers are already displayed publicly on each listing page. You are responsible for your own compliance with Centris's Terms of Service and with applicable data-protection law (including Quebec's Law 25 and, where relevant, Canada's CASL and GDPR) — in particular before using broker contact details for commercial outreach.

### SEO Keywords

centris scraper, quebec real estate data, quebec mls listings, centris ca data export, montreal property data, quebec real estate listings scraper, property lead generation quebec, mls data quebec, real estate market research quebec, plex multi unit quebec, commercial listings quebec, property comps cma quebec, quebec rental listings, montreal real estate scraper, quebec housing data, residential listings quebec, commercial property scraper, real estate investor data, centris api alternative, quebec mls api, property database builder, real estate lead generation, housing market research, listing data export

# Actor input Schema

## `sellingType` (type: `string`):

Scrape properties for sale, for rent, or both.

## `category` (type: `string`):

Residential or commercial properties.

## `regions` (type: `array`):

Optional. One or more Quebec regions, cities or neighbourhoods, e.g. "Montreal", "Laval", "Quebec City", "Mont-Tremblant". Each is resolved to a Centris geography id. Leave empty to scrape the whole province.

## `propertyTypes` (type: `array`):

Optional. Restrict to specific property types. Valid values: SingleFamilyHome, SellCondo, RentCondo, LoftStudio, Plex, Intergenerational, MobileHome, HobbyFarm, Chalet, ResidentialLot, MultiFamily, Office, SaleIndustrial, RentIndustrial, SaleCommercial, RentCommercial, Accommodation, Agricultural, CommercialLot, Business. Leave empty for all types.

## `searchUrls` (type: `array`):

Optional. One or more Centris.ca search result URLs copied from your browser (the ones containing the q= parameter, e.g. https://www.centris.ca/en/properties~for-sale?q=...). When provided, these URLs are scraped directly (with automatic pagination, following each search until maxItems is reached) and the listing type / category / regions / property-types filters above are ignored. French /fr/ URLs are switched to /en/ automatically.

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

Maximum number of listings to scrape (each listing = 1 search card + 1 detail page). Search pages (20 listings each) are walked automatically until this many listings are collected.

## `proxy` (type: `object`):

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "sellingType": "Sale",
  "category": "Residential",
  "regions": [
    "Montreal"
  ],
  "maxItems": 100,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "regions": [
        "Montreal"
    ],
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/centris-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 = {
    "regions": ["Montreal"],
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/centris-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 '{
  "regions": [
    "Montreal"
  ],
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/centris-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/centris-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/sMzXn6F9h4vXA1bH7/builds/O8aQBYtlJTgKGA8FK/openapi.json
