# Career Site Jobs Scraper - Greenhouse, Lever, Ashby, Workday (`sweet_stickball/ats-jobs-scraper`) Actor

Career site jobs scraper and ATS jobs API alternative: extract job postings from Greenhouse, Lever, Ashby and Workday boards with title, department, locations, remote flag, employment type, salary range, posting date, apply URL and description. Company URLs or names, no login or API key.

- **URL**: https://apify.com/sweet_stickball/ats-jobs-scraper.md
- **Developed by:** [CrawlKit](https://apify.com/sweet_stickball) (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.90 / 1,000 job postings

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

## Career Site Jobs Scraper - Greenhouse, Lever, Ashby, Workday

Scrape job postings from company career sites hosted on **Greenhouse**, **Lever**, **Ashby** and **Workday**. Give the Actor a list of career page URLs or company names; it returns one flat JSON record per open job, with title, department, locations, remote flag, employment type, salary range (when the employer publishes one), posting date, apply URL and the full description as text and HTML.

The data comes from the public JSON endpoints these applicant tracking systems (ATS) serve to their own job boards. No login, no API key, no browser.

### What it does

- Detects the ATS from each URL: `boards.greenhouse.io`, `job-boards.greenhouse.io`, `jobs.lever.co`, `jobs.ashbyhq.com`, `<tenant>.wdN.myworkdayjobs.com/<site>`.
- Also accepts `greenhouse:airbnb` / `lever:spotify` / `ashby:ramp`, a bare board name (`stripe`, looked up on Greenhouse, then Lever, then Ashby), or a company's own careers page URL, which is read once (if its robots.txt allows it) to find a link to one of these job boards.
- Reads every open job of each board, newest first on Greenhouse, Lever and Ashby, and fetches the job detail where the list does not carry it (Greenhouse: offices, departments, pay ranges, description; Workday: description, locations, date).
- Optional filters: words in the job title, location text, remote only, posted within N days.
- Normalizes everything to one schema: ISO 8601 UTC dates, `remote` boolean, `workplaceType` (remote / hybrid / onsite), numeric salary with separate currency and period.
- Deduplicates on (`platform`, `jobId`).
- A company that cannot be read (unknown board, refused request) is reported in the log and the run continues with the others. The run fails with an explicit reason only when no job at all is returned (board not found, blocked, no job matching the filters).

### Input

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `companies` | array of strings | Yes | - | Career site URLs (Greenhouse, Lever, Ashby, Workday), `platform:slug` values, bare board names, or company careers page URLs. Workday URLs must include the site name, e.g. `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`. |
| `keyword` | string | No | - | Only jobs whose title contains every word (case-insensitive). |
| `location` | string | No | - | Only jobs with a location containing this text, e.g. `London`, `Germany`. `remote` also matches jobs flagged remote. |
| `remoteOnly` | boolean | No | `false` | Only remote jobs. |
| `postedWithinDays` | integer | No | - | Only jobs first published in the last N days. Jobs without a date are excluded when set. |
| `includeDescription` | boolean | No | `true` | Include `descriptionText` and `descriptionHtml`. |
| `maxItems` | integer | No | 20 | Maximum jobs in total, shared across companies: each company gets an equal share, and the share a company does not use passes to the next ones. |

Example:

```json
{
    "companies": [
        "https://boards.greenhouse.io/airbnb",
        "https://jobs.lever.co/spotify",
        "ramp",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ],
    "keyword": "engineer",
    "postedWithinDays": 14,
    "maxItems": 100
}
```

### Output

One dataset item per job (description shortened here):

```json
{
    "jobId": "6232541004",
    "requisitionId": "2676",
    "title": "Customer Enablement Manager - Figma Weave (New York, United States)",
    "company": "Figma",
    "companyId": "figma",
    "platform": "greenhouse",
    "department": "Figma Weave",
    "team": null,
    "location": "New York, NY • United States",
    "locations": ["New York, NY • United States", "Canada", "US"],
    "remote": false,
    "workplaceType": null,
    "employmentType": null,
    "salaryMin": 127000,
    "salaryMax": 269000,
    "salaryCurrency": "USD",
    "salaryPeriod": "YEAR",
    "postedAt": "2026-10-27T20:24:36Z",
    "updatedAt": "2026-10-27T20:24:36Z",
    "applyUrl": "https://boards.greenhouse.io/figma/jobs/6232541004?gh_jid=6232541004",
    "jobUrl": "https://boards.greenhouse.io/figma/jobs/6232541004?gh_jid=6232541004",
    "descriptionText": "Figma is growing our team of passionate creatives and builders on a mission to make design accessible to all. ...",
    "descriptionHtml": "<div class=\"content-intro\"><p>Figma is growing our team of passionate creatives ...",
    "source": "figma",
    "scrapedAt": "2026-10-28T06:45:37Z"
}
```

Field availability by ATS:

| Field | Greenhouse | Lever | Ashby | Workday |
|-------|-----------|-------|-------|---------|
| `department` / `team` | department | both | both | - |
| `workplaceType` | when the employer sets it | yes | yes | when the site publishes it |
| `employmentType` | when the employer sets it | yes | yes | yes |
| salary | when the employer publishes a pay range | when the employer publishes a pay range | when the employer publishes compensation | - |
| `postedAt` | date and time | date and time | date and time | date only |
| `updatedAt` | yes | - | - | - |
| `requisitionId` | yes | - | - | yes |

`company` is the company name on Greenhouse and the board name (slug or Workday tenant) on the other platforms.

### Pricing

Pay-per-event, no start fee: **$1.50 per 1,000 jobs** on the Apify Free plan, lower on paid plans.

| Event | Free | Starter | Scale | Business | Enterprise |
|-------|------|---------|-------|----------|------------|
| `JOB` (one job pushed to the dataset) | $1.50 | $1.30 | $1.10 | $0.90 | $0.90 |

Prices in USD per 1,000 events. Only jobs returned are charged; a company that cannot be read costs nothing. When the maximum cost per run you set is reached, the run stops cleanly with the jobs already collected.

### Limitations

- Only career sites hosted on Greenhouse, Lever, Ashby and Workday. Other systems (SmartRecruiters, iCIMS, Taleo, SuccessFactors...) are not supported. A careers page on the company's own domain works only if it links to one of the four job boards in its HTML (pages built entirely in JavaScript may not).
- A bare company name is matched against the board name, which is not always the company name (Greenhouse uses `airbnb`, but some companies use another slug). When a name finds nothing, use the job board URL.
- Workday sites cannot be found from a name: give the full URL with the site name. Workday returns the posting date without a time and has no department or salary fields (some employers write the pay range in the description).
- Salary fields are filled only when the ATS publishes a structured pay range (Greenhouse pay transparency, Lever salary range, Ashby compensation). Ranges written only in the description text are not parsed. For Greenhouse ranges with several zones, the widest range in the first listed currency is returned, and the period is read from the range title or, failing that, inferred from the amount.
- `keyword` matches the job title only, not the description. On Workday it is also sent to the site's own search, so results follow Workday's relevance order.
- Greenhouse, Lever and Ashby list all open jobs of a board; very large Workday sites are read 20 jobs per page, up to 2,000 jobs per site.
- Jobs reflect what the board publishes at run time; closed jobs disappear from the boards and are not returned.

### Related Actors

- [Indeed Jobs Scraper API - Listings & Salaries, $0.50/1K](https://apify.com/sweet_stickball/indeed-job-scraper) — Scrape Indeed job listings: title, company, location, salary and job type in 6 countries (US, UK, FR, DE, CA, AU). Jobs data API, no login needed.
- [Google Jobs Scraper API - Listings, Salaries & Apply Links](https://apify.com/sweet_stickball/google-jobs-scraper) — Scrape Google for Jobs listings: title, company, location, salary, apply links and posting date. Job postings data API for recruiters, no login needed.
- [Glassdoor Scraper - Company Reviews & Salaries](https://apify.com/sweet_stickball/glassdoor-scraper) — Scrape Glassdoor company reviews and salary ranges by company name or URL: rating, sub-ratings, title, pros, cons, advice, job title, date, plus typical pay per job title.

# Actor input Schema

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

One entry per company. Accepted forms: a job board URL on Greenhouse (https://boards.greenhouse.io/airbnb, https://job-boards.greenhouse.io/figma), Lever (https://jobs.lever.co/spotify), Ashby (https://jobs.ashbyhq.com/ramp) or Workday (https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite - the URL must include the career site name); a 'platform:slug' value such as 'greenhouse:airbnb', 'lever:spotify' or 'ashby:ramp'; a bare board name such as 'stripe', looked up on Greenhouse, then Lever, then Ashby; or a company's own careers page URL, which is read once to find a link to one of these job boards. Workday sites cannot be found from a bare name.

## `keyword` (type: `string`):

Only jobs whose title contains every word of this text (case-insensitive), e.g. 'data engineer' or 'sales'. Leave empty for all jobs.

## `location` (type: `string`):

Only jobs with a location containing this text (case-insensitive), e.g. 'London', 'Germany', 'NY'. The value 'remote' also matches jobs flagged remote. Leave empty for all locations.

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

Only jobs the ATS marks as remote, or whose location says 'Remote'.

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

Only jobs first published in the last N days (by calendar date). Jobs without a publication date are excluded when this filter is set. Leave empty for no date filter.

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

Add the full job description as plain text (descriptionText) and HTML (descriptionHtml). Turn off for smaller datasets.

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

Maximum number of jobs returned in total (each job is one billed JOB event). The limit is shared across companies: each company gets an equal share, and shares a company does not use pass to the next ones. Newest jobs first on Greenhouse, Lever and Ashby; Workday order is the career site's own.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/airbnb",
    "lever:spotify",
    "ramp"
  ],
  "keyword": "engineer",
  "location": "London",
  "remoteOnly": false,
  "postedWithinDays": 7,
  "includeDescription": true,
  "maxItems": 10
}
```

# Actor output Schema

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

Job postings shown with the 'jobs' view (all fields are in the full items).

# 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://boards.greenhouse.io/airbnb",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/ramp",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("sweet_stickball/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://boards.greenhouse.io/airbnb",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/ramp",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    ],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("sweet_stickball/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://boards.greenhouse.io/airbnb",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/ramp",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "maxItems": 10
}' |
apify call sweet_stickball/ats-jobs-scraper --silent --output-dataset

```

## MCP server setup

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