# BambooHR Jobs: Career Pages & Salaries (`deepmine/bamboohr-jobs`) Actor

BambooHR jobs scraper: every open job from any company's BambooHR careers page (acme.bamboohr.com) with the pay as published and as numbers, experience level, job type, address, company logo, full description as text or Markdown and the apply link. Subdomains or URLs. No login.

- **URL**: https://apify.com/deepmine/bamboohr-jobs.md
- **Developed by:** [DeepMine](https://apify.com/deepmine) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.39 / 1,000 jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## BambooHR Jobs: Career Pages & Salaries

Paste BambooHR careers pages (`https://acme.bamboohr.com/careers`) or just their subdomains (`acme`), and get **every open job** as one clean row each: title, location and full address, remote or hybrid, department, job type and the company's own employment status, **minimum experience level**, posting date, **the pay as the company wrote it and as numbers** (min, max, currency, period), the company logo, the full description as text **and Markdown**, and the job link.

| 💼 Title | 🏢 Company | 📍 Location | 💰 Salary | 🎓 Experience | 🕒 Job Type | 📅 Posted |
|---|---|---|---|---|---|---|
| Estimator | Tri-M Group | Kennett Square, Pennsylvania, United States | $85K-$88K dependent upon experience | Experienced | Full-time | 2026-10-23 |
| Lineperson 1st Class (LH) | Tri-M Group | Lock Haven, Pennsylvania, United States | $46-$61 per hour dependent upon experience | Experienced | Full-time | 2026-10-20 |
| Civil Project Superintendent | Fraser Valley | Emil Anderson Group | Abbotsford, British Columbia, Canada | $120,000-$160,000 | Manager/Supervisor | Full-time | 2026-09-22 |

<sub>Collected 2026-10-23 with Tri-M Group and Emil Anderson Group, 25 newest jobs each: 45 of 50 rows have a salary (read as USD or CAD, per hour or per year), 48 an experience level, and all 50 a logo, an address and a posting date.</sub>

**$0.49 per 1,000 jobs** on the Starter plan ($0.59 Free, $0.44 Scale, $0.39 Business). The prefilled run (50 jobs: 25 from each of 2 companies) costs about $0.02.

It reads BambooHR's public careers API, the one each company's careers page uses, live on every run. No browser and no login. Descriptions, Markdown and every pay field are included at the same price.

### What you can do with it

- **Pay you can sort and chart:** BambooHR's pay field is free text ("$46-$61 per hour dependent upon experience", "Up to £71,800 FTE", "$40 per hour + $2,000 signing bonus", "JPY 5M-9M"). `salary` keeps the company's words; `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryPeriod` read it: "up to" is the top of the range, a bonus after a `+` is not, `$` on a Canadian job is CAD unless the line says `US$`. When the pay field is empty but the description states a range, the salary comes from there and `salarySource` says `description`.
- **Filter by pay and seniority before you pay:** a minimum yearly pay (hourly pay counts 2,080 hours), only jobs with published pay, BambooHR's experience levels (Entry-level to Executive), plus title words, department, job type, location (whole words or country codes), remote only, posted in the last N days or on or after a date. Jobs your filters drop cost nothing.
- **Feed LLMs and AI agents:** `descriptionMarkdown` keeps headings, lists, bold and links; `description` is plain text.
- **Monitor hiring** at target accounts: schedule a daily run with **📅 Posted within** 1.
- **Build lead lists** of companies hiring on BambooHR: each row carries the company name and logo as its careers page shows them, and the job's full address.

### What to paste

- **A careers page URL**, e.g. `https://trimgroup.bamboohr.com/careers`, or a job URL from it (`https://trimgroup.bamboohr.com/careers/507`).
- **The subdomain alone**, e.g. `trimgroup`: the part before `.bamboohr.com`.
- Greenhouse, Lever, Ashby and Workday board URLs work in the same run (`greenhouse:airbnb` for a board name on another job board), with the same columns.

### Input

```json
{
  "companies": ["https://trimgroup.bamboohr.com/careers", "emilanderson"],
  "titleKeywords": ["technician", "estimator"],
  "experienceLevels": ["Mid-level", "Experienced"],
  "minSalary": 50000,
  "locations": ["US"],
  "postedWithinDays": 30,
  "maxJobsPerCompany": 100,
  "maxResults": 1000,
  "includeMarkdown": true,
  "includeAllFields": true
}
```

| Field | What it does |
|---|---|
| `companies` | BambooHR careers page URLs or subdomains, one per line. Other job board URLs work too. |
| `maxJobsPerCompany` | Each company's newest jobs, up to this many (default 100), so one big company can't take all of `maxResults`. 0 = every job. You pay per job, so this caps the cost per company. |
| `maxResults` | Stop after this many jobs in total, which caps the run's cost. |
| `includeDescription` | Reads each job's own page (on by default): the description, pay, posting date and experience level. BambooHR's job list shows none of these, so with it off the rows are shorter and the run faster. |
| `titleKeywords` | Keep jobs whose title contains any of these (not case-sensitive). |
| `departments` | Keep jobs whose department contains any of these (not case-sensitive). |
| `employmentTypes` | Keep only these job types: `Full-time`, `Part-time`, `Contract`, `Internship`, `Temporary`. |
| `experienceLevels` | Keep only these minimum experience levels: `Entry-level`, `Mid-level`, `Experienced`, `Manager/Supervisor`, `Senior Manager/Supervisor`, `Executive`. |
| `locations` | Keep jobs whose location contains any of these as whole words (`India` doesn't match Indiana). Two letters are a country code and match only the job's countries: `US`, `GB` (or `UK`), `DE`, `CA` (Canada, not California). |
| `remoteOnly` | Keep only jobs marked remote. |
| `postedWithinDays` | Keep only jobs posted in the last N days (0 = any date). |
| `postedAfter` | Keep only jobs posted on or after this day, e.g. `2026-10-01` (empty = any date). |
| `minSalary` | Keep jobs whose published pay reaches this much a year, in the job's own currency (an hourly rate times 2,080; a monthly one times 12). Jobs without pay are left out. |
| `onlyWithSalary` | Keep only jobs whose pay field or description states an amount. |
| `includeMarkdown` | Adds `descriptionMarkdown` (on by default). |
| `includeHtml` | Adds `descriptionHtml`, the company's own formatting. |
| `includeAllFields` | Reads the pay line as numbers with the rules above and takes the description's range when the pay field has none; adds `salarySource`, `experienceLevel`, `employmentStatus`, `isRemote`, `address`, `postalCode`, `globalId`, `inputOrder` and the company logo (on by default). |
| `includeRawJson` | Adds `raw`: BambooHR's own records for the job, verbatim, for your own parsing. Needs `includeAllFields`. |

### Output

One row per job. Rows come in the order of your companies list, each company's jobs newest first.

Two datasets, both with the same rows:

- **💼 All Jobs** (default dataset). Views: **📊 Overview** (🖼️ Logo, 💼 Title, 🏢 Company, 📍 Location, 🏠 Workplace, 🕒 Job Type, 🗂️ Department, 💰 Salary, 🎓 Experience, 📅 Posted, 🔗 Job Page) and **📝 Details** (💼 Title, 🏢 Company, 🏷️ Employment Status, 🎓 Experience, 🗂️ Department, 🗺️ All Locations, 🌍 Country, 📮 Address, 📋 Job Board, 🆔 Job ID, 🔗 Job Page).
- **💰 With Salary**: the delivered jobs with a pay amount, in the same order, at no extra charge. View: 🖼️ Logo, 💼 Title, 🏢 Company, 📍 Location, 💰 Salary, 💰 Salary Min, 💰 Salary Max, 💱 Currency, ⏱️ Pay Period, 🔎 Pay Source, 📅 Posted, 🔗 Job Page.

#### Output fields

In row order:

- `companyLogo`: the company logo from its BambooHR careers page. A stable image link.
- `title`: job title.
- `company`: company name as its careers page shows it.
- `location`: city, state or province and country.
- `workplaceType`: `Remote`, `Hybrid` or `On-site` from the company's own setting.
- `employmentType`: `Full-time`, `Part-time`, `Contract`, `Internship`, `Temporary` or `Other`, read from the company's employment status.
- `department`: the department the company files the job under.
- `salary`: the pay as the company wrote it, e.g. `$46-$61 per hour dependent upon experience`, or the range the description states.
- `salaryMin`: the lowest pay, as a number.
- `salaryMax`: the highest pay, as a number.
- `salaryCurrency`: ISO currency code, e.g. `USD`, `CAD`, `GBP`.
- `salaryPeriod`: `year`, `month`, `week`, `day` or `hour`.
- `postedAt`: the date BambooHR shows for the job (`2026-10-23`).
- `jobUrl`: the job's page on the careers site, where you apply too.
- `applyUrl`: where to apply. On BambooHR that is the job page itself, so it equals `jobUrl`.
- `locations`: every place the job is offered, as a list.
- `countryCode`: ISO code of the job's country.
- `salarySource`: where the salary comes from: `compensation` (the pay field) or `description` (a range written in the job description, when the pay field has none).
- `experienceLevel`: the minimum experience the company asks for: `Entry-level`, `Mid-level`, `Experienced`, `Manager/Supervisor`, `Senior Manager/Supervisor` or `Executive`.
- `employmentStatus`: the company's own employment status label, e.g. `Regular Full-Time` or `Craft`.
- `isRemote`: `true` for a remote job, `false` for an on-site or hybrid one, empty when the company doesn't say.
- `address`: the job's address on one line, e.g. `Abbotsford, British Columbia V2T 1N3, Canada` (each part only where the company publishes it).
- `postalCode`: the postal code, where the company publishes one.
- `globalId`: a key unique across companies and runs, `bamboohr:<subdomain>:<job id>`: use it to find jobs new since your last run.
- `inputOrder`: the company's place in your `companies` list (0 = first).
- `description`: the full job description as plain text. Only with `includeDescription` (on by default).
- `descriptionHtml`: the description with the company's formatting. Only with `includeHtml`.
- `descriptionMarkdown`: the description as Markdown. Only with `includeMarkdown` (on by default).
- `raw`: BambooHR's own records for the job, verbatim (`list` and `detail`). Only with `includeRawJson`.
- `ats`: `BambooHR` (or the other job board's name).
- `boardUrl`: the careers page the job was read from.
- `jobId`: the job's id on BambooHR.
- `companyInput`: the entry of your `companies` list that led to this job.
- `scrapedAt`: when this run read the job (UTC).

Example row (description shortened):

```json
{
  "companyLogo": "https://images3.bamboohr.com/478787/logos/cropped.jpg?v=42",
  "title": "Civil Project Superintendent | Fraser Valley",
  "company": "Emil Anderson Group",
  "location": "Abbotsford, British Columbia, Canada",
  "workplaceType": "On-site",
  "employmentType": "Full-time",
  "department": "EAC",
  "salary": "$120,000-$160,000",
  "salaryMin": 120000,
  "salaryMax": 160000,
  "salaryCurrency": "CAD",
  "salaryPeriod": "year",
  "postedAt": "2026-09-22",
  "jobUrl": "https://emilanderson.bamboohr.com/careers/319",
  "applyUrl": "https://emilanderson.bamboohr.com/careers/319",
  "locations": ["Abbotsford, British Columbia, Canada"],
  "countryCode": "CA",
  "salarySource": "compensation",
  "experienceLevel": "Manager/Supervisor",
  "employmentStatus": "Full Time Staff",
  "isRemote": false,
  "address": "Abbotsford, British Columbia V2T 1N3, Canada",
  "postalCode": "V2T 1N3",
  "globalId": "bamboohr:emilanderson:319",
  "inputOrder": 1,
  "description": "Division: Emil Anderson Construction\n\nDepartment: EAC\n\nAbout Emil Anderson Construction...",
  "descriptionMarkdown": "Division: Emil Anderson Construction\n\nDepartment: EAC\n\nAbout Emil Anderson Construction...",
  "ats": "BambooHR",
  "boardUrl": "https://emilanderson.bamboohr.com/careers",
  "jobId": "319",
  "companyInput": "https://emilanderson.bamboohr.com/careers",
  "scrapedAt": "2026-10-23T21:58:12Z"
}
```

The run's **🧾 Run summary** (the OUTPUT record in the key-value store) shows, per company, which careers page was read, how many jobs it lists, how many matched your filters and how many were delivered, plus any error.

### When something goes wrong

- A subdomain that isn't a BambooHR careers page (BambooHR sends unknown ones to its own website) is listed in the run summary and the status message as not found. The run still delivers everything else.
- A job taken down between the list and its own page is skipped and counted in the run summary; it isn't charged.
- If a careers page can't be read after several retries on fresh IPs, the run ends as **failed** with the reason, so you notice. The jobs that were read are still in the dataset.
- When `maxResults` is reached, the companies after that point get nothing; the run summary marks them as skipped.

### Pricing

You pay per job delivered: $0.59 per 1,000 jobs on the Free plan, $0.49 on Starter, $0.44 on Scale and $0.39 on Business. Descriptions, Markdown and every pay field are included at the same price. Companies that aren't found, jobs removed by your filters, jobs taken down and the 💰 With Salary list cost nothing.

Examples on Starter: the prefilled run (50 jobs) about $0.02; the default `maxResults` of 1,000 jobs $0.49.

### FAQ

**Why do some jobs have no salary?** The company decides whether to fill in BambooHR's pay field. When it is empty, the row takes the range the description states, if it states one (`salarySource`: `description`). A job with neither has no salary.

**Why isn't every job newest first by the minute?** BambooHR shows a posting date, not a time, so jobs posted the same day keep the company's order.

**Can it find every company on BambooHR?** No: BambooHR has no public list of its customers. Paste the companies you care about; a careers page URL or the subdomain is enough.

**Do I need a proxy?** The default Apify datacenter proxy is all BambooHR's careers API needs.

**How fresh is the data?** Each run reads the careers pages live; nothing comes from a cache or a database.

### Feedback

Missing a field or a company it can't read? Open an issue on the Issues tab and we'll look at it. If the data helped you, a short review on this page helps other people find it.

# Actor input Schema

## `companies` (type: `array`):

BambooHR careers page URLs (https://acme.bamboohr.com/careers) or just the subdomain (acme), one per line. Greenhouse, Lever, Ashby and Workday boards work too.

## `maxJobsPerCompany` (type: `integer`):

Each company's newest jobs, up to this many. You pay per job, so this caps the cost per company. 0 = every job.

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

Stop after this many jobs in total, delivered in the order of your inputs. You pay per job, so this caps the run's cost.

## `includeDescription` (type: `boolean`):

Reads each job's own page: the full description, pay, posting date and experience level. Same price. Off is faster but leaves those out (BambooHR's list doesn't show them).

## `titleKeywords` (type: `array`):

Keep jobs whose title contains any of these words or phrases, e.g. engineer, sales manager. Not case-sensitive. Empty = every job.

## `departments` (type: `array`):

Keep jobs whose department contains any of these, e.g. Engineering, Sales. Not case-sensitive. Empty = every department.

## `employmentTypes` (type: `array`):

Keep only these job types. Empty = every type.

## `experienceLevels` (type: `array`):

Keep only jobs asking for this minimum experience, as BambooHR names it. Empty = any level.

## `locations` (type: `array`):

Keep jobs whose location names any of these, e.g. Texas, Toronto, Germany. Two letters are a country code: US, GB, DE, CA (Canada). Empty = anywhere.

## `remoteOnly` (type: `boolean`):

Keep only jobs the company marks as remote, or whose location says Remote.

## `postedWithinDays` (type: `integer`):

Keep jobs posted in the last N days, e.g. 1 for a daily scheduled run. Uses the date BambooHR shows. 0 = any date.

## `postedAfter` (type: `string`):

Keep jobs posted on or after this day (UTC), e.g. 2026-10-01. Uses the date BambooHR shows. Empty = any date.

## `minSalary` (type: `integer`):

Keep jobs whose published pay reaches this much a year, in the job's own currency (hourly pay counts 2,080 hours). Jobs without pay are left out. 0 = any pay.

## `onlyWithSalary` (type: `boolean`):

Keep only jobs whose pay field or description states an amount.

## `includeMarkdown` (type: `boolean`):

Adds descriptionMarkdown: headings, lists, bold and links kept, ready for LLMs and AI agents. Same price.

## `includeHtml` (type: `boolean`):

Adds descriptionHtml with the company's own formatting. Same price. Needs job descriptions on.

## `includeAllFields` (type: `boolean`):

Reads the pay line as numbers (up to, plus bonus, US or local dollars, millions), else the description's range; adds experience level, employment status, remote flag, address, global ID, input order, logo. Same price.

## `includeRawJson` (type: `boolean`):

Adds raw: BambooHR's own records for the job, verbatim (the list's and the job's, nested JSON, for your own parsing). Same price. Needs 💵 Pay numbers... on.

## `bareNamesOn` (type: `string`):

A bare entry such as acme is the BambooHR careers page acme.bamboohr.com.

## `ownFieldsFor` (type: `string`):

With 💵 Pay, experience, address..., a BambooHR job carries BambooHR's own fields.

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

Leave as is: Apify datacenter proxies are all BambooHR needs. Residential and SERP proxies are replaced with datacenter (they cost more and add nothing here); your own proxy URLs work too.

## Actor input object example

```json
{
  "companies": [
    "https://trimgroup.bamboohr.com/careers",
    "https://emilanderson.bamboohr.com/careers"
  ],
  "maxJobsPerCompany": 25,
  "maxResults": 1000,
  "includeDescription": true,
  "remoteOnly": false,
  "postedWithinDays": 0,
  "minSalary": 0,
  "onlyWithSalary": false,
  "includeMarkdown": true,
  "includeHtml": false,
  "includeAllFields": true,
  "includeRawJson": false,
  "bareNamesOn": "bamboohr",
  "ownFieldsFor": "bamboohr",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `withSalaryUrl` (type: `string`):

No description

## `summary` (type: `string`):

No 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 = {
    "companies": [
        "https://trimgroup.bamboohr.com/careers",
        "https://emilanderson.bamboohr.com/careers"
    ],
    "maxJobsPerCompany": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("deepmine/bamboohr-jobs").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 = {
    "companies": [
        "https://trimgroup.bamboohr.com/careers",
        "https://emilanderson.bamboohr.com/careers",
    ],
    "maxJobsPerCompany": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("deepmine/bamboohr-jobs").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 '{
  "companies": [
    "https://trimgroup.bamboohr.com/careers",
    "https://emilanderson.bamboohr.com/careers"
  ],
  "maxJobsPerCompany": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call deepmine/bamboohr-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,deepmine/bamboohr-jobs"
        }
    }
}
```

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/63aQWtR6nN9QsOev7/builds/HoIXq51QEHIoukAO1/openapi.json
