# Job Bank Canada Scraper (jobbank.gc.ca) (`santamaria-automations/jobbank-ca-scraper`) Actor

Extract Canadian job postings from jobbank.gc.ca, the Government of Canada's official job board. Returns title, employer, city and province, salary in CAD, NOC 2021 classification, job language (English / French / Bilingual), education, experience, vacancy count and hours. Pay-per-result.

- **URL**: https://apify.com/santamaria-automations/jobbank-ca-scraper.md
- **Developed by:** [NanoScrape](https://apify.com/santamaria-automations) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 serp results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Job Bank Canada Scraper (jobbank.gc.ca)

Extract Canadian job postings from [Job Bank](https://www.jobbank.gc.ca), the Government of Canada's official job board. Every posting is verified by Employment and Social Development Canada. No login. No captcha. Pay-per-result.

### What it does

Scrapes live vacancies from jobbank.gc.ca and returns clean, structured JSON. Coverage includes every province and territory, every NOC 2021 occupation, and all employment types (permanent, temporary, casual, seasonal, apprenticeship). Trades, healthcare, tech, finance, education, hospitality, agriculture, transport, government roles.

Works with:

- Search keywords, e.g. `"nurse"`, `"welder"`, `"developer"`, `"accountant"`.
- Any search URL copy-pasted from the site (all filters preserved).
- Location or city + province filter.
- Province and employment-type filters.

### Sample output

```json
{
  "_type": "job",
  "id": "50121324",
  "job_bank_id": "50121324",
  "title": "Health Care Aide",
  "employer_name": "Surf Lodge Nursing Home",
  "location": "Souris, PE, C0A 2B0",
  "city": "Souris",
  "province": "PE",
  "postal_code": "C0A 2B0",
  "country": "CA",
  "salary_min": 20.50,
  "salary_max": 23.00,
  "salary_currency": "CAD",
  "salary_period": "hourly",
  "salary_text": "$20.50 to $23.00 hourly",
  "wage_rate_type": "hourly",
  "hours_per_week": 37.5,
  "employment_type": "Permanent employment, Full time",
  "workplace_type": null,
  "employment_conditions": ["Day", "Evening", "Night", "Weekend"],
  "vacancy_count": 3,
  "noc_code": "33102",
  "noc_title": "Nurse aides, orderlies and patient service associates",
  "education_required": "No degree, certificate or diploma",
  "experience_required_text": "Will train",
  "experience_required_years": null,
  "job_language": "English",
  "work_permits_accepted": null,
  "description": "Education: No degree, certificate or diploma. Work setting: Nursing home/home for the aged. Tasks: Assist in daily living activities...",
  "description_full": "Education\nNo degree, certificate or diploma\n\nWork setting\nNursing home/home for the aged\n\nTasks\n- Assist in daily living activities\n- Take patients' blood pressure, temperature and pulse\n- Make beds and maintain patient rooms",
  "description_html": "<ul><li>Assist in daily living activities</li><li>Take patients' blood pressure, temperature and pulse</li><li>Make beds and maintain patient rooms</li></ul>",
  "description_md": "- Assist in daily living activities\n- Take patients' blood pressure, temperature and pulse\n- Make beds and maintain patient rooms",
  "responsibilities": null,
  "job_benefits": "Health care plan",
  "skills": null,
  "posted_at_text": "August 20, 2026",
  "posted_at_datetime": "2026-08-20T00:00:00Z",
  "closing_at": "2026-09-19",
  "job_url": "https://www.jobbank.gc.ca/jobsearch/jobposting/50121324",
  "application_url": "https://www.jobbank.gc.ca/jobsearch/jobposting/50121324",
  "apply_url": "https://macleodcares.com/careers/",
  "company_profile_url": "https://www.jobbank.gc.ca/jobsearch/empprofile/50121324",
  "source_platform": "jobbank.gc.ca",
  "search_query": "health care aide in Prince Edward Island",
  "scraped_at": "2026-08-22T10:14:33Z",
  "company_about": null,
  "company_phone": null,
  "company_email": null,
  "company_website": "http://macleodcares.com",
  "company_address_street": null,
  "company_address_city": "Souris",
  "company_address_province": "PE",
  "company_address_postcode": "C0A 2B0",
  "company_address_country": "Canada",
  "company_business_type": null,
  "company_business_size": "Small-sized business",
  "company_size_range": "Small-sized business (between 1 and 4 employees)",
  "company_industry_naics": null,
  "company_industry": "Health care and social assistance",
  "company_profile_modified_at": "2026-07-09",
  "company_locations_count": 1,
  "company_logo_url": null,
  "company_active_jobs_count": 2,
  "company_active_jobs": [
    {
      "title": "Health Care Aide",
      "job_url": "https://www.jobbank.gc.ca/jobsearch/jobposting/50121324",
      "location": "Souris, PE",
      "salary_text": "$20.50 to $23.00 hourly"
    }
  ],
  "company_workplace_amenities": ["Accessible parking", "Variable work hours available"],
  "company_support_groups": ["Supports newcomers and/or refugees with foreign credential recognition"],
  "company_learning_opportunities": ["On-the-job training"],
  "company_green_initiatives": ["Training for employees on environmental sustainability"]
}
```

### Pricing

**$0.001 per actor start + $0.005 per full-detail row (or $0.003 per SERP-only row) + optional $0.005 per unique employer profile enriched. About $5 per 1,000 jobs in full mode.**

You only pay for rows that successfully return data. Failed fetches are not charged.

**New to Apify?** Every account gets a $5 free monthly platform credit, enough for around 1,000 full-mode results on this actor before you commit to paying anything. Test extensively first.

### Input

| Field | Type | Description |
|---|---|---|
| `searchQueries` | array | Keywords like `"nurse"`, `"welder"`, `"developer"`. Each runs as a separate search. |
| `startUrls` | array | Paste search URLs from the site directly. All filters preserved. |
| `location` | string | City or region, e.g. `"Toronto"`, `"Vancouver, BC"`. Applied to keyword searches. |
| `province` | select | Two-letter province code, applied when the location does not already include one. |
| `employmentType` | select | Permanent, Temporary, Casual or Seasonal. |
| `includeJobDetails` | boolean | Fetch each posting for full description, NOC code, salary, hours, education, language, and detail-only fields. |
| `includeCompanyDetails` | boolean | Fetch each unique employer profile for business size, other open roles, and any contact fields. Implies `includeJobDetails=true`. |
| `maxResults` | integer | Total row cap across all queries. |
| `maxResultsPerQuery` | integer | Row cap per query. |
| `maxConcurrency` | integer | Concurrent detail-page requests. Default 6. |

### Output fields

**Identity:** `id`, `job_bank_id`, `title`, `job_url`, `source_platform`, `_type`.

**Employer + location:** `employer_name`, `location`, `city`, `province`, `postal_code`, `country`.

**Salary in CAD:** `salary_min`, `salary_max`, `salary_currency`, `salary_period`, `salary_text`, `wage_rate_type`, `hours_per_week`.

**Employment:** `employment_type` (compound string, e.g. `"Permanent employment, Full time"`), `workplace_type`, `employment_conditions`, `vacancy_count`.

**Canadian taxonomy:** `noc_code` (NOC 2021), `noc_title`.

**Requirements:** `education_required`, `experience_required_text`, `experience_required_years`, `job_language` (English / French / Bilingual), `work_permits_accepted`.

**Content (full mode):** `description` (single-line normalised), `description_full` (paragraph-and-bullet plain text), `description_html` (raw HTML), `description_md` (Markdown with headings, bullets, bold, links), `responsibilities`, `job_benefits`, `skills`.

**Dates + apply:** `posted_at_text`, `posted_at_datetime` (ISO 8601), `closing_at`, `application_url`, `apply_url`, `company_profile_url`.

**Employer profile (`includeCompanyDetails=true`):** `company_business_type`, `company_business_size`, `company_size_range` (size label + employee count range), `company_industry_naics`, `company_industry` (sector label), `company_profile_modified_at` (ISO date), `company_locations_count`, `company_logo_url`, `company_about`, `company_phone`, `company_email`, `company_website`, `company_address_*`, `company_active_jobs_count`, `company_active_jobs[]`, `company_workplace_amenities[]`, `company_support_groups[]`, `company_learning_opportunities[]`, `company_green_initiatives[]`.

### Use with AI Agents (MCP)

Connect this actor to any MCP-compatible AI client: Claude Desktop, Claude.ai, Cursor, VS Code, LangChain, LlamaIndex, or custom agents.

**Apify MCP server URL:**

`https://mcp.apify.com?tools=nanoscrape/jobbank-ca-scraper`

**Example prompt once connected:**

> "Use `jobbank-ca-scraper` to find all bilingual French / English nursing vacancies in Quebec paying more than $40 per hour. Return as a table with employer, city, wage, closing date."

Clients that support dynamic tool discovery (Claude.ai, VS Code) receive the full input schema automatically.

### Why this scraper

- **Official Government of Canada source.** Every posting is verified by ESDC; no scraped-off-Craigslist noise.
- **NOC 2021 codes surfaced.** The unique Canadian occupation taxonomy is exposed as a native field, so filtering, joining, and analytics against StatsCan wage data works out of the box.
- **Bilingual metadata.** `job_language` distinguishes English, French, and true bilingual roles, which is critical for the Canadian labour market.
- **CA-specific fields.** `vacancy_count`, `hours_per_week`, `education_required`, `experience_required_years`, `wage_rate_type` and Canadian postal codes come as structured fields, not free text.
- **No login. No captcha.** Job Bank is a public government service.

### Common use cases

- Immigration consultants surfacing LMIA-eligible postings by NOC code.
- Recruitment agencies aggregating Canadian jobs into their candidate CRM.
- Provincial labour-market analysts tracking demand by NOC and region.
- Bilingual staffing firms filtering the French-language postings in Quebec, Ontario and New Brunswick.
- Compensation-benchmark teams building CAD wage ranges by occupation and city.

### Notes and limits

- Salary is emitted with `salary_period` set to one of `hourly`, `weekly`, `monthly`, `annual` or `piece-work`; do not compare `salary_min` values across periods without normalising.
- `application_url` is Job Bank's own posting URL when the employer only accepts applications through the government-hosted apply flow. When the listing includes an external career-portal link ("Learn more about this job" button), that URL is in the separate `apply_url` field. `apply_url` is `null` for listings without an external link.
- `company_profile_url` is the employer's Job Bank profile page. **Some listings do not have a linked employer profile** — when absent, `company_profile_url` is `null` and all empprofile-derived fields (`company_about`, `company_size_range`, `company_industry`, `company_profile_modified_at`, `company_industry_naics`, `company_logo_url`, `company_workplace_amenities`, `company_support_groups`, `company_learning_opportunities`, `company_green_initiatives`) are also `null` or empty arrays. These fields only populate when `includeCompanyDetails=true` AND the job listing has a linked `/jobsearch/empprofile/{id}` page.
- `company_website` is extracted from the employer anchor on the job detail page (when the employer name links out to an external site). It may also be populated from the employer profile page. Both sources are checked; the detail-page anchor takes priority. When neither source provides a URL, `company_website` is `null`.
- `company_*` fields are only populated when `includeCompanyDetails` is enabled. Job Bank employer profiles vary widely in completeness. `company_business_size`, `company_locations_count`, and `company_active_jobs_count` populate on most profiles; `company_website`, `company_email`, and `company_phone` are less common.
- `description_md` is real Markdown: headings become `#`/`##`, bullet lists become `- ` items, bold/italic tags are preserved as `**`/`*`, and hyperlinks become `[text](url)`.
- `job_language` is inferred from the posting's Languages field. Postings that say only "English" or only "French" are labelled as such; postings that mention both are labelled `Bilingual (English + French)`.
- The site currently lists 100,000+ live postings. Practical per-query maximum is a few thousand rows due to the site's own pagination cap.

### Related Actors

- [LinkedIn Jobs Scraper](https://apify.com/santamaria-automations/linkedin-jobs-scraper): private-sector job board covering Canada plus every other country.
- [Indeed Scraper](https://apify.com/santamaria-automations/indeed-scraper): global aggregator including Canadian postings.
- [Website Email Scraper](https://apify.com/santamaria-automations/website-email-scraper): follow-up enrichment to extract employer emails from the company website field.

### Support

For issues, feature requests, or field gaps, please open an issue on the [Issues tab](https://apify.com/nanoscrape/jobbank-ca-scraper/issues). We typically respond within 24 hours.

Contact: contact@nanoscrape.com

# Actor input Schema

## `searchQueries` (type: `array`):

One or more keywords, e.g. 'developer', 'nurse', 'welder', 'accountant'. Each runs as a separate search. Results are deduplicated across queries.

## `startUrls` (type: `array`):

Paste jobbank.gc.ca search URLs directly. Go to the site, apply any filters (province, employment type, wage), and copy the browser URL. All filters preserved. Mutually exclusive with searchQueries.

## `location` (type: `string`):

City or region filter, e.g. 'Toronto', 'Montreal', 'Vancouver, BC'. Applied to all keyword searches.

## `includeJobDetails` (type: `boolean`):

Fetch each posting's detail page for full description, NOC 2021 code, salary min/max, hours per week, education, experience, language, and other detail-only fields. Otherwise only SERP-visible fields are returned.

## `includeCompanyDetails` (type: `boolean`):

Also fetch each unique employer's Job Bank profile page for business type / size, other currently-open roles, logo, and any published contact fields. Deduplicated per employer within a run. Implies includeJobDetails.

## `province` (type: `string`):

Two-letter province code appended to the location filter when the location does not already include one. Applies to keyword searches only.

## `employmentType` (type: `string`):

Filter by employment type. Applied to keyword searches only.

## `maxResults` (type: `integer`):

Total cap across all queries and URLs.

## `maxResultsPerQuery` (type: `integer`):

Maximum results per keyword or search URL.

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

Concurrent detail-page requests when includeJobDetails is on.

## Actor input object example

```json
{
  "searchQueries": [
    "developer"
  ],
  "location": "Toronto, ON",
  "includeJobDetails": false,
  "includeCompanyDetails": false,
  "province": "",
  "employmentType": "",
  "maxResults": 5,
  "maxResultsPerQuery": 5,
  "maxConcurrency": 6
}
```

# Actor output Schema

## `jobListings` (type: `string`):

Dataset of Canadian job postings. Each row includes Job Bank ID, title, employer, city, province, postal code, salary min/max in CAD, NOC code + title, education, experience, language, hours, vacancy count, employment type, application URL and full 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 = {
    "searchQueries": [
        "developer"
    ],
    "maxResults": 5,
    "maxResultsPerQuery": 5,
    "maxConcurrency": 6
};

// Run the Actor and wait for it to finish
const run = await client.actor("santamaria-automations/jobbank-ca-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 = {
    "searchQueries": ["developer"],
    "maxResults": 5,
    "maxResultsPerQuery": 5,
    "maxConcurrency": 6,
}

# Run the Actor and wait for it to finish
run = client.actor("santamaria-automations/jobbank-ca-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 '{
  "searchQueries": [
    "developer"
  ],
  "maxResults": 5,
  "maxResultsPerQuery": 5,
  "maxConcurrency": 6
}' |
apify call santamaria-automations/jobbank-ca-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,santamaria-automations/jobbank-ca-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/8KqVxIig6TX6NbkpO/builds/Qc0hJmFKhF8fsvWP4/openapi.json
