How to Get Ontario Home Builder Data by API (2026)
In Ontario, you can't legally build or sell a new home unless you're licensed by the Home Construction Regulatory Authority (HCRA). Every licensed builder - and every expired, revoked or refused one - lives in a public database called the Ontario Builder Directory (OBD). That's a ready-made list of construction businesses, with contact info, licence status, and how many homes each has built.
The catch: there's no "download all" button and no documented API. The directory is a search box. This post shows how to pull that data programmatically in 2026 - the real endpoint behind the search, the fields you get, and a hosted option you can call from code or an AI agent.
Why builder-directory data is useful
An HCRA licence record is a strong commercial signal:
- Contact info - most builders list a phone number, many an email and website.
- Licence status - Licensed, Licensed with Conditions, Expired, Revoked, Refused. Great for lead-gen (only-active) or due diligence (find the bad ones).
- Track record - the directory reports how many freehold and condo homes each builder has completed, plus warranty-claim counts and insolvency flags.
Suppliers, sub-trades, PropTech tools, and anyone doing B2B sales into Ontario residential construction can turn this into a targeted list.
One important thing about HCRA
HCRA licenses new-home builders and vendors - not trade subcontractors. So the directory is full of home-building companies, not roofers, electricians or plumbers. If you search for a trade like "roofing" you'll get very few active hits. Search instead by company terms like homes, construction, developments, or by a specific builder name. (For trade licences, Quebec's RBQ registry is the dataset you want - different post.)
The source: obd.hcraontario.ca
The Ontario Builder Directory is a public site backed by a JSON API. Two endpoints do all the work.
Search (list):
GET https://obd.hcraontario.ca/api/builders?builderName=<term>
Returns a JSON array of builders whose legal name or operating name contains <term> (server-side substring match). Each row is lightweight:
{
"NAME": "1000046468 Ontario Inc.",
"OPERATINGNAME": "Kinfolk Homes",
"ACCOUNTNUMBER": "B61791",
"ADDRESS_2_CITY": "Brighton",
"LICENSESTATUS": "Licensed",
"INSOLVENCY_INDICATOR": "false"
}
Detail (summary):
GET https://obd.hcraontario.ca/api/buildersummary?id=<ACCOUNTNUMBER>
Returns the rich record - address, phone, email, website, initial licence date, homes built and warranty claims (fields shown with illustrative values):
{
"ACCOUNTNUMBER": "B10000",
"VB_Name": "Example Homes Inc.",
"OPERATINGNAME": "Example Homes",
"CITY": "Ottawa",
"LICENCE_STATUS": "Licensed",
"TELEPHONE": "613-555-0100",
"EMAIL": "info@example-homes.ca",
"WEBSITEURL": "example-homes.ca",
"HCRA_INITIALLICENSEDATE": "2021-06-01 00:00:00",
"SUMM_FREEHOLD": "12",
"SUMM_CONDO": "0",
"SUMM_TOTAL": "12",
"SUMM_TOTAL_CLAIMS": "0"
}
Pulling it with Python
Search, then enrich each builder with the detail endpoint:
import requests
BASE = "https://obd.hcraontario.ca/api"
def search(term):
r = requests.get(f"{BASE}/builders", params={"builderName": term}, timeout=60)
r.raise_for_status()
return r.json()
def detail(account):
r = requests.get(f"{BASE}/buildersummary", params={"id": account}, timeout=60)
r.raise_for_status()
data = r.json()
return data[0] if isinstance(data, list) and data else {}
seen = set()
for row in search("homes"):
acct = row["ACCOUNTNUMBER"]
if acct in seen or row["LICENSESTATUS"] != "Licensed":
continue
seen.add(acct)
d = detail(acct)
print(d.get("VB_Name"), "|", d.get("CITY"), "|", d.get("TELEPHONE"), "|", d.get("EMAIL"), "|", "homes:", d.get("SUMM_TOTAL"))
A few gotchas the code above handles or you should know about:
- An empty
builderNamereturns HTTP 500 - always pass a term. - The
pageparameter is ignored; the full matching array comes back in one response, so paginate client-side. - One term (like
homes) returns thousands of rows. To sweep the whole directory you'd query each letteraโzand dedupe byACCOUNTNUMBER. - Filter on
LICENSESTATUS == "Licensed"if you only want active builders - the directory also contains Expired, Revoked and Refused entries.
That's a real little pipeline: search terms, dedupe, per-builder enrichment, status filtering, and a scheduler if you want it fresh. Or skip the plumbing.
The hosted option: one call, both provinces
I maintain an Apify Actor that does the search-and-enrich, normalizes the fields, and filters to active licences by default: Contractor License Scraper Canada - Ontario (HCRA) and Quebec (RBQ) in one schema.
{
"provinces": ["ontario"],
"keywords": ["homes", "construction"],
"activeOnly": true,
"maxResults": 100
}
Output - one clean record per builder:
{
"licenseNumber": "B10000",
"holderName": "Example Homes Inc.",
"otherNames": ["Example Homes"],
"city": "Ottawa",
"phone": "613-555-0100",
"email": "info@example-homes.ca",
"website": "example-homes.ca",
"status": "Licensed",
"issuedDate": "2021-06-01",
"homesBuilt": {
"freehold": 12,
"condo": 0,
"total": 12
},
"province": "ON"
}
activeOnly defaults to on, so you get a clean list of currently-licensed builders; turn it off for research on expired or revoked ones. Pricing is per record ($6 per 1,000), so a targeted regional list costs cents.
Call it from an AI agent (MCP)
The Actor is exposed over the Model Context Protocol, so an LLM agent can pull builder data as a tool:
https://mcp.apify.com?tools=truenorthdata/canada-contractor-licenses
Wire that into a Claude / MCP client and ask in plain language - "active Ontario home builders in Ottawa with a phone number" - and the agent runs the Actor and filters the results itself.
FAQ
Is this legal?
The Ontario Builder Directory is a public register HCRA publishes so consumers can check builders. We read it as published.
Does every builder have an email?
No. Phone is common; email and website are listed for some builders, not all.
Can I get expired/revoked builders?
Yes - set activeOnly off (or filter LICENSESTATUS yourself). Useful for due diligence.
What about trades (roofers, electricians)?
HCRA only licenses home builders/vendors. For Quebec trade licences, use the RBQ registry (same Actor, province: "quebec").
Building with Canadian public data - permits, tenders, licences?
I write about turning open registries into products. Questions welcome in the comments.
Comments
No comments yet. Start the discussion.