# Company Jobs Scraper - Greenhouse, Lever, Ashby + more (`burn98/ats-jobs-scraper`) Actor

Get all job postings for a list of companies. Auto-detects the ATS behind each careers page (Greenhouse, Lever, Ashby, Workable, Recruitee, SmartRecruiters) and returns clean, normalized job data.

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

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Company Jobs Scraper - Greenhouse, Lever, Workday, Ashby & More

Scrape job postings from any list of companies in one run. Paste domains or careers page URLs. The actor auto-detects the ATS and returns clean, normalized job data.

One input, seven ATS platforms, one consistent schema. Ideal for job boards, recruiting tools, sales intelligence and market research.

### Supported ATS platforms

| Platform | Example input |
|---|---|
| Greenhouse | `https://boards.greenhouse.io/gitlab` |
| Lever | `https://jobs.lever.co/palantir` |
| Workday | `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite` |
| Ashby | `https://jobs.ashbyhq.com/linear` |
| Workable | `https://apply.workable.com/yourcompany` |
| Recruitee | `https://yourcompany.recruitee.com` |
| SmartRecruiters | `https://careers.smartrecruiters.com/BoschGroup` |

You can also paste a bare domain like `linear.app` or a careers page like `https://company.com/careers`. The actor finds the ATS board behind it automatically.

### Why this actor

- **One schema for every ATS.** Title, department, location, remote flag, apply link, posting date and source. No per-platform parsing.
- **Bulk ready.** Run 5 or 500 companies at once. Each run fetches live data for the full list.
- **Stable and fast.** Uses each platform's official public JSON feed, not fragile HTML scraping. No proxies needed.
- **Pay per result.** You only pay for jobs delivered. $2 per 1000 jobs.
- **Complete when you need it.** Add full plain-text descriptions with one toggle.

### Use cases

- **Job boards and aggregators:** Keep listings fresh for a fixed portfolio of companies.
- **Sales and recruiting intelligence:** Track hiring activity as a growth signal.
- **Market research:** Monitor who is hiring for what, where and when.
- **Newsletters and talent communities:** Power "Who is hiring" digests with live data.

### Input

Pass a list of companies as domains, careers page URLs, or direct ATS board URLs. ATS detection is automatic.

```json
{
    "companies": [
        "linear.app",
        "https://jobs.lever.co/palantir",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "https://boards.greenhouse.io/gitlab"
    ],
    "includeDescription": false,
    "maxJobsPerCompany": 500
}
```

| Field | Type | Description |
|---|---|---|
| `companies` | array of strings | Required. Domains, careers pages, or direct ATS board URLs. |
| `includeDescription` | boolean | Add plain-text job description to each item. Default is `false`. |
| `maxJobsPerCompany` | integer | Cap per company. Default is `500`. |

### Output

One dataset item per job posting. Consistent fields across all ATS platforms.

```json
{
    "company": "palantir",
    "title": "Software Engineer - Infrastructure",
    "department": "Engineering",
    "location": "San Francisco, CA",
    "remote": false,
    "url": "https://jobs.lever.co/palantir/abc123",
    "publishedAt": "2026-06-30T18:21:07.000Z",
    "source": "lever"
}
```

With `includeDescription: true`, each item also includes a `description` field with the full plain-text job description.

Other fields are always present. `remote` is `true`, `false`, or `null` if not specified by the source. `department` and `publishedAt` are `null` when the ATS does not provide them.

### FAQ

**What input formats are supported?**
Three formats work: bare domains (`linear.app`), company careers pages (`https://company.com/careers`), and direct ATS board URLs (`https://jobs.lever.co/...`). The actor tries ` /careers` and ` /jobs` for bare domains and resolves redirects automatically.

**A company failed with "No supported ATS detected". Why?**
That company uses an ATS not yet supported (for example BambooHR, Personio, iCIMS) or a fully custom careers site with no public ATS feed. Open an issue with the URL. Platform requests drive the roadmap.

**Why is `publishedAt` null for Workday jobs?**
Workday's public job feed only shows relative dates like "Posted Today", not exact timestamps. All other platforms return an ISO date when available. Workday jobs still include title, location, apply link and description.

**Does `includeDescription` affect speed or cost?**
Descriptions are included in the same job record, so the price stays $2 per 1000 jobs. For Workday, each description needs one extra request, so large Workday boards take a bit longer when this option is on.

**How much does it cost?**
Pay per result: $2 per 1000 jobs delivered. You pay only for results returned. No charge for companies with no jobs or failed lookups.

**Is this legal?**
Yes. The actor reads public job feeds that companies publish to distribute their openings. It collects only public job postings. No personal data is scraped.

**How fresh is the data?**
Live at run time. Each run queries the ATS platforms directly. Schedule the actor on a regular interval to keep your dataset continuously up to date.

# Actor input Schema

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

Company domains, careers page URLs, or direct ATS board URLs (e.g. linear.app, https://stripe.com/jobs, https://jobs.lever.co/palantir). The ATS is detected automatically.

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

Adds plain-text description to each job. Larger items; leave off if you only need titles/locations/links.

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

Cap on postings returned per company.

## Actor input object example

```json
{
  "companies": [
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/linear",
    "https://boards.greenhouse.io/gitlab",
    "https://adobe.wd5.myworkdayjobs.com/external_experienced"
  ],
  "includeDescription": false,
  "maxJobsPerCompany": 500
}
```

# 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.lever.co/palantir",
        "https://jobs.ashbyhq.com/linear",
        "https://boards.greenhouse.io/gitlab",
        "https://adobe.wd5.myworkdayjobs.com/external_experienced"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("burn98/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.lever.co/palantir",
        "https://jobs.ashbyhq.com/linear",
        "https://boards.greenhouse.io/gitlab",
        "https://adobe.wd5.myworkdayjobs.com/external_experienced",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("burn98/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.lever.co/palantir",
    "https://jobs.ashbyhq.com/linear",
    "https://boards.greenhouse.io/gitlab",
    "https://adobe.wd5.myworkdayjobs.com/external_experienced"
  ]
}' |
apify call burn98/ats-jobs-scraper --silent --output-dataset

```

## MCP server setup

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