DEV Community

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 builderName returns HTTP 500 - always pass a term.
  • The page parameter 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 letter a โ€“ z and dedupe by ACCOUNTNUMBER.
  • 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.