# BambooHR Scraper \[Only $0.90/1K💰] | Jobs | Salary | Openings (`ahmed_jasarevic/bamboohr-scraper`) Actor

Extract every open role from any BambooHR careers board - title, department, location, remote flag, salary and full description - via BambooHR's public JSON endpoints. Build job feeds, hiring-intent lists and labour-market datasets with no API key, no login and no browser.

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

## Pricing

from $0.85 / 1,000 results

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 Scraper

BambooHR scraper that pulls every open job from any company's BambooHR careers board through the same public JSON endpoints the careers page itself uses - job title, department, location, remote status, salary, full description and apply URL. No login, no API key and no browser.

### Main Use Cases

- Build a live job-board or ATS aggregation feed from thousands of SMB career pages
- Collect hiring-intent signals for recruiters, staffing agencies and B2B sales teams
- Run labour-market and salary research across companies, departments, countries and cities
- Monitor new and updated openings for a watchlist of target companies
- Enrich CRM and lead lists with the roles a prospect is currently hiring for

### How It Works

![How the BambooHR Scraper works: any public careers board to every open role, pay range and location.](https://api.apify.com/v2/key-value-stores/oeuA0kLOyhbRM4fzt/records/how-it-works-bamboohr.webp)

BambooHR hosts a public careers page at `https://{company-slug}.bamboohr.com/careers`. That page loads its data from two unauthenticated JSON endpoints, which this actor calls directly with a plain HTTP crawler:

1. `GET https://{slug}.bamboohr.com/careers/list` returns a JSON index of every open posting (id, title, department, employment status, city/state, remote flags).
2. `GET https://{slug}.bamboohr.com/careers/{id}/detail` returns the full record for one job - HTML description, free-text compensation, posting date, structured location and share URL.

The company display name is not in the JSON, so it is read once per board from the `og:site_name` meta tag on the careers HTML. Because the endpoints are plain JSON, the actor runs on a lightweight Cheerio (HTTP) crawler - no headless browser is involved. Dead or suspended tenants redirect to the BambooHR marketing site instead of returning JSON, and those boards are logged and skipped rather than failing the run.

### Scrape BambooHR Job Listings Without An API Key

BambooHR's official jobs API ("Get Job Summaries") requires OAuth and an authenticated caller with access to ATS settings, and it only returns jobs for the account that authenticates. The public careers feed that this actor reads needs no credentials, works for any company hosted on BambooHR, and returns the same postings the employer already publishes to every visitor - including the description, country and pay text that the official summaries endpoint does not carry.

Because BambooHR has no public directory of company slugs, you supply the boards you want either as a bare subdomain (`home`) or as a full URL (`https://home.bamboohr.com/careers`).

### Input

| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
| `boards` | string\[] | No | 14 curated boards (~104 combined openings) | Company slugs (`"home"`) or full board URLs (`"https://home.bamboohr.com/careers"`). Both forms are accepted per entry. |
| `maxResults` | integer | No | `100` | Maximum job postings returned in total across all boards. Range 1-5000. |
| `includeDescription` | boolean | No | `true` | Fetch each job's detail page for the full description, salary text, country and posting date. Turn off for a faster list-only scrape (title, location, department, type). |
| `proxy` | object | No | off | Apify Proxy picker. Only needed if a specific board rate-limits datacenter IPs. |

### Output

One dataset item per job opening:

| Field | Description |
|---|---|
| `jobId` | Job opening ID on the BambooHR board |
| `title` | Job title |
| `company` | Company display name (from the board HTML) |
| `companySlug` | BambooHR subdomain, e.g. `home` for `home.bamboohr.com` |
| `boardUrl` | Root URL of the company careers board |
| `department` | Department label |
| `employmentType` | Employment status/type, e.g. `Full-Time` |
| `location` | Combined location string |
| `city`, `state`, `country`, `postalCode` | Structured location fields |
| `isRemote` | `true` when the posting is explicitly remote, `null` when unknown |
| `workArrangement` | `"remote"` when remote, otherwise `null` |
| `locationType` | Raw BambooHR `locationType` code |
| `salaryRaw` | Compensation exactly as the employer wrote it |
| `salaryMin`, `salaryMax` | Best-effort parsed salary bounds |
| `salaryCurrency` | `USD` / `EUR` / `GBP` / `CAD` / `AUD` when detectable |
| `salaryPeriod` | `hourly` / `monthly` / `yearly` |
| `postedDate` | ISO date the opening was posted |
| `descriptionText` | Plain-text job description |
| `descriptionHtml` | Original HTML job description |
| `url`, `applyUrl` | Public posting and application URL |
| `scrapedAt` | ISO timestamp of the scrape |

### Example Input

```json
{
  "boards": [
    "home",
    "bibliu",
    "https://framellc.bamboohr.com/careers"
  ],
  "maxResults": 200,
  "includeDescription": true
}
```

### Example Output

```json
{
  "jobId": "15",
  "title": "IT Security Engineer",
  "company": "Home Instead",
  "companySlug": "home",
  "boardUrl": "https://home.bamboohr.com/careers",
  "department": "IT",
  "employmentType": "Full-Time",
  "location": "Salt Lake City, Utah, United States",
  "city": "Salt Lake City",
  "state": "Utah",
  "country": "United States",
  "postalCode": "84101",
  "isRemote": false,
  "workArrangement": null,
  "locationType": "0",
  "salaryRaw": "$80,000 - $100,000 per year",
  "salaryMin": 80000,
  "salaryMax": 100000,
  "salaryCurrency": "USD",
  "salaryPeriod": "yearly",
  "postedDate": "2026-04-30",
  "descriptionText": "About Us - Our mission is simple...",
  "descriptionHtml": "<p>About Us - Our mission is simple...</p>",
  "url": "https://home.bamboohr.com/careers/15",
  "applyUrl": "https://home.bamboohr.com/careers/15",
  "scrapedAt": "2026-10-15T14:47:38.000Z"
}
```

### Integrations & Automation

- **Apify API / JavaScript / Python clients** - pull the dataset programmatically for a job board, CRM or data warehouse.
- **Webhooks** - trigger a downstream workflow whenever a run finishes.
- **Zapier, Make, Google Sheets** - push new openings into a spreadsheet or alerting channel.
- **Scheduling** - run daily (or a few times a day) over a company watchlist to catch new and updated roles quickly. Recurring runs are the recommended way to use this actor as a hiring-intent feed.

### Related Actors

- [BambooHR Jobs Scraper & API - Any Company](https://apify.com/memo23/bamboohr-scraper) - the most established BambooHR scraper in the Store.
- [BambooHR Jobs Scraper](https://apify.com/devilscrapes/bamboohr-jobs-scraper) - multi-tenant BambooHR careers scraper.
- [BambooHR Jobs Scraper - Any Company Careers (No Key)](https://apify.com/ninhothedev/bamboohr-jobs-scraper) - list-only variant.
- [Apna Scraper](https://apify.com/ahmed_jasarevic/apna-scraper) - India blue-collar job listings for a non-ATS source.
- [Welcome to the Jungle Scraper](https://apify.com/ahmed_jasarevic/welcometothejungle-scraper) - tech-job listings to round out a multi-source jobs dataset.

### FAQ

#### Why use this actor instead of the official BambooHR API?

BambooHR's official "Get Job Summaries" endpoint requires OAuth authentication and an account with access to ATS settings - it returns the openings of the authenticated account only. This actor reads the public careers feed that every BambooHR-hosted company already serves to visitors, so you can collect jobs from any company you know the subdomain for, with no credentials and no per-account setup.

#### How can I collect job postings from a company that is not in the default board list?

BambooHR has no public directory of company subdomains, so you add boards yourself: pass the company's subdomain (for `https://acme.bamboohr.com/careers`, use `acme`) or the full careers URL in the `boards` field. If a company embeds its board in its own website, view the page source and look for a `*.bamboohr.com` host.

#### What are alternatives to this actor?

If you need a hosted jobs API instead of scraping, BambooHR's own jobs API (with an account and OAuth scope) or third-party normalized-jobs APIs are options - but they require credentials and typically only cover the accounts or employers they index. For a self-contained, keyless scrape of any BambooHR board, this actor is the direct route.

#### Why are some fields null?

BambooHR exposes remote status, country and salary inconsistently across tenants. `isRemote` is `null` when the employer left it unspecified (it does not mean "on-site"), salary is free text so it is empty on postings without published pay, and evergreen postings can carry a `postedDate` far in the past even though the role is still open.

### For AI Agents & LLM Apps

Purpose: return one structured record per open job on any BambooHR careers board, from the public `/careers/list` and `/careers/{id}/detail` JSON endpoints.

Minimal working input:

```json
{ "boards": ["home"] }
```

Output fields: `jobId`, `title`, `company`, `companySlug`, `boardUrl`, `department`, `employmentType`, `location`, `city`, `state`, `country`, `postalCode`, `isRemote`, `workArrangement`, `locationType`, `salaryRaw`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `postedDate`, `descriptionText`, `descriptionHtml`, `url`, `applyUrl`, `scrapedAt`.

Behaviors an agent should know:

- `boards` is the only field that selects the data; if it is omitted, the actor scrapes a default curated set of 14 boards, not "all companies" - there is no public subdomain directory.
- `maxResults` defaults to 100 and caps total rows (1-5000); set it explicitly for large runs.
- `includeDescription` defaults to `true` and issues one extra HTTP request per job. Turning it off keeps `title`, `department`, `employmentType` and `location` but leaves `descriptionText`, `descriptionHtml`, `salary*`, `country` and `postedDate` empty.
- Dead/suspended tenants are skipped and logged; a board that returns HTML instead of JSON yields no rows rather than an error.

Billing: pay-per-event, charged per result row (about $0.90 per 1,000 jobs on the free tier, lower on paid Apify plans), plus the one-time actor-start event.

### Legal & Compliance Disclaimer

This actor is independent and is not affiliated with, endorsed by, or sponsored by BambooHR. It accesses only publicly available career pages and the public JSON endpoints those pages call; it does not log in, bypass authentication, or solve CAPTCHAs on any account-gated surface. Users are responsible for complying with BambooHR's and the source companies' terms of service and with applicable data-protection law when storing or republishing the collected job data. The dataset contains company job-posting information, not private personal contact data.

### SEO Keywords

bamboohr scraper, bamboohr jobs api, bamboohr careers scraper, scrape bamboohr job listings, bamboohr api alternative, hiring intent data, job posting api, ats job scraping, company careers page scraper, job board aggregator data, remote job listings api, salary data extraction, job listing monitoring, recruiting intelligence, greenhouse lever bamboohr jobs, applicant tracking system data, smb hiring data, job openings dataset

# Actor input Schema

## `boards` (type: `array`):

Company slugs or board URLs to scrape. Accepts a plain slug (e.g. "home") or a full URL (e.g. "https://home.bamboohr.com/careers"). Defaults to a curated set of 14 boards with ~104 combined openings.

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

Maximum number of job postings to return in total across all boards.

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

Fetch each job's full description page. Turn off for a faster list-only scrape (title, location, department, type).

## `proxy` (type: `object`):

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "boards": [
    "bibliu",
    "r2",
    "netvendor",
    "barrows",
    "framellc",
    "cobaltai",
    "globalmediaoutreach",
    "smdynamic",
    "home",
    "advancedmaterial",
    "base",
    "ci0tech",
    "native",
    "extractable"
  ],
  "maxResults": 100,
  "includeDescription": true,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `jobs` (type: `string`):

Dataset items — one scraped BambooHR job opening per item (title, company, location, salary, description, apply URL).

# 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 = {
    "boards": [
        "bibliu",
        "r2",
        "netvendor",
        "barrows",
        "framellc",
        "cobaltai",
        "globalmediaoutreach",
        "smdynamic",
        "home",
        "advancedmaterial",
        "base",
        "ci0tech",
        "native",
        "extractable"
    ],
    "maxResults": 100,
    "includeDescription": true,
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/bamboohr-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 = {
    "boards": [
        "bibliu",
        "r2",
        "netvendor",
        "barrows",
        "framellc",
        "cobaltai",
        "globalmediaoutreach",
        "smdynamic",
        "home",
        "advancedmaterial",
        "base",
        "ci0tech",
        "native",
        "extractable",
    ],
    "maxResults": 100,
    "includeDescription": True,
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/bamboohr-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 '{
  "boards": [
    "bibliu",
    "r2",
    "netvendor",
    "barrows",
    "framellc",
    "cobaltai",
    "globalmediaoutreach",
    "smdynamic",
    "home",
    "advancedmaterial",
    "base",
    "ci0tech",
    "native",
    "extractable"
  ],
  "maxResults": 100,
  "includeDescription": true,
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/bamboohr-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/bamboohr-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/SsffwgsckhJUIdkgO/builds/W6XW9znG1IyG0rjbE/openapi.json
