# Greenhouse, Lever, Ashby & Workday Jobs Scraper - Any Company (`kadi_bence/ats-jobs-scraper`) Actor

Get open jobs of any company by name: Stripe, Ramp (Greenhouse, Lever, Ashby, Workable, Recruitee, Personio) and NVIDIA, Salesforce (Workday) in one run, board auto-detected. Filters: title, location, remote. Returns per job: title, team, location, salary, date, URL. Default: 20/company. $1.25/1K.

- **URL**: https://apify.com/kadi_bence/ats-jobs-scraper.md
- **Developed by:** [Bence Kadi](https://apify.com/kadi_bence) (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

from $1.25 / 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.

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

## Greenhouse, Lever & Ashby Jobs Scraper: ATS jobs API for Workable, Recruitee and Personio too

### What is Greenhouse, Lever & Ashby Jobs Scraper?

Greenhouse, Lever & Ashby Jobs Scraper collects open jobs from company job boards on six applicant tracking systems (ATS): Greenhouse, Lever, Ashby, Workable, Recruitee and Personio. You type company names such as `Stripe`, `ramp.com` or `Hugging Face`, and get all their open jobs as JSON, CSV or Excel, in one schema with title, locations, work mode, department, posted date, salary and description.

It reads the public job-board endpoints that these ATS vendors provide so companies can show openings on their own websites. No login, API key or browser.

**What makes it different**

- **Auto-detects the ATS.** Type a name or domain; all 6 platforms are checked, including Lever EU and Personio `.de`/`.com`. Board URLs work too.
- **Big employers on Workday too.** If a company has no board on these 6 (NVIDIA, Salesforce, Intel, Adobe), its Workday career site is used instead, with the same output fields (`ats: "workday"`). `Stripe` and `NVIDIA` in one run give one dataset. Workday URLs (`*.myworkdayjobs.com`) work as input as well.
- **Newest jobs first,** so a small `maxJobsPerCompany` gives recent openings instead of the A-Z top of the board.
- **One schema for 6 platforms.** Merge companies in a spreadsheet or database without mapping work.
- **No hidden result cap.** `maxJobsPerCompany: 0` returns every open job (Stripe alone has 700+).
- **Salary included.** Structured pay ranges from Ashby, Lever and Recruitee, plus ranges like "$120,000 – $150,000" parsed from descriptions elsewhere.
- **Filters.** Posted within N days, title words, location and remote only.
- **Only new jobs.** Monitoring mode outputs, and charges for, only postings you haven't seen before.
- **Fast.** One request per company board. The 3-company prefill finishes in about 15 seconds.

#### Use cases

- **Sales and lead generation (hiring signals):** find companies hiring for roles that suggest they need your product, like "Head of RevOps" or "Data Engineer".
- **Recruiting agencies:** monitor target accounts and react to new openings the same day.
- **Job boards and newsletters:** aggregate startup and tech jobs from hundreds of career pages.
- **Investors and market research:** track team build-outs across a portfolio.
- **AI agents and RAG apps:** give an LLM fresh, structured job data through the API or the Apify MCP server.

#### Data fields you get

| Field | Description | Example |
|---|---|---|
| `title` | Job title | `Security Engineer, Cloud` |
| `company` | What you typed in the input | `Ramp` |
| `companyName` | Company name the ATS publishes (Greenhouse, Workable, Recruitee, Personio; else empty) | `Stripe` |
| `ats` | `greenhouse`, `lever`, `ashby`, `workable`, `recruitee` or `personio` | `ashby` |
| `jobId` | Job ID on the ATS | `34413f8d-26bf-4bbc-8ade-eb309a0e2245` |
| `url` | Link to the live job page | `https://jobs.ashbyhq.com/ramp/34413f8d-...` |
| `applyUrl` | Link to the application form | `https://jobs.ashbyhq.com/ramp/.../application` |
| `location` | Primary location | `New York, NY (HQ)` |
| `locations` | All locations of the posting | `["New York, NY (HQ)", "Remote (US)"]` |
| `country` | Country, when the ATS gives it | `USA` |
| `countryCode` | Country code, when the ATS gives it (Lever, Workable, Recruitee) | `GB` |
| `workMode` | `remote`, `hybrid`, `onsite` or empty when unknown | `hybrid` |
| `employmentType` | As published by the company | `FullTime` |
| `department` | Department | `Engineering` |
| `team` | Team (or function / category) | `Backend` |
| `seniority` | Seniority (Personio only) | `experienced` |
| `postedDate` | When the job was published (ISO, UTC) | `2026-04-07T17:12:35Z` |
| `updatedDate` | Last update (Greenhouse only) | `2026-09-25T20:45:00Z` |
| `salaryMin` / `salaryMax` | Pay range (numbers) | `211400` / `290600` |
| `salaryCurrency` | Currency code | `USD` |
| `salaryPeriod` | `YEAR`, `MONTH` or `HOUR` | `YEAR` |
| `salaryText` | Original pay text, when available | `$211.4K - $290.6K` |
| `description` | Job description as plain text | `About Ramp\nRamp is building...` |
| `descriptionHtml` | Description as HTML (if you choose HTML or both) | `<p>About Ramp</p>...` |
| `boardUrl` | Job board the job came from | `https://jobs.ashbyhq.com/ramp` |
| `isNew` | Set in monitoring mode for jobs not seen before | `true` |
| `scrapedAt` | When the job was scraped (UTC) | `2026-10-04T23:58:10Z` |

### How to use Greenhouse, Lever & Ashby Jobs Scraper

1. Open the Actor and type one or more **company names, websites or job-board URLs** in the first field, one per line. The prefill is Stripe, Ramp and Hugging Face with 20 jobs each. It saves about 48 jobs, takes about 15 seconds and costs about $0.06.
2. Optional: add **title words** to include or exclude, **locations**, **remote only** or **posted within N days**. Set **Max jobs per company** to `0` to get everything.
3. Click **Start**.
4. When the run finishes, open the **Output** tab and download the data as JSON, CSV, Excel or HTML, or connect it to Google Sheets, Zapier, Make, n8n or your own code.
5. To get only new jobs every day, turn on **Only new jobs** and create a **Schedule** (see [Integrations and scheduling](#integrations-and-scheduling)).

#### Input guide

**Company names, websites or job-board URLs (`companies`)**

Type the company's name or domain, one per line. The Actor turns it into likely board slugs (`Hugging Face` becomes `huggingface` and `hugging-face`) and checks each selected ATS. If a company has boards on several ATSs, each one is scraped. The `RUN_SUMMARY` record shows which ATS and board were found for each company.

- Good: `Stripe`, `ramp.com`, `Hugging Face`, `https://jobs.lever.co/spotify`, `https://bunq.recruitee.com`
- Good board URLs: `job-boards.greenhouse.io/<slug>`, `jobs.lever.co/<slug>` (or `jobs.eu.lever.co`), `jobs.ashbyhq.com/<slug>`, `apply.workable.com/<slug>`, `<slug>.recruitee.com`, `<slug>.jobs.personio.de` (or `.com`)
- Bad: `Stripe jobs in London` (put places in **Locations**), the company's own careers page such as `https://stripe.com/jobs` (paste the ATS board URL), a Workable short link `apply.workable.com/j/...` (it doesn't contain the account)
- Warning: detection uses the board's public slug. When the board publishes a company name (Greenhouse, Workable, Recruitee) that clearly differs from the name you typed, or it is a sandbox/demo account, the board is skipped and listed under `rejectedBoards` in `RUN_SUMMARY`. For generic names, still check `companyName` and `boardUrl`, or paste the exact board URL.
- Warning: companies on Workday, SAP SuccessFactors, iCIMS or an in-house site are not found here. Try our [Workday Jobs Scraper](https://apify.com/kadi_bence/workday-jobs-scraper) or [ATS+ Jobs Scraper](https://apify.com/kadi_bence/ats-plus-jobs-scraper).

**Platforms to check (`atsPlatforms`)**

All 6 by default. If you know your companies use only Greenhouse and Lever, select just those; detection is faster.

**Title filters (`titleIncludes`, `titleExcludes`, `titleKeywords`)**

`titleIncludes` keeps a job if its title contains ANY of the words; `titleExcludes` drops it if the title contains ANY of them. It is a simple, case-insensitive "contains" check. `titleKeywords` is the older comma-separated version of `titleIncludes`; both are combined.

- Good: include `engineer`, `data scientist`; exclude `internship`, `senior`
- Warning: `intern` also matches "International". Use `internship` when that matters.

**Locations (`locations`), Remote jobs only (`remoteOnly`), Posted within (days) (`postedWithinDays`)**

- `locations` keeps jobs whose location text contains ANY of the words as a whole word or phrase, e.g. `London`, `Germany`, `US`, `Remote` (case-insensitive; `US` matches "Remote - US" but not "Austin"). All locations of the posting, plus country and country code, are checked.
- `remoteOnly` keeps jobs whose `workMode` is `remote`. Hybrid jobs are not included.
- `postedWithinDays` keeps jobs posted in the last N days, e.g. `7`. Use `1` for about the last day.

**Max jobs per company (`maxJobsPerCompany`)**

A limit per company, not per run. `0` means no limit. The Console prefill is 20 for a quick test; the default via API, MCP or an AI agent is 20; set `0` for all jobs.

Jobs removed by any filter are not saved, don't count toward the limit and are **not charged**.

**Output and advanced options**

- `descriptionFormat`: `text` (default), `html`, `both` or `none`.
- `stripContactInfo` (default on): removes e-mails and phone numbers from descriptions, so you don't store personal data.
- `proxyConfiguration`: off by default. These are public APIs; enable a proxy only if you see blocking errors in the log.
- `onlyNewJobs` and `monitorName`: see [Monitoring mode](#monitoring-mode-only-new-jobs).

Example input:

```json
{
  "companies": ["Stripe", "Ramp", "Hugging Face", "https://jobs.lever.co/spotify", "personio.com"],
  "titleIncludes": ["engineer", "data"],
  "titleExcludes": ["internship", "senior"],
  "locations": ["London", "Remote"],
  "postedWithinDays": 30,
  "maxJobsPerCompany": 0,
  "onlyNewJobs": false
}
```

### Output

Each job is one item in the run's dataset. Here is one real Ashby item from the prefill run on 2026-10-05 (description shortened). Greenhouse, Lever, Workable, Recruitee and Personio jobs have exactly the same fields.

```json
{
  "title": "Security Engineer, Cloud",
  "company": "Ramp",
  "companyName": null,
  "ats": "ashby",
  "jobId": "34413f8d-26bf-4bbc-8ade-eb309a0e2245",
  "url": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245",
  "applyUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application",
  "location": "New York, NY (HQ)",
  "locations": ["New York, NY (HQ)", "Remote (Canada)", "Remote (US)", "Miami, FL"],
  "country": "USA",
  "countryCode": null,
  "workMode": "hybrid",
  "employmentType": "FullTime",
  "department": "Engineering",
  "team": "Backend",
  "seniority": null,
  "postedDate": "2026-04-07T17:12:35Z",
  "updatedDate": null,
  "salaryMin": 211400,
  "salaryMax": 290600,
  "salaryCurrency": "USD",
  "salaryPeriod": "YEAR",
  "salaryText": "$211.4K - $290.6K",
  "description": "About Ramp\nRamp is building the smart infrastructure for finance teams, embedded in the transaction flow of every dollar a business spends. We…",
  "descriptionHtml": null,
  "boardUrl": "https://jobs.ashbyhq.com/ramp",
  "scrapedAt": "2026-10-04T23:58:10Z"
}
```

Notes:

- Not every ATS has every field. For example, Greenhouse has no structured salary, team or employment type, and only Greenhouse has `updatedDate`. Missing values are `null`, so every item has the same columns in CSV and Excel.
- Without a structured salary, the Actor looks for a clear range with a currency in the description. Several ranges in the same currency (per level or location) are merged into one `salaryMin`–`salaryMax` span; the original text stays in `salaryText`.
- `workMode` comes from the ATS's workplace field when it has one, otherwise from "remote" or "hybrid" in the location or title.

#### Dataset views

The **Output** tab has two views of the same data:

| View | What it shows |
|---|---|
| **Jobs** | A compact table: title, company, ATS, location, work mode, posted date, salary range and URL. Best for a quick look. |
| **Full details** | Adds the published company name, department, team, employment type, all locations, country code, salary text, description and apply link. |

Every export contains all fields, whichever view you look at. The run also writes a `RUN_SUMMARY` record to the key-value store: for each company, the ATS and board found, jobs on the board, saved and skipped by filters, the platforms checked, boards skipped because they belong to another company, or a note such as "no job board found".

#### How to export the data

- **In the Console:** Output tab > **Export** > JSON, CSV, Excel, HTML, XML or RSS. You can pick fields and the view.
- **Google Sheets:** add the Google Sheets integration to the Actor or a schedule (Integrations tab), or use `=IMPORTDATA("https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=csv&token=<TOKEN>")`.
- **API:** `https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=json` (also `csv`, `xlsx`, `xml`). Add `&view=overview` for the compact table.

### Pricing

This Actor uses **pay per event**. You pay **$1.25 per 1,000 jobs** ($0.00125 per job saved to the dataset), plus Apify's standard Actor start fee of **$0.00005 per run**. Platform compute is included in the price.

| Example run | Jobs saved | Cost |
|---|---|---|
| Prefill test (Stripe, Ramp, Hugging Face, 20 jobs each) | 48 | about $0.06 |
| 700 jobs (e.g. all open jobs at Stripe) | 700 | about $0.88 |
| 50 companies, 20 jobs each | 1,000 | about $1.25 |
| Daily monitoring, ~50 new jobs per day for 30 days | 1,500 | about $1.88 per month |

What you don't pay for:

- jobs removed by your filters (title, location, remote, posted date),
- jobs already seen in monitoring mode,
- companies where no job board was found,
- postings that failed to parse,
- the `RUN_SUMMARY` record.

To cap spending, set **Max charge per run** in the run options; the Actor stops cleanly at that limit and keeps what it saved.

### Use it via API

Get your API token in the Apify Console under **Settings > API & Integrations**. The examples below run the Actor, wait for it to finish and read the jobs.

**JavaScript / Node.js** (`npm install apify-client`)

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('kadi_bence/ats-jobs-scraper').call({
    companies: ['Stripe', 'ramp.com', 'https://jobs.lever.co/spotify'],
    titleIncludes: ['engineer'],
    locations: ['London', 'Remote'],
    maxJobsPerCompany: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`${items.length} jobs`, items[0]);
```

**Python** (`pip install apify-client`)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("kadi_bence/ats-jobs-scraper").call(run_input={
    "companies": ["Stripe", "ramp.com", "https://jobs.lever.co/spotify"],
    "titleIncludes": ["engineer"],
    "locations": ["London", "Remote"],
    "maxJobsPerCompany": 100,
})

for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["ats"], job["title"], job["location"], job["salaryMin"], job["url"])
```

**cURL** (runs the Actor and returns the jobs in one request; best for runs under 5 minutes)

```bash
curl -X POST "https://api.apify.com/v2/acts/kadi_bence~ats-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["Stripe", "Ramp", "Hugging Face"], "maxJobsPerCompany": 20}'
```

**Apify CLI**

```bash
apify call kadi_bence/ats-jobs-scraper --input '{"companies": ["Stripe", "Ramp", "Hugging Face"], "maxJobsPerCompany": 20}' --output-dataset
```

**MCP server for AI agents** (Claude, Cursor, VS Code and other MCP clients)

Add the Apify MCP server with this Actor as a tool. Your client will ask you to sign in to Apify (OAuth), or you can send your token as an `Authorization: Bearer YOUR_APIFY_TOKEN` header.

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?actors=kadi_bence/ats-jobs-scraper"
    }
  }
}
```

Then ask your agent, for example: "Find all open engineering jobs at Stripe, Ramp and Hugging Face posted in the last 7 days and list the ones with a salary range."

### Integrations and scheduling

- **Schedules:** in the Console go to **Schedules > Create new**, pick this Actor (or a saved task with your input) and a time, e.g. every day at 07:00. Each run gets its own dataset.
- **Webhooks:** on the Actor's **Integrations** tab, add a webhook for "Run succeeded" to send the run and dataset ID to your server.
- **Zapier, Make and n8n:** use the Apify app or node. Trigger "Actor run finished", then "Get dataset items", then send each job to Slack, e-mail, a CRM or Airtable.
- **Google Sheets:** the Google Sheets integration appends each run's jobs to a sheet, which is the easiest job-alert setup.

#### Monitoring mode (only new jobs)

Turn on **Only new jobs** (`onlyNewJobs: true`) and schedule the Actor:

1. The first run outputs all matching jobs and saves their IDs as a baseline.
2. Every later run outputs only jobs that weren't returned before. In monitoring mode, saved jobs have `isNew: true`.
3. You pay only for those new jobs.

The "already seen" list is stored in a named key-value store (`ats-jobs-monitor`) in your own Apify account, one list per **Monitor name** and job board (ATS + slug). Filters are not part of the key, so if you run two schedules on the same companies with different filters (e.g. engineers and sales), give them different **Monitor names**. To start over, use a new monitor name.

Only jobs that were actually output (and charged) are remembered. Jobs cut off by **Max jobs per company** or **Max charge per run** come in a later run, and nothing is charged twice.

### Other job scrapers by the same developer

All of them use the same output fields where possible, so you can merge datasets.

- [Workday Jobs Scraper](https://apify.com/kadi_bence/workday-jobs-scraper): every job from company career sites on Workday (myworkdayjobs.com), by company name, with no 2,000-job cap.
- [Oracle, Taleo, BambooHR & Rippling Jobs Scraper](https://apify.com/kadi_bence/ats-plus-jobs-scraper): nine more applicant tracking systems, including Oracle Recruiting Cloud, Taleo, Teamtailor and Jobvite.
- [Germany Jobs Scraper - Arbeitsagentur](https://apify.com/kadi_bence/arbeitsagentur-jobs-scraper): 1M+ German job offers from the federal employment agency's Jobbörse.
- [Sweden Jobs Scraper - Platsbanken](https://apify.com/kadi_bence/sweden-jobs-scraper): all Swedish job ads from Arbetsförmedlingen, with an archive since 2016.
- [EURES Jobs Scraper](https://apify.com/kadi_bence/eures-jobs-scraper): EU job vacancies from 31 countries via the official European Job Mobility Portal.
- [Remote Jobs Scraper](https://apify.com/kadi_bence/remote-jobs-scraper): remote jobs from RemoteOK, Himalayas, Jobicy and Arbeitnow in one de-duplicated feed.

Related company data for B2B leads: [SEC Form D Scraper](https://apify.com/kadi_bence/sec-form-d-funding) (startup funding rounds), [New Business Filings USA](https://apify.com/kadi_bence/us-new-business-filings) (newly registered companies) and [Website Tech Stack Detector](https://apify.com/kadi_bence/tech-stack-detector) (technologies a company uses).

### FAQ

**How does Greenhouse, Lever & Ashby Jobs Scraper work?**
Each supported ATS has a public job-board endpoint that returns all open jobs of a board in one response. The Actor turns your company name into likely board slugs, checks each selected ATS, and reads every board it finds. It doesn't use a browser, so it's fast and cheap.

**Is there an official Greenhouse, Lever or Ashby jobs API?**
Yes, each vendor has a public job-board API that companies use to show jobs on their own sites. But each has its own format, and you need to know the board slug. This Actor finds the board for you and returns one schema for all six, through the Apify API.

**How many jobs can I get? Is there a limit?**
No hidden cap. With `maxJobsPerCompany: 0` you get every job the board publishes, and you can list hundreds of companies per run.

**How fast is it?**
The 3-company prefill takes about 15 seconds. A few hundred companies take about a minute.

**A company wasn't found, or I get fewer jobs than the careers page shows. Why?**
The company may use another system (Workday, SAP SuccessFactors, iCIMS, an in-house site) or its board has an unusual slug. Open the careers page, click a job, and paste the board URL (e.g. `https://jobs.lever.co/acme`). Fewer jobs usually come from a filter or `maxJobsPerCompany`; `RUN_SUMMARY` shows jobs on the board, saved and skipped per company. For generic names, check `boardUrl` to be sure the right company was matched.

**Why is the salary or another field empty?**
Many companies don't publish pay. Salary is filled when the ATS has a structured range or the description contains a clear range with a currency. Other fields, like `team` or `countryCode`, exist only on some platforms; missing values are `null`.

**Do I need proxies?**
No. These are public APIs. The proxy option exists only for unusual network setups.

**Is it legal to scrape these job boards?**
The Actor uses only the public job-board endpoints that these ATS vendors publish so postings can be displayed and shared. It respects `robots.txt` (including crawl-delay), doesn't log in, and removes e-mails and phone numbers from descriptions by default, so it doesn't collect personal data (GDPR). You are responsible for how you use the data, including the platforms' terms and data-protection law in your country.

**Can I use it from Python or another app, and get only new jobs every day?**
Yes. Use the Apify API, the JavaScript or Python client, the CLI, or the MCP server, as shown in [Use it via API](#use-it-via-api). For daily new jobs, turn on **Only new jobs** and create a schedule; see [Monitoring mode](#monitoring-mode-only-new-jobs).

**The run failed or a field is missing. What should I do?**
Open an issue on the **Issues** tab with the run link or your input. Fixes usually land within 24–48 hours. See the changelog below for recent changes.

### Companies tested by name

These companies were found by typing just their name (tested 2026-10-05):

- **Greenhouse:** Stripe, Figma, Airbnb, Discord, Coinbase, Anthropic, Databricks, Cloudflare, Duolingo, Reddit, Pinterest, Dropbox
- **Ashby:** Ramp, Notion, Plaid, OpenAI, Linear
- **Lever:** Spotify
- **Workable:** Hugging Face

### Related Actors

More low-cost Actors by the same developer, built on official APIs and public data:

- [Workday Jobs Scraper](https://apify.com/kadi_bence/workday-jobs-scraper) — open jobs of any company by name (NVIDIA, Salesforce), plus Greenhouse/Lever fallback
- [ATS Jobs Feed](https://apify.com/kadi_bence/ats-jobs-feed) — search a daily database of jobs from 1,000+ companies, no crawling wait
- [Oracle, Taleo, BambooHR & Rippling Jobs Scraper](https://apify.com/kadi_bence/ats-plus-jobs-scraper) — jobs from 9 more applicant tracking systems
- [Remote Jobs Scraper](https://apify.com/kadi_bence/remote-jobs-scraper) — remote jobs from We Work Remotely, RemoteOK, Himalayas and more
- [EURES Jobs Scraper](https://apify.com/kadi_bence/eures-jobs-scraper) — EU job vacancies from 31 countries
- [Website Tech Stack Detector](https://apify.com/kadi_bence/tech-stack-detector) — CMS, ecommerce, analytics and frameworks of any website
- [SEC Form D Scraper](https://apify.com/kadi_bence/sec-form-d-funding) — new startup funding rounds from SEC EDGAR

All my Actors: [apify.com/kadi_bence](https://apify.com/kadi_bence)

### Changelog

- **2026-10-05:** Workday fallback: companies not found on the 6 ATS platforms are read from their Workday career site (`atsPlatforms` option "workday", on by default). Jobs are returned newest first.
- **2026-10-05:** Added title include/exclude filters (`titleIncludes`, `titleExcludes`). Filtered-out jobs are not charged. The older `titleKeywords` text field still works.
- **2026-10-05, 1.0:** first public release: auto-detection across 6 ATS platforms, unified schema with salary, title/location/remote/date filters, monitoring mode.

# Actor input Schema

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

One per line, e.g. Stripe, ramp.com, Hugging Face, or a board URL like https://jobs.lever.co/spotify. The Actor detects which applicant tracking system (ATS) each company uses; the RUN_SUMMARY record shows the board it found. If a company is not found, open its careers page, click a job and paste the board URL (e.g. https://job-boards.greenhouse.io/stripe).

## `atsPlatforms` (type: `array`):

Which applicant systems to try when detecting a company's job board. Leave all selected unless you know the platform (fewer = faster). Workday is tried only when none of the others has the company (large employers like NVIDIA, Salesforce, Intel). Board URLs are always read directly.

## `titleIncludes` (type: `array`):

Keep only jobs whose title contains ANY of these words, e.g. engineer, data scientist. Not case-sensitive. Leave empty for all titles. Filtered-out jobs are not saved and not charged.

## `titleExcludes` (type: `array`):

Drop jobs whose title contains ANY of these words, e.g. intern, senior, manager. Not case-sensitive ('intern' also drops 'International'; use 'internship' to be precise). Filtered-out jobs are not charged.

## `titleKeywords` (type: `string`):

Same as 'Job title must contain' above, as one comma-separated text, e.g. 'engineer, data'. Kept for existing tasks; both lists are combined.

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

Keep jobs whose location text contains ANY of these as a whole word, e.g. London, Germany, US, Remote ('US' matches 'Remote - US' but not 'Austin'). A job with several locations is kept if any of them matches. Not case-sensitive. Leave empty for all.

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

Keep only jobs whose work mode is remote (from the ATS's workplace field, or 'remote' in the location or title).

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

Only jobs posted in the last N days, e.g. 7. Use 1 for jobs posted in about the last day. Leave empty for any date.

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

Stop after this many jobs per company. 0 = no limit (all open jobs). The default without input (API, MCP and AI-agent calls) is 20.

## `onlyNewJobs` (type: `boolean`):

Remember returned jobs and output only NEW ones on later runs. Ideal for a daily schedule (hiring signals, job alerts). The first run stores a baseline and returns everything. You only pay for new jobs. Jobs cut off by 'Max jobs per company' are not remembered, so they come in a later run.

## `monitorName` (type: `string`):

Separate 'already seen' lists for different schedules, e.g. 'engineers' and 'sales'. Use a new name to start over with a fresh baseline.

## `descriptionFormat` (type: `string`):

How to output the job description.

## `stripContactInfo` (type: `boolean`):

Removes e-mail addresses and phone numbers from descriptions. Recommended, so you don't store personal data (GDPR).

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

Not needed for these public APIs. Enable only if you see blocking errors.

## Actor input object example

```json
{
  "companies": [
    "Stripe",
    "Ramp",
    "Hugging Face"
  ],
  "atsPlatforms": [
    "greenhouse",
    "lever",
    "ashby",
    "workable",
    "recruitee",
    "personio",
    "workday"
  ],
  "remoteOnly": false,
  "maxJobsPerCompany": 20,
  "onlyNewJobs": false,
  "monitorName": "default",
  "descriptionFormat": "text",
  "stripContactInfo": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped jobs (table view).

## `jobsFull` (type: `string`):

All scraped jobs with every field.

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

Per-site/company counts, what was found and any problems.

# 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": [
        "Stripe",
        "Ramp",
        "Hugging Face"
    ],
    "maxJobsPerCompany": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kadi_bence/ats-jobs-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 = {
    "companies": [
        "Stripe",
        "Ramp",
        "Hugging Face",
    ],
    "maxJobsPerCompany": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("kadi_bence/ats-jobs-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 '{
  "companies": [
    "Stripe",
    "Ramp",
    "Hugging Face"
  ],
  "maxJobsPerCompany": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call kadi_bence/ats-jobs-scraper --silent --output-dataset

```

## MCP server setup

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