# ATS Jobs Scraper: Greenhouse, Lever, Workable & SmartRecruiters (`api-co/ats-jobs-scraper`) Actor

Scrape company job postings from Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee careers pages in one schema: title, location, remote, salary, department, description, apply URL. Paste careers URLs or slugs. Hiring signals for sales and recruiting. Official public APIs, no proxies.

- **URL**: https://apify.com/api-co/ats-jobs-scraper.md
- **Developed by:** [Emilio Cisneros](https://apify.com/api-co) (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 $0.96 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## ATS Jobs Scraper: Greenhouse, Lever, Workable & SmartRecruiters

Get **every open job from a company's careers page** in one clean, normalized dataset — no matter which applicant tracking system (ATS) the company uses. Paste careers-page URLs (or just company slugs) and get title, location, remote flag, department, employment type, salary range (when published), posting date, description and apply link.

### How to use

1. Paste careers-page URLs (Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee) or bare company slugs into **Companies**.
2. Optionally filter by title keywords, location, remote-only or *posted within N days*.
3. Click **Start**, then download the jobs as JSON, CSV or Excel, or connect them to Google Sheets, Slack or a webhook.

### Why this Actor

- **6 ATSs, one schema** — Greenhouse, Lever (US & EU), Ashby, Workable, SmartRecruiters, Recruitee.
- **Official public job-board APIs** — the same JSON feeds the companies' own careers pages use. No browser, no proxies, no CAPTCHAs, so runs are fast, cheap and reliable.
- **Auto-detect** — give a bare slug like `openai` and every supported ATS is tried.
- **Filters** — title keywords, excluded keywords, location, remote-only, department, posted within N days.
- **Fair pricing** — pay only per job returned. Boards that fail or have no jobs produce a free error record explaining why.
- **Fails loudly** — if nothing matches, the run fails with a clear message instead of "succeeding" with an empty dataset.

### Input examples

```json
{
  "companies": ["https://jobs.ashbyhq.com/openai", "https://boards.greenhouse.io/airbnb", "lever:palantir", "https://apply.workable.com/blueground", "https://jobs.smartrecruiters.com/BoschGroup", "https://bunq.recruitee.com"],
  "titleKeywords": ["engineer", "data"],
  "locationKeywords": ["remote", "united states"],
  "postedWithinDays": 30,
  "maxItems": 500
}
```

Accepted company formats: careers URLs (`boards.greenhouse.io/<slug>`, `job-boards.greenhouse.io/<slug>`, `jobs.lever.co/<slug>`, `jobs.eu.lever.co/<slug>`, `jobs.ashbyhq.com/<slug>`, `apply.workable.com/<slug>`, `jobs.smartrecruiters.com/<slug>`, `<slug>.recruitee.com`), `provider:slug`, or a bare slug.

### Output (one item per job)

```json
{
  "provider": "ashby", "company": "openai", "companyName": "openai", "jobId": "8fb1615c-…",
  "title": "Technical Program Manager, Compute Infrastructure", "department": "Technical Program Management",
  "location": "San Francisco", "locations": ["San Francisco"], "country": "United States",
  "workplaceType": null, "isRemote": null, "employmentType": "FullTime",
  "salary": { "min": 230000, "max": 385000, "currency": "USD", "interval": "1 YEAR", "summary": "$230K – $385K" },
  "postedAt": "2026-03-12T16:38:15.322Z", "url": "https://jobs.ashbyhq.com/openai/…", "applyUrl": "https://jobs.ashbyhq.com/openai/…/application",
  "descriptionText": "About the Team …", "scrapedAt": "2026-10-19T03:00:00.000Z"
}
```

Error records (not charged) look like `{"input": "...", "error": "BOARD_NOT_FOUND", "errorMessage": "...", "#error": true}`.

### Use cases

Job aggregators and niche job boards, recruiting and sourcing, hiring-signal / sales-trigger monitoring (who is hiring for what), labor-market research, salary benchmarking, and AI agents that need fresh job data. Schedule it daily and use `postedWithinDays: 1` to get only new jobs.

### Pricing

Pay per result: **$1.20 per 1,000 jobs** (plus Apify's tiny start fee). Error records are free.

### How much does it cost?

You only pay for results, never for compute time:

| You get | You pay (Starter/Bronze plan price) |
|---|---|
| 100 jobs | $0.12 |
| 1,000 jobs | $1.20 |
| 10,000 jobs | $12.00 |

Apify's **free plan includes $5 of usage every month**, and free-plan users pay **half price** on this Actor, so that covers about **8,332 jobs** at no cost. Paid plans get volume discounts (Silver -10%, Gold -20%). Set a *maximum cost per run* and the Actor stops cleanly at your limit.

### Notes

Data comes from publicly published job postings via the providers' public job-board endpoints. Job postings are company data, not personal data. Please respect each provider's terms and use the data responsibly.

### Run it from code (API, Python, JavaScript)

```bash
curl -X POST "https://api.apify.com/v2/acts/api-co~ats-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" -d '{"companies": ["https://boards.greenhouse.io/airbnb", "lever:palantir"], "titleKeywords": ["engineer"], "maxItems": 200}'
```

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("api-co/ats-jobs-scraper").call(run_input={"companies": ["https://boards.greenhouse.io/airbnb", "lever:palantir"], "titleKeywords": ["engineer"], "maxItems": 200})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('api-co/ats-jobs-scraper').call({"companies": ["https://boards.greenhouse.io/airbnb", "lever:palantir"], "titleKeywords": ["engineer"], "maxItems": 200});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

It also works from **AI agents through the Apify MCP server**, and with Zapier, Make, n8n, Google Sheets and webhooks. You can schedule it in the Apify Console.

### FAQ

**Is this a LinkedIn or Indeed scraper?**
No. It reads companies' own ATS job boards (Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee). These are first-party, usually fresher than aggregators, and include the direct apply link.

**How do I find a company's ATS slug?**
Open the company's careers page and copy the job-board URL, e.g. `boards.greenhouse.io/airbnb`. If you only know the name, pass a bare slug like `airbnb` and every supported ATS is tried.

**Can I monitor new jobs daily?**
Yes. Schedule the Actor with `postedWithinDays: 1` and connect the dataset to Slack, Google Sheets, Zapier, Make or n8n.

**Does it return salary?**
Yes, when the company publishes it (common on Ashby and Greenhouse in US pay-transparency states).

# Actor input Schema

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

One per line. Examples: https://boards.greenhouse.io/airbnb, https://jobs.lever.co/palantir, https://jobs.ashbyhq.com/openai, https://apply.workable.com/blueground, https://jobs.smartrecruiters.com/BoschGroup, https://bunq.recruitee.com, lever:palantir, or just a slug like 'openai' (all ATSs are tried automatically).

## `titleKeywords` (type: `array`):

Case-insensitive. Leave empty for all jobs.

## `excludeTitleKeywords` (type: `array`):

E.g. intern, senior.

## `locationKeywords` (type: `array`):

Matches location, all locations, country and workplace type. E.g. London, United States, Remote.

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

Keep only jobs marked remote.

## `departments` (type: `array`):

Department/team contains any of.

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

Jobs without a publish date are kept unless 'Strict dates' is on.

## `strictDates` (type: `boolean`):

Drop jobs that have no publish date when a date filter is set.

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

Include description text.

## `includeHtml` (type: `boolean`):

Include description HTML.

## `maxItems` (type: `integer`):

Stop after this many jobs. You pay only per job returned.

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

Max concurrent companies.

## Actor input object example

```json
{
  "companies": [
    "https://jobs.ashbyhq.com/openai",
    "https://boards.greenhouse.io/airbnb",
    "lever:palantir"
  ],
  "remoteOnly": false,
  "strictDates": false,
  "includeDescription": true,
  "includeHtml": false,
  "maxItems": 50,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `results` (type: `string`):

Normalized job postings (one item per job) plus free error records for boards that failed.

# 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": [
        "https://jobs.ashbyhq.com/openai",
        "https://boards.greenhouse.io/airbnb",
        "lever:palantir"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("api-co/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": [
        "https://jobs.ashbyhq.com/openai",
        "https://boards.greenhouse.io/airbnb",
        "lever:palantir",
    ],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("api-co/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": [
    "https://jobs.ashbyhq.com/openai",
    "https://boards.greenhouse.io/airbnb",
    "lever:palantir"
  ],
  "maxItems": 50
}' |
apify call api-co/ats-jobs-scraper --silent --output-dataset

```

## MCP server setup

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