At a glance
What the Canada Building Permits does
- Cities
- Toronto, Calgary, Edmonton, Vancouver, Winnipeg, Kitchener and Montréal (10 datasets)
- Filters
- Days back (up to 365), application types, statuses, wards, keywords, max results per city
- Output
- 25 fields per application; JSON, CSV, Excel, API
- Automate
- Schedules, webhooks, Zapier, Make, n8n, Google Sheets, MCP for AI agents
Who it is for
- Builders, trades and suppliers finding new projects from fresh applications and permits
- Real estate investors and brokers watching rezonings and site plans in their area
- Commercial real estate and retail teams spotting new restaurants, shops and changes of use
- Urban planners, journalists and residents tracking development in a ward
Output
What you get
- Application number, type (rezoning, site plan, subdivision, development or building permit) and category
- Street address(es), postal code, ward, neighbourhood, latitude/longitude
- Description of the proposal or work, current status
- Submitted, decision and issued dates (YYYY-MM-DD)
- Declared project value, permit category (Vancouver, Winnipeg), land-use district or zoning (Calgary, Edmonton), current and proposed use (Toronto building permits)
- Builder or contractor company (Toronto and Calgary building permits, Kitchener)
- City record link and a stable app_id for joins and dedupe
Example
Input and output
Input
{
"cities": [
"toronto",
"calgary"
],
"daysBack": 7,
"applicationTypes": [
"zoning",
"site plan",
"new"
],
"keywords": [
"storey",
"mixed-use"
],
"incremental": true
}One output record
{
"app_id": "calgary-building:BP2026-14894",
"city": "Calgary",
"province": "AB",
"application_number": "BP2026-14894",
"application_type": "Residential Improvement Project",
"category": "1113 - Detached Garage Dwelling Unit - New",
"address": "83G MARBANK WY NE",
"addresses": [
"83G MARBANK WY NE"
],
"postal_code": null,
"ward": null,
"neighbourhood": "MARLBOROUGH",
"description": "Additional Dwelling Unit",
"status": "Issued Permit",
"submitted_date": "2026-08-07",
"decision_date": null,
"issued_date": "2026-11-02",
"project_value": 113393.31,
"land_use": null,
"permit_category": null,
"contractor_company": "AIM BUILDER & DEVELOPMENT",
"latitude": 51.06397737432121,
"longitude": -113.97820309651591,
"url": "https://data.calgary.ca/resource/c2es-76ed.json?permitnum=BP2026-14894",
"source_url": "https://data.calgary.ca/resource/c2es-76ed.json?permitnum=BP2026-14894",
"scraped_at": "2026-11-04T18:47:17Z"
}From a real run of this tool; long text and lists shortened here.
How to use it
Three steps
- Pick the datasets (Toronto, Calgary, Edmonton, Vancouver, Winnipeg, Kitchener, Montréal; development applications or building permits) and how many days back to look; the defaults return Toronto and Calgary applications from the last 60 days.
- Optionally narrow it: application types (e.g. 'zoning', 'site plan'), statuses, wards and keywords; turn on 'Only new or changed since last run' for a weekly feed.
- Click Start, then download JSON, CSV or Excel, or schedule the run and send results to Google Sheets, Zapier, Make or n8n.
API
Call it from Python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("aurelix/canada-building-permits-scraper").call(run_input={'cities': ['toronto', 'calgary'],
'daysBack': 7,
'applicationTypes': ['zoning', 'site plan', 'new'],
'keywords': ['storey', 'mixed-use'],
'incremental': True})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)pip install apify-client. The same input works from the Apify console, a schedule, Make, n8n, Zapier or an AI agent through the Apify MCP server.
Pricing
Pay per result
| Per 1,000 applications, free plan | $3.00 |
| Per 1,000 applications, paid plans | $2.10 |
| Start fee per run | $0.00005 |
Live prices from the Apify Store; no subscription and no platform usage billed on top. A price change is scheduled; the Store page shows it before it applies. See the Store page.
Honest limits
What it does not do
- Seven cities only. Toronto Committee of Adjustment, Mississauga and Ottawa are not covered (no current open dataset).
- Vancouver, Kitchener and Montréal are issued building permits, Winnipeg issued development permits, not applications; Edmonton development permits publish a decision date only. Toronto building permits include applications not yet issued (issued_date empty) and one record per permit revision.
- Toronto publishes fewer development applications in its open data than Calgary: about 28 distinct applications in 60 days (25 to 40 a month since mid-2025; Calgary development permits: 912 in 60 days), because the dataset holds only planning applications (rezoning, official plan, site plan, subdivision, condominium, part lot), not minor variances or permits. It is also added weeks after submission (about a month in our checks), so short look-backs can return nothing for Toronto. For Toronto volume, add the Toronto building-permits dataset (5,840 records in 60 days).
- Toronto coordinates are converted from the city's MTM grid and are accurate to about 20 m; Toronto links point to the city's Application Information Centre or, where missing, the open-data record.
- Calgary, Edmonton, Vancouver, Winnipeg, Kitchener and Montréal links point to the open-data record, not a city web page. Toronto building permits and Edmonton building permits have no ward; Toronto building permits have no coordinates.
- Look-back is capped at 365 days (Vancouver at about 10,000 permits per run).
- Kitchener lists permit revisions under the same permit number; the newest row per permit is returned.
- Free-text descriptions can mention businesses; personal emails and phone numbers are removed. Vancouver descriptions keep only the work scope: permit-desk notes that name professionals, contractors, applicants or staff are dropped, so a few Vancouver records have no description.
- Montréal records are in French as published (types, borough, description).
FAQ
Questions buyers ask
How do I find construction leads before permits are issued?
Use the development applications: rezonings and site plans are filed at the planning stage, before building permits. Filter by ward, type and status, and schedule the run with new-or-changed mode.
Is there a cheaper Canadian building permits scraper?
This Actor costs $3.00 per 1,000 records on the free plan and $2.10 on paid plans; truenorthdata/canada-building-permits costs $5.00 and openpermits/building-permits-canada-us $3.50. It covers 7 Canadian cities (10 datasets), including Toronto development applications before a permit is issued, with a ward filter. openpermits also covers 4 US cities, which this Actor does not.
How do I get new Canadian building permits into Google Sheets, n8n or an AI agent?
Two ways. For a fixed workflow, add Apify's n8n or Make node, choose **Run Actor**, enter aurelix/canada-building-permits-scraper and map the dataset to the next step. For an AI agent (Claude, ChatGPT, Cursor or an n8n AI Agent node), add https://mcp.apify.com/?tools=aurelix/canada-building-permits-scraper as an MCP server and ask for permits and development applications in plain words; setup for each client is in the section above. Runs bill your own Apify account at the same per-result price.
How much does the Canada Building Permits cost?
$3.00 per 1,000 applications ($2.10 on paid Apify plans), billed through your Apify account; you pay only for results. Apify's free plan includes $5 of credit a month, enough for about 1,666 applications. A price change is scheduled; the Store page shows it before it applies.
Which datasets does it read?
Toronto: Development Applications (OZ rezoning/official plan, SA site plan, SB subdivision, CD condominium, PL part lot) and Building Permits - Active Permits. Calgary: Development Permits and Building Permits. Edmonton: Development Permits and General Building Permits. Winnipeg: Detailed Development Permit Data. Vancouver: Issued building permits (no open development-applications dataset). Kitchener: Building Permits (ArcGIS). Montréal: Permis de construction, transformation et démolition (CKAN). Every record links to its open-data source.
Is this legal?
It reads only public data any logged-out visitor can see: the official open-data portals of Toronto, Calgary, Edmonton, Vancouver, Winnipeg and Kitchener (each city's open government licence) and Montréal (CC BY 4.0). It goes at a polite pace, never logs in and never solves CAPTCHAs. It returns application and permit fields (address, type, status, dates, description, link); owner, applicant and contact names are dropped, and a builder or contractor is kept only as a company. To have a record removed, open an issue on this Actor's Issues tab; if a city formally asks us to stop, this Actor will stop. You are responsible for using the data lawfully, incl. anti-spam and privacy laws; this is not legal advice.
How does 'new or changed since last run' work?
The Actor remembers each application with its status for the same cities and filters (or the state name you set). It returns applications it has not returned before and those whose status changed. Entries are forgotten 400 days after they were last seen.
Which date does 'days back' use?
The submitted date for Toronto (both datasets) and Calgary development permits, the decision date for Edmonton development permits (its only date) and the issue date for every other dataset.
How fresh is it?
Toronto, Calgary, Edmonton, Winnipeg and Vancouver refresh daily, but Toronto development applications appear about a month after submission; Kitchener and Montréal refresh about weekly. In our checks the newest records were 0 to 2 days old for Edmonton and for Toronto and Calgary building permits, about 5 days for Winnipeg, about 6 for Kitchener and about 9 for Montréal. Look back at least 8 days if you rely on Kitchener or Montréal.
Why does Toronto return so few development applications?
Toronto's open data is genuinely thin, not cut short by this Actor: its Development Applications dataset holds about 25 to 40 planning applications a month (28 distinct in a recent 60 days, against 912 Calgary development permits) and adds them about a month after submission. Every page of the dataset is read. Add the Toronto building-permits dataset for volume (5,840 records in the same 60 days).
Can I add another city?
Not from the input: the Actor reads only these 10 datasets. Open an issue to ask for a city that publishes an open-licence dataset.
Can I use it from an AI assistant?
Yes. The input fields are described for agents: give cities, days back and optional filters. It works through Apify's MCP server and API.
What is charged when a city returns nothing or fails?
One application-result per record saved. A dataset with no matching records adds nothing, so a run that finds nothing pays only the start fee. Each API call is tried 4 times; if a city still fails (HTTP 429, a server error or no connection), that dataset is skipped, the others are returned, and the status message names it. If every dataset fails, the run fails and no records are charged.
How do the type, status, ward and keyword filters match?
Types and statuses are case-insensitive text matches on the type or category and on the status, so 'issued' matches Issued and Issued Permit. Keywords match the description and the addresses. Wards match the ward number or name, e.g. 18 or Willowdale. A dataset without wards (Vancouver, Kitchener, Montréal and the Toronto, Calgary and Edmonton building permits) returns nothing when you set a ward filter.
How do the per-city cap and new-or-changed mode work together?
Filters run first, then the newest records per dataset up to Max results per city, then new-or-changed mode drops records already returned. With a small cap, a feed sees only the newest records each run, so use 0 (no limit) or a generous cap for a scheduled feed. Records not saved because the maximum charge was reached are not remembered, so they come back next run.
How long does a run take?
Seconds for a normal run: in our Apify test runs Toronto and Calgary at 20 per city took 9 s, 7 datasets over 10 days 26 s, and Montréal over 12 days 4 s. The slowest case is all 10 datasets over 365 days, about 6 minutes, because every row in the window is read before the filters apply.
Are there limits per run?
Up to 365 days back. Each dataset is read newest first up to 50,000 source rows per run, Vancouver up to about 10,000. In our tests 365 days of Montréal returned 20,034 records and 365 days of Vancouver 4,156, both under those caps. Max results per city goes up to 100,000.
What does app_id mean, and how are duplicates handled?
app_id is the dataset plus the city's application or permit number, e.g. calgary-building:BP2026-14894, and each app_id is returned once per run. Toronto development applications have one source row per address; they are merged into one record with all addresses in addresses. Toronto building permits give one record per permit revision, and Kitchener keeps the newest row per permit.
Why are some fields empty?
Each city publishes different fields, and the Actor never fills one in. Postal codes come only from Toronto; project values only from Toronto, Calgary and Edmonton building permits, Vancouver and Kitchener; contractor companies only from Toronto and Calgary building permits and Kitchener, and only when the name reads as a company. Toronto building permits have no coordinates, and in our 30-day test Winnipeg records had no description.
Can I get an alert after each run?
Yes. Paste a Slack webhook URL to post a short digest (how many records, and the top 10 with links), or any webhook URL to receive the same digest as JSON (actor, newOnly, count, items, runUrl, text) for Zapier, Make or n8n. Nothing is sent when the run saved nothing. With new-or-changed mode on, the digest covers only the new and changed records.
Guides
Tutorials using this tool
Try the Canada Building Permits
Open it on the Apify Store, paste the example input above and click Start. Results download as CSV, Excel or JSON.