# Greenhouse, Lever, Workday & Ashby Jobs Scraper (`deriverge/greenhouse-lever-workday-jobs-scraper`) Actor

\[$1.50 / 1K] Live jobs read from the company career board at run time across ten systems: Greenhouse, Lever, Ashby, SmartRecruiters, Workday, Workable, Recruitee, Teamtailor, BambooHR and Personio. Give it a domain and it confirms the system first. New jobs only since your last run.

- **URL**: https://apify.com/deriverge/greenhouse-lever-workday-jobs-scraper.md
- **Developed by:** [deriverge s.r.o.](https://apify.com/deriverge) (community)
- **Categories:** Jobs, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 job listings

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?

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

## Career Site Jobs Scraper

### What does Career Site Jobs Scraper do?

**Career Site Jobs Scraper** reads job listings directly from company career sites, the place where jobs appear first, before they reach LinkedIn or Indeed. It supports the ten applicant tracking systems that power most career pages: **Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Workday, Recruitee, Teamtailor, BambooHR and Personio**. Paste the career-site URLs, and every job comes back in one unified schema: title, locations, remote flag, department, employment type, salary where the ATS shows it, posting date, job and apply links, and optionally the full description.

No browser, no proxies, no login. Every system is read through its public job-board endpoint, which is why runs are fast and cheap.

### Give it a domain, it finds the system

You rarely have a list of career-board URLs. You have a list of companies. Put in `stripe.com` and the actor reads the company careers page, and if that page is rendered by JavaScript it probes the usual board names directly against each system's API. Six of eight test companies resolved in one run this way.

The match is always confirmed before anything is scraped: either the company domain appears in the system's own response, or the board name matches the company. Greenhouse hosts a public demo board called "example" with 21 jobs belonging to a company named Democorp, and a naive probe would hand you those jobs for `example.com`. This actor rejects it and reports the company as not found, because the wrong company's jobs are worse than none.

### New jobs only: a hiring signal feed

Turn on `newOnly`, give the run a watch name or save it as a task, and schedule it. Each run compares the career sites with the snapshot from the previous run and returns **only the jobs that appeared since**. You pay for those and nothing else. Closed jobs are counted in the `CHANGES` record. A hundred competitor or prospect career sites checked every morning turns into a feed of new openings the day they are posted, which is what sales teams, recruiters and job boards actually want from career-site data.

### Filters

Title keywords (include and exclude), locations, remote only, posted within the last N days, and a cap per company. Filters are applied before charging, so a filtered-out job is free.

### Input

```json
{
  "companies": [
    "stripe.com",
    "https://jobs.ashbyhq.com/notion",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    { "url": "greenhouse:airbnb", "reference": "prospect-118" }
  ],
  "newOnly": true,
  "watchKey": "competitors",
  "keywords": ["engineer", "developer"],
  "remoteOnly": false
}
```

URLs are recognised by their host (boards.greenhouse.io, jobs.lever.co, jobs.ashbyhq.com, careers.smartrecruiters.com, apply.workable.com, \*.myworkdayjobs.com, \*.recruitee.com, \*.teamtailor.com, \*.bamboohr.com, \*.jobs.personio.de). The short form `ats:slug` works too. Sites the scraper cannot recognise are skipped and listed in the summary with the reason.

### Output

```json
{
  "key": "greenhouse:stripe:7532733",
  "ats": "greenhouse",
  "company": "stripe",
  "jobId": "7532733",
  "title": "Backend Engineer, Payments",
  "locations": ["Dublin, Ireland"],
  "remote": false,
  "department": "Engineering",
  "employmentType": null,
  "salaryText": null,
  "postedAt": "2026-08-28T09:14:02.000Z",
  "url": "https://stripe.com/jobs/search?gh_jid=7532733",
  "applyUrl": "https://stripe.com/jobs/search?gh_jid=7532733",
  "description": null,
  "firstSeenAt": "2026-09-02T10:41:11.000Z"
}
```

### Pricing

| Event | Price |
|---|---|
| Job listing returned | $0.003 ($3 per 1,000 jobs) |
| Jobs filtered out, jobs already seen in new-only mode, unsupported sites | **free** |

The leading career-site jobs actor charges $0.012 per job plus a $0.01 fee for starting the run. This one charges $0.003 per job and nothing to start.

No start fee. A run that returns nothing costs nothing.

### Frequently asked questions

**I only have company domains, not board URLs.** Put the domains in. The actor finds the system for each one and tells you in the run summary how it was found and which companies it could not place.

**Which ATS does a company use?** Open its careers page and look at the URL of a job: boards.greenhouse.io, jobs.lever.co, jobs.ashbyhq.com, careers.smartrecruiters.com, apply.workable.com, something.myworkdayjobs.com, company.recruitee.com, company.teamtailor.com, company.bamboohr.com or company.jobs.personio.de. Paste that URL.

**Why is the description off by default?** On Greenhouse, Lever, Ashby, Recruitee, Teamtailor and Personio the description comes with the listing. On SmartRecruiters, Workable, Workday and BambooHR it needs one extra request per job. Switch it on when you need the text.

**How does new-only know what is new?** By the job's stable identifier in its ATS. The snapshot is stored per watch name (or per saved task) and updated after every run. The first run with a new name returns everything and saves the baseline.

**Does it work on LinkedIn or Indeed?** No. This scraper reads career sites, the original source. For aggregators use a dedicated scraper.

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

1. Open the actor and fill in `companies` in the input form, or paste the JSON input from the example above.
2. Click **Start**. The first rows appear in the **Output** tab within seconds; the run summary is in the **Storage** tab under the key `SUMMARY`.
3. Download the results as JSON, CSV or Excel from the Output tab, or read them through the API link shown there.
4. To run it on a schedule, click **Save as a task**, set the input once and add a schedule. Scheduled tasks keep their own change snapshot, so the new-only mode works without any extra setup.

### Integrations

The actor is available in the Apify apps for **Make**, **Zapier**, **n8n** and **Keboola**, where you pick it by name and map the input fields. It is also exposed to AI agents through the Apify MCP server, and callable from any language through the Apify API; the API tab on this page has ready-made snippets for Node.js, Python and curl. Every run can post its results to a webhook when it finishes.

### Support

Questions and problems go into the **Issues** tab of this actor. Each issue is answered by the maintainer, and fixes ship as new builds without any change on your side.

Built and operated by deriverge s.r.o., the team behind the company checkers and the EU VAT checker on Apify Store. Same rules everywhere: unified schemas, honest billing, no charge for what you did not get.

# Actor input Schema

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

One entry per company. Either the career-site URL (https://boards.greenhouse.io/stripe, https://jobs.ashbyhq.com/notion, https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite), the short form ats:slug (greenhouse:stripe), or just the company domain (stripe.com): the actor then reads the company careers page and finds which applicant tracking system it uses. Objects may carry a reference returned on every job. Companies with no supported system are skipped and listed in the run summary.

## `newOnly` (type: `boolean`):

Keeps a snapshot per watch name (or per saved task) and returns only jobs that were not in the previous snapshot. Schedule the task daily and you get a hiring-signal feed: every new opening, once, the day it appears. Closed jobs are counted in the CHANGES record.

## `watchKey` (type: `string`):

Name of the snapshot used by the new-only mode, for example "competitors". Runs from a saved task get a snapshot automatically even without a name.

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

Adds the job description as plain text. Costs one extra request per job on SmartRecruiters, Workable, Workday and BambooHR, so runs take longer there.

## `keywords` (type: `array`):

Keep only jobs whose title, department or team contains at least one of these words, case-insensitive. Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Drop jobs whose title, department or team contains any of these words.

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

Keep only jobs whose location contains one of these strings, for example "London", "United States", "Remote".

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

Keep only jobs the ATS marks as remote or whose location says remote.

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

Drop jobs older than this many days when the ATS provides a posting date. Leave empty for no limit.

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

Caps the number of jobs returned per career site. Leave empty for all.

## Actor input object example

```json
{
  "companies": [
    "stripe.com",
    "https://jobs.ashbyhq.com/notion",
    {
      "url": "greenhouse:airbnb",
      "reference": "prospect-118"
    }
  ],
  "newOnly": false,
  "includeDescription": false,
  "remoteOnly": false
}
```

# Actor output Schema

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

One row per job with the unified schema: title, locations, remote, department, employment type, salary text where the ATS provides it, posting date, links and optional description.

## `changes` (type: `string`):

New, closed and retitled jobs compared with the previous snapshot of the same watch name or task.

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

Per-company counts, skipped inputs with reasons, and totals.

# 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.com",
        "https://jobs.ashbyhq.com/notion",
        {
            "url": "greenhouse:airbnb",
            "reference": "prospect-118"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("deriverge/greenhouse-lever-workday-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.com",
        "https://jobs.ashbyhq.com/notion",
        {
            "url": "greenhouse:airbnb",
            "reference": "prospect-118",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("deriverge/greenhouse-lever-workday-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.com",
    "https://jobs.ashbyhq.com/notion",
    {
      "url": "greenhouse:airbnb",
      "reference": "prospect-118"
    }
  ]
}' |
apify call deriverge/greenhouse-lever-workday-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,deriverge/greenhouse-lever-workday-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/9fYY4pfqSzmiNsrgh/builds/X0SODLMPp4WOKWkIQ/openapi.json
