# Centris Canada Property Scraper (`xtracto/centris-property-scraper`) Actor

Scrape real-estate listings from Centris.ca across Quebec and Canada. Paste a Centris search URL or pick filters to pull price, address, beds/baths, broker and agency, map coordinates, year built, living area, parking, and every photo.

- **URL**: https://apify.com/xtracto/centris-property-scraper.md
- **Developed by:** [Farhan Febrian Nauval](https://apify.com/xtracto) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.33 / 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/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 Canada Property Scraper

Extract real-estate listings from **Centris.ca** — Quebec's official MLS marketplace — into clean, structured JSON. Paste a Centris search link (or pick a few filters) and get every matching property with price, address, beds and baths, the listing broker and agency, map coordinates, year built, living area, parking, and the full photo set.

### Why use this actor

- **No account, no login, no API key** — just paste a search URL and run.
- **Full listing detail** — beyond the search card: broker name and agency, exact map coordinates, room counts, year built, living area, parking, move-in date, and every listing photo.
- **Works from a normal Centris search** — filter on the site the way you already do (region, property type, price, bedrooms…), copy the URL, and the actor reproduces that exact search.
- **French accents preserved** — city and street names come out correctly (e.g. *Montréal*, *Côte-de-Liesse*), ready for databases and spreadsheets.
- **Stable JSON output** suitable for pipelines, CRMs, and analysis, with automatic retries built in.
- Export to **JSON, CSV, or Excel**, or run it on a schedule.

### How it works

1. Paste one or more Centris search-results URLs, or choose a category, selling type, property type, and region.
2. The actor reproduces your search and walks through every results page.
3. For each listing it collects the summary data (price, address, beds/baths, photo).
4. With **Fetch full listing details** on, it opens each property page to add broker and agency, map coordinates, characteristics, and the complete photo gallery.
5. Every property is saved as one row in the dataset.

You don't manage any scrapers, browsers, or blocks — just provide a search and collect the results.

### Input

```json
{
  "searchUrls": [
    "https://www.centris.ca/en/houses~for-sale~montreal-island?q=H4sIAAAAAAAACl2PQWvCQBCF_8uec7BFPPRWhEYRSukWL-JhTF6SwYkbZmPLIvnvnaBC9Dbv...&v=2"
  ],
  "fetchDetail": true,
  "maxItems": 100,
  "maxItemsPerSearch": 1000,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "CA"
  }
}
```

Or drive it with structured filters instead of a URL:

```json
{
  "category": "Residential",
  "sellingType": "Sale",
  "propertyType": "SingleFamilyHome",
  "geographicArea": "GSGS4621",
  "fetchDetail": true,
  "maxItems": 100
}
```

| Field | Type | Description |
| --- | --- | --- |
| `searchUrls` | array of strings | One or more Centris.ca search-results URLs. Apply filters on Centris, copy the address-bar URL, and paste it here. All your on-site filters are preserved. Takes priority over the structured filters below. |
| `category` | string | Used only when no search URLs are given. `Residential` or `Commercial`. |
| `sellingType` | string | Used only when no search URLs are given. `Sale` (for sale) or `Rent` (for rent). |
| `propertyType` | string | Used only when no search URLs are given. E.g. single-family home, condo, plex, land. |
| `geographicArea` | string | Used only when no search URLs are given. A Centris region code (e.g. `GSGS4621` = Montreal Island). Leave blank to search all of Quebec. |
| `fetchDetail` | boolean | Open each listing page for broker, agency, map coordinates, characteristics, and the full photo set. Default `true`. Turn off for a faster, lighter run. |
| `maxItems` | integer | Stop after this many listings across all searches. `0` = no limit. Default `100`. |
| `maxItemsPerSearch` | integer | Cap per individual search. Default `1000`. |
| `proxyConfiguration` | object | Residential Canadian proxies recommended for larger runs. |

### Output

One row per listing:

```json
{
  "_source": "S1-centris-api+detail",
  "_scrapedAt": "2026-07-09T20:29:25Z",
  "_input": "https://www.centris.ca/en/houses~for-sale~montreal-island?q=...",
  "mlsId": "10882160",
  "url": "https://www.centris.ca/en/houses~for-sale~westmount/10882160",
  "price": 3900000,
  "priceLabel": "$3,900,000",
  "propertyType": "SingleFamilyHome",
  "category": "House for sale",
  "sellingType": "Sale",
  "address": "563, Avenue Victoria, Westmount",
  "city": "Westmount",
  "bedrooms": 4,
  "bathrooms": 4,
  "rooms": "14 rooms",
  "brokerNames": ["Christina Miller"],
  "agency": "PROFUSION IMMOBILIER INC.",
  "latitude": 45.481564,
  "longitude": -73.608625,
  "description": "14 rooms 4 bedrooms (1 in basement) 3 bathrooms and 1 powder room",
  "characteristics": {
    "yearBuilt": "1922, Century",
    "livingArea": "4,067 sqft",
    "parking": "Driveway (3)",
    "style": "Two or more storey, Detached",
    "moveInDate": "60 days after acceptance of promise to purchase or rent"
  },
  "images": [
    "https://mspublic.centris.ca/media.ashx?id=ADDD250DADBEE7CDDDDDDDDDDD",
    "https://mspublic.centris.ca/media.ashx?id=ADDD250DDDD9398DDDDDDDDDDA",
    "… 64 more"
  ],
  "thumbnail": "https://mspublic.centris.ca/media.ashx?id=ADDD250DADBEE7CDDDDDDDDDDD&t=pi&w=320&h=240&sm=c"
}
```

| Field | Type | Description |
| --- | --- | --- |
| `_source` | string | Where the row came from (`S1-centris-api` or `S1-centris-api+detail`). |
| `_scrapedAt` | string | UTC timestamp when the row was collected. |
| `_input` | string | The search URL or filter set that produced this row. |
| `mlsId` | string | Centris MLS listing number. |
| `url` | string | Direct link to the listing page. |
| `price` | integer | Asking price (or monthly rent), digits only. |
| `priceLabel` | string | Price as displayed, e.g. `$3,900,000`. |
| `propertyType` | string | Property type from the search. |
| `category` | string | Listing category, e.g. `House for sale`. |
| `sellingType` | string | `Sale` or `Rent`. |
| `address` | string | Street and city. |
| `city` | string | City / municipality. |
| `bedrooms` | integer | Number of bedrooms. |
| `bathrooms` | integer | Number of bathrooms. |
| `rooms` | string | Total room count (detail only). |
| `brokerNames` | array | Listing broker name(s) (detail only). |
| `agency` | string | Real-estate agency (detail only). |
| `latitude` | number | Map latitude (detail only). |
| `longitude` | number | Map longitude (detail only). |
| `description` | string | Room / bed / bath summary (detail only). |
| `characteristics` | object | Year built, living area, parking, building style, move-in date (detail only). |
| `images` | array | All listing photo links (detail only). |
| `thumbnail` | string | Primary photo link. |

### Notes & limits

- **`brokerNames`, `agency`, `latitude`, `longitude`, `rooms`, `description`, `characteristics`, and `images` are collected only when `fetchDetail` is on.** With it off you still get MLS number, price, address, city, beds/baths, and the thumbnail — much faster.
- **A single search returns up to ~5000 listings.** For a region with more inventory, split it into several searches (by sub-region or price range) and pass them all in `searchUrls`.
- **Region codes** (e.g. `GSGS4621` = Montreal Island) are embedded in every Centris search URL — the easiest way to target a region is to paste its search URL.
- For large runs, enable **Residential** proxies with country **Canada** for the most reliable results.

### Other real-estate actors

Part of a real-estate collection that also includes Redfin, Realtor, Zillow, Rightmove, Zoopla, Idealista, Immobiliare, Daft.ie, and mobile.de scrapers.

# Actor input Schema

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

Paste one or more Centris.ca search-results URLs. Open Centris, apply your filters (region, property type, price, etc.), copy the address-bar URL and paste it here. All of your on-site filters are preserved. When provided, these take priority over the structured filters below.

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

Used only when no search URLs are provided. The broad listing category.

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

Used only when no search URLs are provided. For sale or for rent.

## `propertyType` (type: `string`):

Used only when no search URLs are provided. The kind of property to list.

## `geographicArea` (type: `string`):

Used only when no search URLs are provided. A Centris region code (e.g. GSGS4621 = Montreal Island). Find codes inside any Centris search URL. Leave blank to search all of Quebec.

## `fetchDetail` (type: `boolean`):

Open each listing page for map coordinates, broker name(s), agency, room counts, year built, living area, parking, and the full photo set. Turn off for a faster, lighter run (coordinates and broker/agency will then be empty).

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

Stop after this many listings across all searches. Set 0 for no limit.

## `maxItemsPerSearch` (type: `integer`):

Cap per individual search URL / filter set. A single Centris search returns at most ~5000 listings; split by region or price to go beyond that.

## `maxConcurrency` (type: `integer`):

How many searches to run in parallel.

## `proxyConfiguration` (type: `object`):

Residential Canadian proxies are recommended for reliable IP rotation on larger runs.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.centris.ca/en/houses~for-sale~montreal-island?q=H4sIAAAAAAAACl2PQWvCQBCF_8uec7BFPPRWhEYRSukWL-JhTF6SwYkbZmPLIvnvnaBC9DbvzfcNuxfXSnRvbuYyd9BwhC5DCSssh6riAhukazxH5Ai1Utck31AH82aZi-O4ZfxZ3O0tg7RoPqm9XalYeuhtWTGkjFuS82jvLtdiXRq6pB510GTK77i36huRS5x6JnFDNoU9RPhU_6QOE96T4An80tBB-_RMmiz4oJYlrYI99dG6_5OLdwVNvNznfr54fXHDfvgHvFq9zjsBAAA&v=2"
  ],
  "category": "Residential",
  "sellingType": "Sale",
  "propertyType": "SingleFamilyHome",
  "geographicArea": "GSGS4621",
  "fetchDetail": true,
  "maxItems": 100,
  "maxItemsPerSearch": 1000,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "CA"
  }
}
```

# Actor output Schema

## `mlsId` (type: `string`):

Mls Id as reported by the source.

## `address` (type: `string`):

Street address.

## `city` (type: `string`):

City.

## `price` (type: `string`):

Price of the item. Numeric value.

## `bedrooms` (type: `string`):

Bedrooms.

## `bathrooms` (type: `string`):

Bathrooms.

## `propertyType` (type: `string`):

Property Type as reported by the source.

## `agency` (type: `string`):

Agency as reported by the source.

## `url` (type: `string`):

Direct link to the scraped item.

## `_scrapedAt` (type: `string`):

UTC timestamp of the scrape, ISO 8601.

## `priceLabel` (type: `string`):

Price Label as reported by the source.

## `rooms` (type: `string`):

Rooms.

## `brokerNames` (type: `string`):

Broker Names.

## `latitude` (type: `string`):

Latitude. Numeric value.

## `longitude` (type: `string`):

Longitude. Numeric value.

## `description` (type: `string`):

Short description or summary.

## `characteristics` (type: `string`):

Characteristics.

## `images` (type: `string`):

Image URLs. List of values.

## `thumbnail` (type: `string`):

Thumbnail image URL.

## `_source` (type: `string`):

Which extraction strategy produced the row.

## `_input` (type: `string`):

The input value this row was produced from.

## `_error` (type: `string`):

Set only on diagnostic rows - why that target produced no data.

## `_errorDetail` (type: `string`):

Extra context for the error.

# 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 = {
    "searchUrls": [
        "https://www.centris.ca/en/houses~for-sale~montreal-island?q=H4sIAAAAAAAACl2PQWvCQBCF_8uec7BFPPRWhEYRSukWL-JhTF6SwYkbZmPLIvnvnaBC9DbvzfcNuxfXSnRvbuYyd9BwhC5DCSssh6riAhukazxH5Ai1Utck31AH82aZi-O4ZfxZ3O0tg7RoPqm9XalYeuhtWTGkjFuS82jvLtdiXRq6pB510GTK77i36huRS5x6JnFDNoU9RPhU_6QOE96T4An80tBB-_RMmiz4oJYlrYI99dG6_5OLdwVNvNznfr54fXHDfvgHvFq9zjsBAAA&v=2"
    ],
    "category": "Residential",
    "sellingType": "Sale",
    "propertyType": "SingleFamilyHome",
    "geographicArea": "GSGS4621"
};

// Run the Actor and wait for it to finish
const run = await client.actor("xtracto/centris-property-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 = {
    "searchUrls": ["https://www.centris.ca/en/houses~for-sale~montreal-island?q=H4sIAAAAAAAACl2PQWvCQBCF_8uec7BFPPRWhEYRSukWL-JhTF6SwYkbZmPLIvnvnaBC9DbvzfcNuxfXSnRvbuYyd9BwhC5DCSssh6riAhukazxH5Ai1Utck31AH82aZi-O4ZfxZ3O0tg7RoPqm9XalYeuhtWTGkjFuS82jvLtdiXRq6pB510GTK77i36huRS5x6JnFDNoU9RPhU_6QOE96T4An80tBB-_RMmiz4oJYlrYI99dG6_5OLdwVNvNznfr54fXHDfvgHvFq9zjsBAAA&v=2"],
    "category": "Residential",
    "sellingType": "Sale",
    "propertyType": "SingleFamilyHome",
    "geographicArea": "GSGS4621",
}

# Run the Actor and wait for it to finish
run = client.actor("xtracto/centris-property-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 '{
  "searchUrls": [
    "https://www.centris.ca/en/houses~for-sale~montreal-island?q=H4sIAAAAAAAACl2PQWvCQBCF_8uec7BFPPRWhEYRSukWL-JhTF6SwYkbZmPLIvnvnaBC9DbvzfcNuxfXSnRvbuYyd9BwhC5DCSssh6riAhukazxH5Ai1Utck31AH82aZi-O4ZfxZ3O0tg7RoPqm9XalYeuhtWTGkjFuS82jvLtdiXRq6pB510GTK77i36huRS5x6JnFDNoU9RPhU_6QOE96T4An80tBB-_RMmiz4oJYlrYI99dG6_5OLdwVNvNznfr54fXHDfvgHvFq9zjsBAAA&v=2"
  ],
  "category": "Residential",
  "sellingType": "Sale",
  "propertyType": "SingleFamilyHome",
  "geographicArea": "GSGS4621"
}' |
apify call xtracto/centris-property-scraper --silent --output-dataset

```

## MCP server setup

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