# BambooHR Careers Scraper — Company Hiring Signals (`foxlabs/bamboohr-ats-scraper`) Actor

Search open jobs across thousands of BambooHR companies by job title, location, department, remote/hybrid and date — no subdomains needed. Live data with real company name and logo, department, workplace, type, salary where published, posted date, full description, apply URL.

- **URL**: https://apify.com/foxlabs/bamboohr-ats-scraper.md
- **Developed by:** [Berkan Kaplan](https://apify.com/foxlabs) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 job posting delivereds

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/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 Careers Scraper — Company Hiring Signals 🚀

**foXLabs hiring series:** [Greenhouse](https://apify.com/foxlabs/greenhouse-job-board-scraper) · [Lever](https://apify.com/foxlabs/lever-job-board-scraper) · [Ashby](https://apify.com/foxlabs/ashby-job-board-scraper) · [Workday](https://apify.com/foxlabs/workday-job-board-scraper) · [SmartRecruiters](https://apify.com/foxlabs/smartrecruiters-job-board-scraper) · [Personio](https://apify.com/foxlabs/personio-job-board-scraper) · [Teamtailor](https://apify.com/foxlabs/teamtailor-job-board-scraper) · [Workable](https://apify.com/foxlabs/workable-ats-scraper) · **[All platforms in one search →](https://apify.com/foxlabs/job-postings-database)**

🎉 Search open jobs across 7,500+ companies that hire on BambooHR — by job title, location, department, remote/hybrid and date — without knowing a single company subdomain. No login, no API key, one row per open role, with the company's real name and logo.
Built for sales & competitive-intelligence teams scoring hiring intent, recruiters, and job-data pipelines.

### 🔍 What is the BambooHR Careers Scraper — and when should you use it?

BambooHR powers the careers sites of tens of thousands of small and mid-market companies, but it has no job search of its own: every company's jobs sit on a separate `{company}.bamboohr.com` site. This actor does the searching for you. It carries an index of BambooHR careers sites (discovered from the public Common Crawl web archive), reads each site's job list **live** during your run, keeps the jobs that match your title keywords and filters, and returns them with full details — title, department, location, country, workplace (on-site / remote / hybrid), employment type, seniority, salary where published, posted date, full description and apply link — plus the company's display name and logo.

Already know your target companies? Add their subdomain (`acme`) or careers URL and get every open role on them.

**Use it when you need:** small and mid-market companies hiring for a function right now; a feed of new roles for a job title; every open role at a target company; or a read on a competitor's hiring plans.

**Use something else when:** the companies you care about don't run on BambooHR. Point the matching actor at their ATS instead — [Greenhouse](https://apify.com/foxlabs/greenhouse-job-board-scraper), [Lever](https://apify.com/foxlabs/lever-job-board-scraper), [Ashby](https://apify.com/foxlabs/ashby-job-board-scraper), [Workday](https://apify.com/foxlabs/workday-job-board-scraper), [SmartRecruiters](https://apify.com/foxlabs/smartrecruiters-job-board-scraper), [Personio](https://apify.com/foxlabs/personio-job-board-scraper), [Teamtailor](https://apify.com/foxlabs/teamtailor-job-board-scraper) or [Workable](https://apify.com/foxlabs/workable-ats-scraper). Every one emits the **same core schema**, so their outputs concatenate into one hiring-intent table.

**Need one search across every platform?** [Job Postings Database](https://apify.com/foxlabs/job-postings-database) keeps a daily-refreshed index of 440,000+ open roles from ~33,000 Greenhouse, Lever, Ashby, SmartRecruiters, BambooHR, Personio and Teamtailor boards and answers a single query across all of them in seconds — every delivered role is re-checked live on its own board before it reaches you.

### 🤖 Use with AI agents

**Already on the Apify MCP server?** Ask for this Actor by name: `foxlabs/bamboohr-ats-scraper`.

**Your agent can pay for its own runs.** This Actor is pay-per-event with agentic payments, so an agent can discover it, run it and settle the bill over **x402 (USDC on Base)** or **Skyfire** — no Apify account or API token of its own. Billing is the same either way: per delivered role, never for errors.

Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```
I want to find open jobs at companies that hire on BambooHR using the Apify Actor
`foxlabs/bamboohr-ats-scraper`.

Input: `searchQueries` is a list of job-title keywords (every word must appear in the title;
"*" = every job). Optional filters: `location` (text the city/state/country must contain, e.g. "Texas"),
`department` (e.g. "Sales"), `workplace` ("remote" | "hybrid" | "on_site"),
`employmentType` (e.g. "Full-Time"), `postedWithinDays` ("1" | "7" | "30" | "90").
`maxResultsPerQuery` caps jobs per keyword (default 200).
Each row has companyName, companyLogo, jobTitle, department, location, countryName, workplace,
employmentType, seniority, salary, postedAt, description and applyUrl.

Start with:
{ "searchQueries": ["account manager"], "location": "United States", "maxResultsPerQuery": 50 }

Ask me which roles and region I care about, run the Actor, then summarise the hiring companies as a table.
```

Things you can ask your agent for:

- "Which BambooHR companies are hiring nurses in Montana? List them with the roles."
- "Remote marketing jobs posted in the last 7 days, as a table."
- "Pull every role on this BambooHR careers site and group them by department."

The machine-readable API, MCP config and OpenAPI definition live at `apify.com/foxlabs/bamboohr-ats-scraper.md`.

### 📋 Overview

Everything you need to turn BambooHR's scattered careers sites into one searchable hiring dataset — in one actor, with no login, cookies or API key.

**Why teams pick this actor:**

- 🔎 **No subdomains needed** — search 7,500+ BambooHR companies by job title; the companies come to you.
- ⚡ **Live, not a stale dump** — every matching company's job list is read during your run.
- 🎛️ **Filters that matter** — location, department, workplace (on-site / remote / hybrid, as the employer set it), employment type, posting date.
- 🏢 **Real company names** — the display name and logo from the careers site, not a guess from the subdomain (`bvhc` → "One Health").
- 💸 **Salary where published** — the compensation string is surfaced when the company lists one.
- 🔗 **Same schema across the series** — join BambooHR output with the other ATS actors on `companyName` / `companyBoard`.
- 💰 **Pay only for results** — per-role pricing; a job found by two keywords is charged once; empty searches and failed lookups are never billed.
- 🤖 **Agent-ready** — MCP + x402 agentic payments.

### ✨ Features

- 🔍 **Title search across the BambooHR index** — stops as soon as it has the number of matches you asked for.
- 📄 **Complete role details** — title, department, location, country, workplace, remote flag, employment type, seniority, salary, posted date, full description (HTML stripped), apply URL.
- 🏢 **Company block** — `companyName`, `companyLogo`, `companyJobsUrl`, `companyBoard`.
- 📋 **Company sites** — every open role on a careers site by subdomain or URL.
- 🧹 **Deduplicated** — overlapping keywords never deliver or bill the same job twice.
- 📦 **Clean export** — stable camelCase rows, ready for CSV/Excel/JSON.

### 🎬 Quick Start

```bash
curl -X POST "https://api.apify.com/v2/acts/foxlabs~bamboohr-ats-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries": ["account manager"], "location": "United States", "maxResultsPerQuery": 50}'
```

### 🚀 Getting Started (3 steps)

1. **Type your job titles** — one per line (`nurse`, `account manager`), or `*` for every job.
2. **Narrow it down (optional)** — location, department, workplace, employment type, posting date.
3. **Run and export** — get a clean dataset as JSON, CSV or Excel.

### 📥 Input

```json
{
  "searchQueries": ["account manager", "customer success"],
  "location": "United States",
  "department": "Sales",
  "workplace": "remote",
  "employmentType": "Full-Time",
  "postedWithinDays": "30",
  "queries": ["concept2"],
  "maxResultsPerQuery": 200
}
```

| Field | Type | Description |
|---|---|---|
| `searchQueries` | array | Job-title keywords, one per line. Every word must appear in the title (`engineer` also matches `engineering`). `*` = every job matching the filters. |
| `location` | string | Text the job's city, state or country must contain, e.g. `Texas`, `London`, `Canada`. |
| `department` | string | Text the department must contain, e.g. `Sales`, `Nursing`. |
| `workplace` | string | `any`, `remote`, `hybrid` or `on_site` — as the employer set it in BambooHR. |
| `employmentType` | string | Text the employment type must contain, e.g. `Full-Time`, `Part-Time`, `Contract`, `Intern`. |
| `postedWithinDays` | string | `any`, `1`, `7`, `30` or `90`. Jobs with no published date are left out when set. |
| `queries` | array | Optional company sites: subdomains (`acme`) or careers URLs. Search filters do not apply to them. |
| `maxResultsPerQuery` | integer | Caps jobs per keyword or company (default 200). |
| `maxConcurrency` | integer | How many keywords/companies to run at once (default 4). |
| `scanConcurrency` | integer | How many careers sites one search reads at once (default 25). |
| `includeRaw` | boolean | Attach the source's untouched record under `raw`. |
| `requestDelayMs` | integer | Politeness delay between requests. |
| `proxyConfiguration` | object | Optional — BambooHR careers sites answer datacenter IPs directly. |

### 📤 Output

One row per open role, saved to the dataset.

| Field | Type | Description |
|---|---|---|
| `companyName` | string | Company display name from its careers site |
| `companyBoard` | string | BambooHR subdomain — the join key across runs |
| `companyLogo` | string | Company logo URL |
| `companyJobsUrl` | string | The company's BambooHR careers site |
| `jobId` | string | BambooHR job opening ID |
| `jobTitle` | string | Role title |
| `department` | string | Department the role sits in |
| `location` | string | City, state and country as posted (for remote roles: the remote location) |
| `city` / `countryName` | string | Parsed location parts |
| `workplace` | string | `on_site`, `remote` or `hybrid`, as set in BambooHR |
| `isRemote` | boolean | True when the role is remote or reads as remote |
| `employmentType` | string | Full-Time, Part-Time, Contract… |
| `seniority` | string | Minimum experience level as posted |
| `salary` | string | Compensation, where the company publishes one |
| `postedAt` | string | Date the role was posted (ISO) |
| `description` | string | Full role description, HTML stripped |
| `applyUrl` / `sourceUrl` | string | Apply link / public posting URL |

Every row also carries `query`, `scrapedAt`, and — when a search finds nothing or a lookup fails — an `error` explaining why.

```json
{
  "source": "BambooHR",
  "query": "designer",
  "companyName": "Greenpark",
  "companyBoard": "greenparkcontent",
  "companyLogo": "https://pandabox.bamboohr.com/eu-west-1/company_logo/422691/cropped?v=33",
  "companyJobsUrl": "https://greenparkcontent.bamboohr.com/careers",
  "jobId": "768",
  "jobTitle": "Graphic Designer (Philippines)",
  "department": "Creative",
  "location": "Manila, Manila, Philippines",
  "city": "Manila",
  "countryName": "Philippines",
  "workplace": "hybrid",
  "isRemote": false,
  "employmentType": "Fixed-Term Employee",
  "seniority": "Mid-level",
  "postedAt": "2026-03-13",
  "applyUrl": "https://greenparkcontent.bamboohr.com/careers/768"
}
```

### 💼 Use cases

**1. Hiring-intent lead lists** — a company that just opened sales roles is buying sales tooling.
*Input:* `searchQueries: ["account executive", "sales manager"]`, `postedWithinDays: "30"`, scheduled weekly. *Output:* hiring companies with their roles. *Use:* rank accounts by what they're recruiting for.

**2. New-role feed** — new postings for a job title in a region.
*Input:* your titles, `location`, `postedWithinDays: "7"`. *Output:* fresh postings with apply links. *Use:* job boards, alerts, market dashboards.

**3. Competitor headcount tracking** — watch which functions a peer grows and which freeze.
*Input:* the competitor's careers site in `queries`, run weekly. *Output:* the full role list over time. *Use:* spot expansion and hiring freezes early.

**4. Recruiter sourcing** — every open role for a title, with salary where listed.
*Input:* `searchQueries: ["controller"]`, `workplace: "remote"`. *Output:* one table of roles + companies. *Use:* build a sourcing pipeline in minutes.

### 🔗 Integration

**JavaScript / Node.js**

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('foxlabs/bamboohr-ats-scraper').call({
  searchQueries: ['account manager'], location: 'United States', maxResultsPerQuery: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

**Python**

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('foxlabs/bamboohr-ats-scraper').call(
    run_input={'searchQueries': ['account manager'], 'location': 'United States', 'maxResultsPerQuery': 50}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)
```

Written for `apify-client` 3 for Python, where `call()` returns a run object; with version 1 or 2 it returns a dict — write `run['defaultDatasetId']` there.

**Automation (n8n / Zapier / Make):** schedule or webhook → HTTP request to the actor API with your `searchQueries` → handle the JSON dataset → push to a sheet, CRM or dashboard.

### 📊 Pricing

Pay-per-event: **$0.002 per delivered role**. A job found by two of your keywords is charged once; empty searches and failed lookups are never billed; jobs that don't match your filters are never billed. [View current pricing.](https://apify.com/foxlabs/bamboohr-ats-scraper)

### ❓ FAQ

**Do I need a BambooHR account, login or API key?** No. This reads the public BambooHR careers API — the same endpoints each company's own careers page calls.

**Do I need to know company subdomains?** No. Search by job title; every row tells you the company. Subdomains are only for when you want one specific company's full list.

**Which companies does the search cover?** BambooHR careers sites found in the public Common Crawl web archive — 7,510 sites, of which 7,509 had a live careers board in our last full check (October 2026). A company that isn't in the index can still be read by adding its subdomain to `queries`.

**How current is the data?** Every run reads the matching careers sites live, so jobs are as fresh as the sites themselves.

**Why is `companyWebsite` missing?** BambooHR careers sites don't publish the company's website, and guessing it from the name would be wrong too often, so it is left out rather than invented.

**Can I export to CSV / Excel / JSON?** Yes — directly from the Apify dataset.

**What happens when a search finds nothing or a subdomain is wrong?** You get a row carrying your `query` and an `error` — nothing is silently dropped, and you're not charged.

### 🐛 Troubleshooting

- **Fewer rows than expected** — title matching is strict (every word must appear in the title); try fewer or shorter keywords, or loosen the filters.
- **"BambooHR has no public careers site at …"** — the subdomain is wrong or that company doesn't host careers on BambooHR; take the subdomain from the careers URL (the part before `.bamboohr.com`).
- **A large `*` search takes a while** — it reads every careers site in the index; set `maxResultsPerQuery` to what you need and it stops early.

### ⚠️ Trademark

Independent, third-party tool. Not affiliated with, endorsed by or connected to BambooHR LLC. "BambooHR" and related marks belong to their owners and are used here for identification only.

### ⚖️ Is it legal to scrape this data?

This actor reads only publicly published job-posting data — no private or personal user data. Your results can still contain personal data (e.g. a recruiter name in a description); personal data is protected by the GDPR and similar laws, so only process it with a legitimate basis. See Apify's blog post on the legality of web scraping.

### 🤝 Support & contact

- 🌐 **Website:** [data.foxlabs.com.tr](https://data.foxlabs.com.tr)
- 📧 **Email:** info@foxlabs.com.tr
- 🐛 **Issues:** open a ticket in the Actor's **Issues** tab
- 🧰 **More clean B2B data actors:** [Fox Labs on Apify](https://apify.com/foxlabs)

### Changelog

#### Index refresh — 2026-10-14

- Company index refreshed from the latest public web-archive snapshots: no new careers sites found, 1,323 that no longer exist removed (checked live on 2026-10-14); the index now holds 7,510 careers sites, 7,509 of them answering and 1 temporarily unreachable (kept).

#### 0.2.0 — 2026-10-14

- **New: job-title search across 7,500+ BambooHR companies** (`searchQueries`) — no subdomain needed. The actor walks a bundled index of BambooHR careers sites, reads each one live and keeps matching jobs. Filters: `location`, `department`, `workplace`, `employmentType`, `postedWithinDays`.
- **Real company names and logos** from each careers site (`companyName` used to be the subdomain in title case, e.g. "Bvhc" instead of "One Health"). New fields: `companyLogo`, `companyJobsUrl`, `workplace`.
- Remote roles now carry their location (BambooHR stores it separately for remote jobs).
- A job found by several keywords is delivered and charged once.
- `queries` (company sites) works as before and is now optional.

#### 0.1.0 — 2026-10-11

- Initial release: full open-roles extraction from any BambooHR careers site by subdomain or URL (list + per-role detail), with department, parsed location, country, seniority, salary where published, HTML-stripped description and apply URL. Shares the hiring-signal core and schema (`companyBoard` join key) with the Greenhouse/Lever/Ashby/… series.

# Changelog

This Actor's version history is a separate document: https://apify.com/foxlabs/bamboohr-ats-scraper/changelog.md

# Actor input Schema

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

Search open jobs across thousands of companies that hire on BambooHR — no company subdomain needed. One keyword or phrase per line, matched against the job title (every word must appear; `engineer` also matches `engineering`), e.g. `nurse`, `account executive`, `controller`. Use `*` for every job that matches the filters below. A job found by two lines is delivered and charged once.

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

Keep only jobs whose city, state or country contains this text, e.g. `Texas`, `London`, `Canada` (keyword search).

## `department` (type: `string`):

Keep only jobs whose department contains this text, e.g. `Sales`, `Engineering`, `Nursing` (keyword search).

## `workplace` (type: `string`):

Keep only on-site, remote or hybrid jobs, as the employer set it in BambooHR (keyword search).

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

Keep only jobs whose employment type contains this text, e.g. `Full-Time`, `Part-Time`, `Contract`, `Intern` (keyword search).

## `postedWithinDays` (type: `string`):

Keep only jobs posted recently (keyword search). Jobs whose employer published no date are left out when this is set.

## `queries` (type: `array`):

Already know the companies? Add BambooHR company subdomains (`acme`) or careers URLs (`https://acme.bamboohr.com/careers`) to get every open role on those sites. Search filters do not apply to companies listed here.

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

How many jobs one search line or one company may return. A search stops walking the company index as soon as it has this many matches.

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

How many search lines/companies to run at the same time.

## `scanConcurrency` (type: `integer`):

How many BambooHR careers sites one search reads at the same time while walking the index. Lower it if you see throttling.

## `includeRaw` (type: `boolean`):

Attach the source's untouched response under `raw`. Useful when you need a field this actor does not map.

## `requestDelayMs` (type: `integer`):

Politeness delay against a public source. Raise it for large runs.

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

Optional. BambooHR careers sites answer datacenter IPs directly.

## Actor input object example

```json
{
  "searchQueries": [
    "sales"
  ],
  "workplace": "any",
  "postedWithinDays": "any",
  "maxResultsPerQuery": 200,
  "maxConcurrency": 4,
  "scanConcurrency": 25,
  "includeRaw": false,
  "requestDelayMs": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "searchQueries": [
        "sales"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("foxlabs/bamboohr-ats-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": ["sales"] }

# Run the Actor and wait for it to finish
run = client.actor("foxlabs/bamboohr-ats-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": [
    "sales"
  ]
}' |
apify call foxlabs/bamboohr-ats-scraper --silent --output-dataset

```

## MCP server setup

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