BambooHR Jobs Scraper - Any Company's Open Jobs
Pricing
from $2.19 / 1,000 job returneds
BambooHR Jobs Scraper - Any Company's Open Jobs
Every open job of any company that hires through BambooHR, one row per job: title, department, employment type, city, state, country, link, and with one switch the posting date, compensation text and full description. A company ID that does not exist is reported, never returned as zero jobs.
Pricing
from $2.19 / 1,000 job returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
21 hours ago
Last modified
Categories
Share
Pull every open job of any company that hires through BambooHR - the careers sites at <company>.bamboohr.com/careers - read straight from the JSON that BambooHR's own careers page loads. No login, no API key, no proxies, no HTML scraping.
One row per job: title, department, employment type, city, state, country and a link to the job page - plus, with one switch, the posting date, the compensation text, the minimum experience level, the postal code and the full job description.
Unofficial. This Actor is not affiliated with, endorsed by, or sponsored by BambooHR. All product names are trademarks of their respective owners.
A company that does not exist is never reported as "0 jobs"
BambooHR answers a company ID that does not exist with a redirect to www.bamboohr.com, and a company that exists but has no openings with totalCount: 0. Those are two different answers, and this Actor keeps them apart: a typo in the company ID gets a company-not-found row that says where to find the right ID, and a company with nothing open gets a no-openings row. Neither is charged, and neither is an empty dataset.
rowType | ok | What it means | Charged? |
|---|---|---|---|
job | true | A real open job | Yes |
no-openings | true | The company's BambooHR careers site exists and lists no open jobs | No |
no-matching-jobs | true | The company has jobs, but none match your filters - the row says how many it has | No |
company-not-found | false | No BambooHR careers site exists for this ID (BambooHR redirects it to www.bamboohr.com). The row tells you where to find the right one | No |
posting-closed | false | A job that was in the list but whose own page says it is gone or no longer Open when its details were read - not returned as an open job | No |
incomplete | false | BambooHR reported more openings than it returned; the jobs that were read are returned | No |
more-jobs-available | true | maxResults cut the list; says how many were left out | No |
not-looked-up | false | Not fetched because maxResults was already reached, or the run was close to its time limit | No |
duplicate-input | false | The same company was given twice (IDs are not case-sensitive); its jobs are returned once | No |
bad-input | false | Not a BambooHR company ID or careers link | No |
unavailable | false | BambooHR could not be reached after retries, or answered in a shape this Actor does not read | No |
budget-reached | false | The run hit your maximum charge before or during this company | No |
You are charged only for job rows.
What BambooHR publishes where - measured, not estimated
Measured 2026-09-12 on 10 companies with open jobs (401auto, basdensteel, montroseholdings, kiln, flyio, cardinal, fbcs, beehiiv, avaindustries, posthog): 208 open jobs, every one of them also read from its own page.
The list (/careers/list) is one request per company - there is no paging - and it carries only part of each job:
| Column | Filled (208 jobs) | Source |
|---|---|---|
title, employmentType, jobUrl | 100% | list |
department | 97% | list |
city / state (location) | 95% | list, from location or, when that is empty, atsLocation |
country | 2% (4 of 208) | list - only a few companies fill it there; 94% (195 of 208) once the job page is read |
postalCode | 0% | list - only on the job page (94%) |
isRemote | 0% | list - BambooHR sends the field but it was null for all 208 jobs, so it stays null here |
The job page (/careers/<id>/detail) is where the rest lives. With includeDescription on, each job costs one more request and the row gains:
| Column | Filled (208 jobs) |
|---|---|
postedAt (date only, as BambooHR gives it), descriptionText | 100% |
minimumExperience, country, postalCode | 94% |
compensationText | 66% |
compensationText is whatever the company typed - $55,000 per year, $19/hr, TBD, Up to $20 DOE - and is left as text. No number is parsed out of it, and nothing is filled in when it is empty.
locationTypeCode is BambooHR's own code (0, 1 or 2). It was 0 for all 194 jobs that carry a street address and 1/2 for the 14 that do not, but BambooHR publishes no key for it, so it is passed through as-is rather than translated into "remote" or "on-site".
Filters
BambooHR's list has no search of its own, so every filter is applied here, after reading the list, against the fields the list carries: titleContains, departmentContains, locationContains and keyword (title, department, location, employment type). Filters do not look into the description. When a filter can never match on a company - it publishes no department, or no location - the no-matching-jobs row says so instead of pretending no job qualifies.
Location needs one more word. The list carries only the city and the state (a country for 4 of the 208 measured jobs, never a postal code). So on its own, locationContains matches city and state - Kitchener, Ontario - and a country or postal code returns a no-matching-jobs row that says exactly this. With includeDescription: true every listed job's page is read before the filter is applied, and locationContains then also matches the country and the postal code: Canada returns 118 of 401 Auto's 124 jobs, N2C the jobs in that Kitchener postal district. Jobs whose page could not be read are judged on the list's city and state only.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
companies | array | (prefilled: 401auto) | BambooHR company IDs or careers links, up to 200. If empty, 401auto is used and every row says so in input |
keyword | string | (empty) | Keep jobs whose title, department, location or employment type contains this text |
titleContains | string | (empty) | Keep jobs whose title contains this text (case-insensitive) |
departmentContains | string | (empty) | Keep jobs whose department contains this text |
locationContains | string | (empty) | Matches city and state from the list (Kitchener, Ontario); with includeDescription also country and postal code (Canada, N2C) |
includeDescription | boolean | false | Read each job's page: adds the description, posting date, compensation text, experience level, postal code and country (one extra request per job, 8 in parallel). With locationContains, every listed job's page is read before filtering |
maxResults | integer | 1000 | Job rows for the whole run; a more-jobs-available row counts the rest, later companies get not-looked-up |
maxRetries | integer | 3 | Attempts per request for temporary errors (HTTP 429 / 5xx) |
Finding a company ID: open the company's careers page. The address looks like https://401auto.bamboohr.com/careers - 401auto is the ID. You can also paste that address, or a job link such as https://401auto.bamboohr.com/careers/560.
Descriptions
With includeDescription on, descriptionStatus says what happened for each job:
ok- the description is indescriptionText(emptyif the page has none)failed: ...- BambooHR did not return the page after retries; the job is still returned and charged, because everything from the list is real, butpostedAt,compensationTextand the other page-only columns staynullnot-fetched-time-limit- the run was close to its time limit, so pages were skipped to return the jobs in time (still charged); companies after it get anot-looked-uprow- A job whose page answers 404 or is no longer marked
Openis not returned as a job - it becomes a freeposting-closedrow
Without includeDescription, descriptionStatus and the page-only columns are null for every job.
Output columns
rowType, ok, note, input, companyId, jobId, title, department, departmentId, employmentType, city, state, country, postalCode, fullLocation, isRemote, locationTypeCode, postedAt, compensationText, minimumExperience, jobUrl, descriptionText, descriptionStatus, searchedKeyword, checkedAt
Every row - including note rows - has all 25 columns in the same order.
Things it refuses to invent or pass on
- No people's names - but the application address stays. The list and the job page carry no recruiter name. Inside descriptions, an e-mail address whose local part looks like a person's name (
jane.doe@,janedoe@) is replaced with[email removed]; role mailboxes such ascareers@,hr@orjobs+infra@and phone numbers are the way to apply, so they are left as written (measured: all 125 addresses and 118 phone numbers in the 208 descriptions were role mailboxes and a company switchboard). isRemoteis only ever what BambooHR sends. A job without a location is not turned into "remote"; itsfullLocationstaysnull.postedAtis the date BambooHR publishes (YYYY-MM-DD). No time of day is added.employmentTypeis the company's own label (Full-Time,Part-Time,Full-Time - Weekly Paid (Ocean Hotels)), not normalised into a guess.- Empty values are
null, never an empty string or a0.
How it is checked
- 71 automated checks, most of which run the real list, page, retry, filter and charging code against recorded BambooHR responses (a company that does not exist, an empty company, a list shorter than its count, closed postings, budget and time limits)
- 72 deliberate defects injected into the source, plus 23 into the charging path; every one was caught by those checks (re-run 2026-09-12)
- The rows this Actor returns for the 10 measured companies were compared against the companies' lists fetched directly: 208 of 208 jobs, same IDs, same order
- Only public careers pages are read. Nothing needs a login
- Every request has a 45-second timeout; temporary errors are retried with a growing pause
Support
Found a company that behaves oddly? Open an issue on the Issues tab with the company ID - it will be reproduced against the live careers site before anything is changed.