# ATS Job Postings Scraper - 12 Platforms, Auto-Detect, No Key

Live job postings from Greenhouse, Lever, Ashby, Recruitee, Workable, Rippling, Pinpoint, Breezy, BambooHR, Personio, Eightfold and Taleo. Auto-detects each company's ATS. No API key, one schema.

Canonical product page: https://mayd-it.com/data-tools/actors/ats-job-postings-scraper/
Public Actor: https://apify.com/maydit/ats-job-postings-scraper

## Example input

```json
{
  "companies": [
    "dropbox",
    "linear",
    "bunq",
    "blueground",
    "visa",
    "swordhealth",
    "spotify"
  ],
  "includeDescription": false,
  "maxResults": 10
}
```

## Full guide

![One job table, twelve ATS platforms — illustrative workflow](https://api.apify.com/v2/key-value-stores/YGxD9JRpduom8Q5Zd/records/ats-job-postings-scraper-6d5c03faf517.png?signature=10J42IebamMS5znmKZ80c)

## One job table, twelve ATS platforms

Bring a target-company list and collect public openings across twelve supported ATS platforms. This is useful for recruiting pipelines and hiring research when employers use different job-board systems.

[Open this Actor in Console](https://console.apify.com/actors/zkwXPahBHDRl7gxHu/input) · [First run](#try-this-actor) · [Results](#result-preview) · [Cost](#usage-and-pricing) · [Full guide](#full-guide)

## Try this Actor

1. **Choose a small scope.** Begin with one documented board slug or supported board URL in **Companies**. If using a direct platform list instead, clear the prefilled sample companies. Set the total results cap for a bounded first look and leave job descriptions off unless needed.
2. **Run and review.** Open the run's dataset for postings and the key-value-store `SUMMARY` for companies found, failed platform checks, unprocessed companies and limits.
3. **Use the results.** Export CSV or JSON and retain `ats`, company and posting links. The platform coverage table below explains which details each source exposes.

**Read this before using the data:** Use board identifiers, not arbitrary company display names. This is not a search across every employer. Missing fields reflect source coverage; incomplete snapshots cannot prove that omitted jobs closed.

## Result preview

The dataset view highlights these columns:

- **Company** · `company`
- **Source ATS** · `ats`
- **Job title** · `title`
- **Department** · `department`
- **Location** · `location`
- **Remote** · `remote`

Use the original source links and the field definitions below when interpreting the results. CSV works well for flat columns; JSON preserves nested values.

## Usage and pricing

Base result rate on the FREE tier: **$2.5 per 1,000 results**. The [Pricing tab](https://apify.com/maydit/ats-job-postings-scraper/pricing) shows your plan's result rate and any Actor Start charge. Set a small result limit for the first run; the requested limit is not a guarantee of that many results.

---

## Full guide

> Supply employer board slugs or supported career-board URLs to collect postings across twelve applicant tracking systems. Slug-based detection checks supported platforms; it is not a company-name search.

### What it does

Supply a company board slug or a supported career-board URL to collect its published job postings. This ATS job postings scraper reads company career boards on **twelve applicant tracking systems - Greenhouse, Lever, Ashby, Recruitee, Workable, Rippling, Pinpoint, Breezy HR, BambooHR, Personio, Eightfold and Oracle Taleo** - and returns one normalized row per posting. Give it a company slug and it **auto-detects which ATS that company uses**, then queries the same public, keyless job-board endpoints that render the company's careers page: nothing is served from a database, so every row is what the board publishes at the moment you run. Filter by title, location or remote-only, optionally attach the full job description, and export to CSV, JSON, Excel or Google Sheets. Because it turns live openings into structured data, it doubles as a hiring-signals source for sales prospecting and labor-market research.

A supported board slug can be checked across the twelve platforms without selecting its ATS first. When an employer uses a different tenant identifier, supply that identifier or its supported career-board URL.

### Who it's for

- **Recruiters and sourcers** building candidate pipelines from live career-board openings
- **Job boards and aggregators** ingesting normalized postings from many ATS platforms at once
- **Sales and BD teams** using hiring signals as buying intent for prospecting
- **Labor-market researchers and analysts** tracking roles, locations, employment types and published pay
- **Job seekers** monitoring target companies' openings over time

### What you get / Output

One record per job posting. Fields:

| Field | Description |
|---|---|
| `ats` | Which ATS the posting came from: `greenhouse`, `lever`, `ashby`, `recruitee`, `workable`, `rippling`, `breezy`, `pinpoint`, `bamboohr`, `personio`, `eightfold` or `taleo` |
| `company` | The slug you passed (the company's identifier on that platform) |
| `title` | Job title |
| `department` | Department, where the ATS exposes it (see the coverage table) |
| `team` | Team or sub-department, where the ATS exposes it: Greenhouse (office), Lever, Ashby, Rippling (with descriptions on), Eightfold apply-family boards (business unit). Empty on the other platforms, which publish no such field |
| `location` | Location string as published; a posting open in several places lists them joined with `; ` |
| `remote` | `true` when the posting can be worked fully remotely: the ATS marks it remote, or one of its listed locations is a remote one (text containing `remote` or `distributed`, e.g. `US - Remote`, `Remote (Canada)`). A hybrid or on-site posting with no remote location is never `true`: it shows `false` where the platform states hybrid/on-site, and stays empty on platforms that publish no workplace field (Greenhouse, Personio, Taleo - there only the location text can set it to `true`). On Ashby and Lever a posting can list extra locations that the `location` column (primary location) does not show, so a row can read `New York, NY (HQ)` with `remote` `true` because it also offers `Remote (US)` |
| `workplaceType` | `remote`, `hybrid` or `onsite`: the posting's workplace type as published by Ashby, Lever, Pinpoint, BambooHR and Eightfold, read from Recruitee's remote / hybrid / on-site flags, from Rippling's typed location labels (`Remote (...)`, `Hybrid (...)`) and from Breezy's per-location remote/hybrid flag. Workable only marks `remote` postings; Greenhouse, Personio and Taleo have no such field, so it stays empty there, as it does wherever the ATS leaves it unset. Eightfold's fourth value `remote_local` (remote within the listed country or region) is reported as `remote`. It is one value per posting, so a `hybrid` posting that also lists a remote location has `remote` `true` |
| `employmentType` | Full-time, part-time, contract, etc., as the platform words it (Personio publishes two taxonomies joined: `permanent, full-time`). Empty on Greenhouse and Eightfold, which do not publish it; on Rippling and Taleo it comes from the posting detail, so only with descriptions on |
| `postedAt` | Posting timestamp, ISO 8601. Empty on Pinpoint (no date published), on Rippling and BambooHR without descriptions (the date sits on the detail), and on Taleo tenants whose list has no date column (Temple; filled from the job page with descriptions on) |
| `salaryMin` | Minimum of a **structured** pay range the platform publishes as numbers: Lever, Recruitee and Pinpoint in the list; Rippling and Breezy HR from the posting detail (descriptions on). As published per year or per hour - there is no frequency column, so an hourly band shows hourly numbers. Free-text pay (BambooHR's `$70,000 - $100,000 per year`, Breezy's list text) is never turned into numbers |
| `salaryMax` | Maximum of that range |
| `salaryCurrency` | ISO currency code of that range (`USD`, `SAR`, ...) |
| `url` | Direct link to the live posting |
| `jobId` | The platform's own stable posting id, as a string: a UUID on Lever, Ashby and Rippling, a 12-character hex code on Breezy HR, a shortcode on Workable, a number on Greenhouse, Recruitee, Pinpoint, BambooHR, Personio, Eightfold and Taleo (the Pinpoint posting UUID is in `url`) |
| `description` | Full job description as clean text, capped at 5,000 characters (only when **Include job descriptions** is on). On BambooHR the employer's free-text pay line is appended as a last line `Compensation (as published): ...` when there is one |
| `scrapedAt` | When this row was read |

Not every company publishes every field - `department`, `team`, salary and `employmentType` depend on what the source ATS exposes and on what the employer filled in. Nothing is guessed: a field the platform does not publish stays empty.

#### Coverage by platform

Measured on 2026-09-25 with the adapter test runner on the boards named under "Companies to try" (rows are what the Actor returns). "list" means the field comes with the one board request; "detail" means it is filled only when **Include job descriptions** is on, at one extra request per posting.

| Platform | Slug is | Board fetched as | `description` | `postedAt` | `remote` / `workplaceType` | Structured salary | `department` / `team` / `employmentType` |
|---|---|---|---|---|---|---|---|
| Greenhouse | `boards.greenhouse.io/<slug>` | one request | list | list | from location text / never | never | list / office / never |
| Lever | `jobs.lever.co/<slug>` | one request | list | list | platform field | list | list / list / list |
| Ashby | `jobs.ashbyhq.com/<slug>` | one request | list | list | platform field | never (not mapped here) | list / list / list |
| Recruitee | `<slug>.recruitee.com` | one request | list | list | platform flags | list | list / never / list |
| Workable | `apply.workable.com/<slug>` | one request | list | list | remote flag only | never | list / never / list |
| Rippling | `ats.rippling.com/<slug>/jobs` | one request (one item per job x location, merged by uuid) | detail (~0.3 s each) | detail | typed location labels: 0-100% of rows per board (17% on Rippling's own board, 100% on chess), never guessed from a bare city | detail: pay tiers on 47% of Rippling's own 332 postings, 0% on some boards | list / detail / detail |
| Breezy HR | `<slug>.breezy.hr` | one request | detail (~0.6 s each) | list | per-location flag: 0-10% of rows on the sample boards (employers rarely set it) | detail, from the page's JobPosting block (rare: 1 of 31 on plat4mation, 3 of 3 sampled on kimmel-associates) | employer-dependent (0-100%) / never / list |
| Pinpoint | `<slug>.pinpointhq.com` | one request (whole board, no paging; 930 rows in 3 s) | list (no extra requests) | never published | platform field on 100% of rows | list: 82% of the 139 rows on the pay-transparency task; 0% on boards that hide pay | list / never / list |
| BambooHR | `<slug>.bamboohr.com/careers` | one request | detail (~0.4 s each) | detail | platform field (locationType) on 100% of rows | never (free text only, kept in the description) | list / never / list |
| Personio | `<slug>.jobs.personio.de` | one request | list where the company publishes sections there, else detail | list | from office text only: `true` or empty, never `false` | never published | list / never / list (`permanent, full-time`) |
| Eightfold | `<tenant>.eightfold.ai` | careers page + 10 postings per request (paced) | detail on most tenants | list | platform field on 100% of rows | never published | list (0% on amdocs) / apply-family boards only / never |
| Oracle Taleo | `<tenant>.taleo.net` | career section discovery + 25 per request | detail (75-270 KB page each) | list where the tenant shows a date column; detail otherwise | from location text only (empty on all 3,000 sample rows) | not seen on any tenant | never / never / detail |

### Input / How to query

Two ways to target companies, and you can mix them in one run:

- **Auto-detect (recommended):** put company slugs in **Companies** (e.g. `stripe`, `spotify`, `ramp`). The Actor tries the twelve platforms in a fixed order - Greenhouse, Lever, Ashby, Recruitee, Workable, then Rippling, Breezy HR, Pinpoint, BambooHR, Personio, Eightfold, Oracle Taleo - stops at the first one that has the company and reports it in `ats`. A company on one of the later platforms costs a few seconds of misses before its hit (about 0.5 s per platform). A full board or posting URL on any of the twelve platforms also works here: the platform is read off the URL and detection is skipped.
- **Direct per-platform lists:** if you already know the platform, paste identifiers (or board/posting URLs) into the matching field to skip detection: **Greenhouse board tokens**, **Lever companies**, **Ashby organizations**, **Recruitee companies**, **Workable accounts**, **Rippling boards**, **Breezy HR boards**, **Pinpoint boards**, **BambooHR boards**, **Personio career pages**, **Eightfold boards**, **Oracle Taleo career sections**. Clear the **Companies** field when you use these (the console pre-fills it with `stripe`, `spotify`, `ramp` as a sample): only what you list is scraped. A run that names no company at all - `{}` over the API - scrapes those three sample companies and says so in the log.

How to read a slug off a careers URL:

| Platform | Example URL | Slug |
|---|---|---|
| Greenhouse | `https://boards.greenhouse.io/stripe` or `https://job-boards.greenhouse.io/gitlab` | `stripe`, `gitlab` |
| Lever | `https://jobs.lever.co/spotify` | `spotify` |
| Ashby | `https://jobs.ashbyhq.com/ramp` | `ramp` |
| Recruitee | `https://bunq.recruitee.com/` | `bunq` |
| Workable | `https://apply.workable.com/blueground/` | `blueground` |
| Rippling | `https://ats.rippling.com/chess/jobs` | `chess` - slugs are free-form (`foundant-careers`, `daversa-partners-jobs-external`), so copy them rather than guessing |
| Breezy HR | `https://embraer.breezy.hr/` | `embraer` |
| Pinpoint | `https://nypl.pinpointhq.com/en/postings/...` | `nypl` - careers sites on a custom domain cannot be detected; pass the pinpointhq.com slug |
| BambooHR | `https://401auto.bamboohr.com/careers` | `401auto` - most BambooHR customers embed the board on their own website, so take the subdomain from a posting's Apply or "Link to This Job" URL |
| Personio | `https://ottonova.jobs.personio.de/` (or `.jobs.personio.com`) | `ottonova` |
| Eightfold | `https://amdocs.eightfold.ai/careers` | `amdocs` - companies that front the site with their own domain (careers.micron.com) still have an eightfold.ai tenant; look for `<tenant>.eightfold.ai` in that page's links |
| Oracle Taleo | `https://temple.taleo.net/careersection/tu_ex_staff/jobsearch.ftl` | `temple` - the default career section is discovered automatically; for a non-default one add its code (`temple/tu_ex_staff`) or paste the whole URL |

Filters and options:

- **Title contains** - keep only jobs whose title matches text like `engineer` or `sales` (case-insensitive)
- **Location contains** - keep only jobs whose location matches text like `remote` or `new york` (case-insensitive)
- **Remote only** - keep only jobs whose `remote` flag is `true` (see the table above); hybrid and on-site roles with no remote location are dropped, and so are postings with no remote flag (on Greenhouse, Personio and Taleo the flag comes from the location text alone)
- **Include job descriptions** - attach the full description as clean text. Free on Greenhouse, Lever, Ashby, Recruitee, Workable and Pinpoint (it comes with the list); one extra request per posting on Rippling, Breezy HR, BambooHR, Eightfold, Taleo and description-less Personio boards, where it is also what fills posted date, employment type or pay range on the platforms that keep them on the detail
- **Max results** - hard cap on the postings written across the whole run; when it cuts the run short the log names the companies left unprocessed and `SUMMARY.maxResultsReached` is `true`
- **Max run seconds** - wall-clock budget for the run (default 240). When it is reached the Actor stops cleanly and finishes successfully with the postings it already has, and records `stoppedEarlyOnTimeLimit: true` in the run's `SUMMARY` - also when a large Eightfold or Taleo board had to be cut mid-list (the rows written are complete, the board is not). Raise it, together with the run timeout, for a long list of companies or for a large Eightfold or Taleo board

The run's `SUMMARY` record (key-value store) lists postings written, companies given / found / failed, how many requests and platform checks failed, and whether the time budget or the results cap ended the run early.

### Example use cases

1. **Sales intent list:** run 200 target-account slugs on auto-detect, filter `titleContains = "sales"`, and hand your SDRs a list of companies actively hiring reps - a hiring signal that they are scaling.
2. **Engineering sourcing pool:** pull every open role across your target companies with `titleContains = "engineer"` and `Remote only`, then export to CSV for your ATS or sourcing tool.
3. **Aggregator ingestion:** feed a list of employers and get normalized postings from twelve platforms in one schema instead of maintaining twelve scrapers.
4. **Pay-transparency research:** collect postings with published pay bands (`salaryMin`, `salaryMax`, `salaryCurrency`) from Pinpoint, Lever and Recruitee boards - or from Rippling and Breezy HR with descriptions on - to benchmark pay by role and location.
5. **Competitor watch:** track a rival's careers page over time to see which teams and locations they are staffing up.
6. **Public-sector and enterprise hiring:** read university, state-government and enterprise boards on Oracle Taleo and Eightfold that no single-platform startup-ATS scraper reaches.

### Recurring use & scheduling

Use Apify **Schedules** to run this on a cron (for example daily or weekly) against a fixed company list so you always have fresh openings.

Each run writes the postings it retrieves from the requested boards within the selected filters, result cap, time budget and spending limit. Compare runs with the same company list and filters, using `ats` + `company` + `jobId` (or the posting `url`) to identify records. A newly observed ID is new to that comparison, not necessarily newly published. An ID missing from a later dataset is **not observed in that run**, not proof that the job closed or was filled. Check `SUMMARY` and logs for failed checks, skipped inputs and limit stops before investigating a difference, then verify the employer's posting. These observation differences can be passed to your sheet, database or webhook workflow.

### How it compares

Every claim below was read from the named Actor's Store page or its public Actor record on 2026-09-25; users are the Store's own "monthly active users" figure that day.

**Two kinds of tool sell under "ATS jobs" on the Store.** The most-used ones are *indexed databases*: [fantastic-jobs/career-site-job-listing-api](https://apify.com/fantastic-jobs/career-site-job-listing-api) (about 1,500 monthly users - the Store shows 1.5K) answers "wait, this isn't a scraper?" in its own FAQ with "you're accessing our database with scraped jobs with a small delay" - a one-hour delay, new jobs "within 3 hours of posting", expiry checked once a day, and $0.012 per job on the free plan. [jobo.world/ats-jobs-api](https://apify.com/jobo.world/ats-jobs-api) (155) searches its index of "3.9 million+ live jobs", re-verified daily, and returns one page of up to 100 results per run at $0.004 per job on the free plan. Both are excellent when you want a keyword search across every employer they crawl. Neither fetches a company you name from its board at run time.

**This Actor is the other kind: a live, per-company fetch.** You give it company slugs; it detects the ATS and reads the board's own public endpoint while the run is happening. The nearest neighbour with the same model is [memo23/career-site-ats-jobs-api](https://apify.com/memo23/career-site-ats-jobs-api) (71 monthly users, 116 platforms claimed), priced at $0.004 per job on the free plan plus a $0.03 start fee on every run, with Taleo and most enterprise boards accepted "URL only". [webdata_labs/greenhouse-lever-ashby-jobs-scraper](https://apify.com/webdata_labs/greenhouse-lever-ashby-jobs-scraper) (19) is priced per posting like this Actor, covers seven platforms, and lists Workable, BambooHR, Taleo, Breezy HR, Pinpoint and Rippling among the systems it does not cover.

**What you get here**

- **12 platforms, one input.** Greenhouse, Lever, Ashby, Recruitee, Workable, Rippling, Pinpoint, Breezy HR, BambooHR, Personio, Eightfold, Oracle Taleo - detected automatically from a bare slug, or targeted directly per platform. Taleo tenants are resolved from the tenant name alone (the default career section is discovered for you); Eightfold tenants from the subdomain.
- **Read from the source during each run.** The Actor queries public career-board endpoints rather than its own stored job index. Results reflect the source responses it receives, within the selected filters and run limits. They do not guarantee that every newly published role is included or that an absent role has closed.
- **No API key, no login, no browser.** Only public keyless endpoints, only where robots.txt allows them (SmartRecruiters is excluded for that reason and says so in the FAQ).
- **One schema with honest nulls.** `remote` is true only when the board says fully remote or lists a remote location; `salaryMin/Max/Currency` are numbers only when the board publishes a structured range (Lever, Recruitee and Pinpoint lists, Rippling and Breezy HR detail pages do; BambooHR publishes a free-text pay line that is not turned into numbers). Fields a platform never publishes stay empty rather than being guessed.
- **Pay per posting returned - no subscription, no minimum.** The current per-posting rate is on this Actor's Pricing tab (plus Apify's standard Actor-start charge on each run). Filters (title, location, remote) run before rows are written, so a filtered run costs what it returns.
- **No personal data.** Job postings only; no candidate, applicant or contact-person fields (Pinpoint's "reporting to" name is dropped on purpose).

**What it does not do**

- No keyword search across employers you have not named - bring your own company list (fantastic-jobs and jobo.world are the right tools for "every remote data engineer job this week").
- No AI enrichment, no LinkedIn or Crunchbase company data, no geocoding.
- No Workday, iCIMS, SuccessFactors or SmartRecruiters. Large Eightfold and Taleo boards page 10 and 25 postings per request, so a 5,000-posting board is a multi-minute run - raise **Max run seconds** for those.

### FAQ

### Which ATS platforms does this job scraper support, and which does it not?

Twelve: Greenhouse, Lever, Ashby, Recruitee, Workable, Rippling (ats.rippling.com), Pinpoint (pinpointhq.com), Breezy HR (breezy.hr), BambooHR (bamboohr.com/careers), Personio (jobs.personio.de and .com), Eightfold (eightfold.ai) and Oracle Taleo (taleo.net career sections). In auto-detect mode a slug is tried on all twelve, cheapest first, and the match is reported in the `ats` column. Not supported: SmartRecruiters (its API robots.txt disallows crawlers), Workday, iCIMS, SuccessFactors, and careers pages that only embed a board on the company's own domain without a public tenant host. A company found on none of the twelve is reported as not found, never as an empty success - and a company whose check on one platform failed (a rate limit, an outage) is reported as "could not be checked there", not as "not found".

### How do I find a company's Rippling, Pinpoint, Breezy, BambooHR, Personio, Eightfold or Taleo slug?

Open any posting on the careers site and read the host or path: ats.rippling.com/**chess**/jobs, **nypl**.pinpointhq.com, **embraer**.breezy.hr, **401auto**.bamboohr.com/careers, **ottonova**.jobs.personio.de, **amdocs**.eightfold.ai/careers, **temple**.taleo.net/careersection/tu_ex_staff/jobsearch.ftl. The bold part is the slug; pasting the whole URL into the per-platform field (or into Companies) also works. Rippling slugs are free-form ("foundant-careers", "daversa-partners-jobs-external"), so copy them rather than guessing. Most BambooHR customers embed the board on their own website, so take the subdomain from a posting's Apply link. For Taleo the tenant alone ("hdr") is enough - the default career section is discovered automatically; add the section code only for a non-default one ("temple/tu_ex_staff").

### How do I scrape job postings from Greenhouse, Lever, and Ashby in one run?

Put the company slugs in the **Companies** field and run. The Actor auto-detects each company's ATS across all twelve supported platforms - including Greenhouse, Lever, and Ashby - and returns every posting in one normalized schema. No need to run separate scrapers or know which platform each company uses.

### How do I get job postings from a company's careers page without an API key?

Enter the company slug (usually the lowercase name from its careers URL, e.g. `stripe`). The Actor queries the public ATS job-board endpoints that power the careers page directly - **no API key, login, or token setup** required from you.

### How can I find which ATS a company uses automatically?

That is the default behavior. In auto-detect mode the Actor probes the twelve platforms for each company slug and reports the match in the `ats` field on every record, so you learn the platform and get the jobs in the same run.

### Why does a big Eightfold or Taleo board take minutes, and how do I keep the run short?

Eightfold serves a fixed 10 postings per request and Taleo 25, and neither offers a bigger page, so Ericsson (586 postings) is 59 list requests and under a minute, while Micron (2,958) or Lockheed Martin (5,168) are several minutes - Eightfold also enforces a per-IP rate rule of roughly 420 requests per five minutes, which the Actor paces itself under (100 requests at full speed, then 0.8 per second), so Morgan Stanley (1,323) takes about a minute and a half, Micron about 4.5 minutes and Lockheed Martin about 9.5. On Taleo, HDR's 2,301 requisitions are 93 list pages and about 45 seconds. The other ten platforms return a whole board in one request. For the large boards raise **Max run seconds** (and the run timeout in Run options) or run them one tenant per run; the wall-clock guard stops cleanly with what it has (newest postings first on Eightfold) and records `stoppedEarlyOnTimeLimit: true` in the run's SUMMARY. Job descriptions add one request per posting on Rippling, Breezy, BambooHR, Eightfold and Taleo (Pinpoint and most Personio boards carry them in the list), so leave **Include job descriptions** off for a quick count.

### Why not SmartRecruiters?

SmartRecruiters was removed on 2026-09-25. Its public postings API at `api.smartrecruiters.com` publishes a robots.txt that disallows every crawler except LinkedInBot (`User-agent: *` / `Disallow: /`), so this Actor does not read it. A company whose only careers board is SmartRecruiters is reported as not found on any supported platform.

### How do I export job postings to CSV or Google Sheets?

Every run stores results in an Apify dataset. From the run's **Storage** tab, export to CSV, JSON, Excel, or XML in one click, or push straight to Google Sheets via Apify's integration. The API and integrations let you automate the export on a schedule.

### How do I use job postings as hiring signals for sales prospecting?

Companies posting roles in a function (sales, engineering, ops) are signaling investment and growth. Run your target-account slugs, filter with **Title contains**, and use the resulting list of actively-hiring companies as buying-intent signals for outreach.

### How do I compare observed jobs between runs?

Schedule recurring runs with the same company list and filters, then compare records using `ats` + `company` + `jobId` (or the posting `url`). Added records are newly observed in that comparison; missing records were not observed in the later run. The Actor does not confirm newly closed or filled jobs. Inspect `SUMMARY` and logs for failed checks, skipped inputs and result, time or spending stops, and verify the employer's posting before assigning a closure status. Keep the comparison in your sheet, database or webhook handler.

### Is it legal to scrape public job boards like Greenhouse and Lever?

The Actor reads only **public** job-board data - the same postings any visitor sees on a company's careers page - via the platforms' own public endpoints, honours each platform's robots.txt, and collects no personal candidate data. Public job data is generally low-risk to collect, but you are responsible for your own compliance, each platform's terms, and applicable laws in your use case.

### How do I get salary data from job postings?

When a platform publishes a pay range as numbers, it is captured in `salaryMin`, `salaryMax` and `salaryCurrency`: Lever, Recruitee and Pinpoint publish it with the list; Rippling and Breezy HR publish it on the posting detail, so turn on **Include job descriptions** there. Coverage depends on the employer - many roles omit pay, and those fields stay empty rather than being estimated. Greenhouse, Workable, Personio and Eightfold publish no structured pay this Actor can read; no Taleo tenant seen so far publishes a structured range (the adapter would read a schema.org `baseSalary` from the job page if one did); BambooHR publishes only a free-text line (kept verbatim in the description); and Ashby compensation is not mapped by this Actor. Numbers are as published per year or per hour; there is no frequency column.

### What happens when a company is not found, or a platform is down?

A slug that exists on none of the twelve platforms is logged as not found (naming the platforms tried) and the run still succeeds - with 0 rows if that was the only company, which the log calls an honestly empty result. A platform that fails (network error, HTTP 5xx, or a rate limit such as an HTTP 429 with a long Retry-After) is a *failed check* for that company, not a "not found": the error is logged, the other platforms are still tried, and `SUMMARY.checksFailed` counts it. If nothing at all was found and at least one check failed, the run fails with a message saying so instead of returning an empty dataset that looks like "no jobs".

### Companies to try

Verified live on 2026-09-25 through the adapter test runner and local Actor runs (rows as returned by this Actor; counts change daily). Use the slug exactly as written.

- **Rippling** (ats.rippling.com/<slug>/jobs): chess (Chess.com, 13 postings), pythian (23), foundant-careers (Foundant Technologies, 16), button (11), careers-at-harver (Harver, 5), daversa-partners-jobs-external (Daversa Partners, 8), serviceupcareers (ServiceUp, 4), rippling (Rippling's own board, 332). The list API repeats a posting once per work location; rows are deduplicated by uuid.
- **Pinpoint** (<slug>.pinpointhq.com): nypl (New York Public Library, 29 rows, pay band on every row), weoneil (W.E. O'Neil Construction, 68, pay on 47), groupo (Group O, 20, pay on 20), princesscruises (Princess Cruises, 314, pay on a handful), trilongroup (Trilon Group, 930, pay on about 750 - a 6.8 MB single response), wolfe (Wolfe LLC, 10), ascensusspecialties (7), nodalexchange (Nodal Exchange, 5), safetywing (3, fully remote), digitalscience (Digital Science, 3), ports (Ports of Jersey, 1). Pinpoint publishes no posted date.
- **Breezy HR** (<slug>.breezy.hr): embraer (Embraer, 66), kimmel-associates (Kimmel & Associates, 447 - department and pay text on every row), plat4mation (31), careers-hankooktire (Hankook Tire, 22), contender-labs (1, fully remote). zeelo is a valid empty board. Never use breezy.breezy.hr (Breezy's demo board).
- **BambooHR** (<slug>.bamboohr.com/careers): 401auto (401 Auto dealer group, 120), canopy (3, Kingston), atomic (2, Ireland contractors). Hosted pages with nothing open that day: soundstripe, lendio, sparkhire (valid empty boards).
- **Personio** (<slug>.jobs.personio.de): ottonova (8, full descriptions in the feed), dfb (Deutscher Fussball-Bund, 6), everphone (5), apheris (11, descriptions come from the posting page), personio (Personio's own board, 1). Boards with a valid but empty feed that day: homeday, tado.
- **Eightfold** (<tenant>.eightfold.ai/careers): amdocs (20, about 3 s), app (Eightfold's own board, 60), symetra (60), vale (214-218), ericsson (586, about 50 s), bayer (627), slb (643), morganstanley (1,323), micron (2,958), lockheedmartin (5,168). Ten postings per request: raise Max run seconds well above the default for the four largest.
- **Oracle Taleo** (<tenant>.taleo.net): temple (Temple University, 91 rows, no posting date on that tenant's list), massanf (Commonwealth of Massachusetts, 608 rows in about 12 s, posting date on every row), hdr (HDR Inc, 2,301 - 93 pages, about 45 s). Legacy joblist.ftl-only sections (chicago) are not supported.

### Data source & notes

- **Source:** the public job-board endpoints of twelve ATS platforms - the same endpoints that render each company's public careers page: Greenhouse, Lever, Ashby, Recruitee and Workable (JSON board APIs), Rippling (board API), Breezy HR (positions feed + posting page), Pinpoint (postings.json), BambooHR (hosted careers page internals), Personio (public XML feed + posting page), Eightfold (careers page + its two jobs APIs), Oracle Taleo (career-section job-board service + job page).
- **No API key** or authentication is required. **robots.txt** is read and honoured per platform: SmartRecruiters is excluded because its rules forbid it; Pinpoint tenants can hide individual postings in their robots.txt and those are dropped; Eightfold's allow-list covers exactly the paths used.
- **Pacing:** one or two requests per board on ten platforms (Pinpoint also reads the tenant's robots.txt; a Personio miss tries `.de` then `.com`); consecutive Lever requests at least 1 s apart (api.lever.co publishes `Crawl-delay: 1`); detail requests 150 ms apart; Eightfold paced under its per-IP rule; Taleo pages 150 ms apart.
- **Coverage caveats:** `department`, `team`, `employmentType` and salary fields appear only when the source ATS exposes them (see the coverage table). Job descriptions are optional (enable **Include job descriptions**). Only public posting data is collected - no candidate, applicant or contact-person information.

---

Actor: `maydit/ats-job-postings-scraper` (ID `zkwXPahBHDRl7gxHu`)

### Related actors

Other maydit data tools that pair well with hiring signals:

- [New Business Leads Scraper](https://apify.com/maydit/us-business-licenses-scraper) - newly registered companies - early-stage hiring signals
- [Federal Contract Awards Scraper](https://apify.com/maydit/us-federal-contract-awards-scraper) - contract wins often precede hiring pushes

See the full list at [apify.com/maydit](https://apify.com/maydit).

### Found this useful?

If this actor saved you time, a short review on the Apify Store genuinely helps. Reviews are how the next person decides whether a tool is worth trying.

Something broken, missing a field, or a source you want covered? Open an issue on the **Issues** tab and it will get looked at - that is the fastest route to getting it changed.


#### Saved rows and run charge limits

The Actor writes results one at a time and stops when Apify reports the run charge limit. `SUMMARY.stoppedOnChargeLimit` distinguishes that stop from an empty source. Saved-row counts include only rows accepted by the dataset. For change detection, prior seen IDs are retained and newly discovered IDs enter the baseline only after their row is saved; rows excluded by a result or charge cap remain eligible for a later run. Avoid concurrent monitor runs sharing the same named baseline store.

## Help with your run

Open the **Issues** tab on this Actor with the run URL, the input field that caused trouble and what you expected to receive. Remove API keys and private information before posting.

[Explore more Mayd-It Actors](https://apify.com/maydit)

## Understand your run

Open **Run report** in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use **CSV export** to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.

The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.
