# Career Site Jobs Scraper: Workday, Greenhouse, Lever (`luzivanlt/career-site-jobs-scraper`) Actor

Every job on Greenhouse, Lever, Ashby, SmartRecruiters and Workday boards, checked against each board's count. $1 per 1,000 jobs. Full description, pay where listed, locations, remote or hybrid.

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

## Pricing

from $0.70 / 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

## Career Site Jobs Scraper: Workday, Greenhouse, Lever

Get every job on a company's own career board, straight from the board,
and know you have them all: each board read to its end is checked against
the count the board itself shows. Works with Greenhouse, Lever, Ashby,
SmartRecruiters and Workday. One row per job, with the full description, the
locations, remote or hybrid, employment type, department and team, dates, and
the pay where the board lists it. No account or cookies needed.

Tested daily. Latest check: 151 jobs from five boards, one on each system,
in 43 seconds; 846 of 846 jobs from the same five boards read whole, in 3
minutes.

### What does this Actor do?

You paste links to companies' career boards. For each board the Actor reads
the jobs it lists right now, live, and saves one row per job, until it
reaches your limit or the board has no more jobs. When a board is read to its
end, the run's status says whether the jobs saved match the count the board
shows.

Each job comes with:

- its title, its link on the board, the link to apply where the board gives
  one, and the company's name where the board states it
- the full description, as text and as HTML, and its sections (such as
  "What you'll do" or "Qualifications") where the board splits it
- where it is: the main location, every other location, and city, region,
  country, postal code, street and coordinates where the board gives them
- whether it is remote, hybrid or on-site, and the employment type
  (full-time, part-time, contract…)
- its department and team, offices, experience level, industry and job
  function, where the board lists them
- when it was published, last updated and when applications close
- the pay, as shown and as numbers (from, to, period, currency), and every
  pay tier, where the board lists pay
- the board's own requisition id, language, custom fields and recruiter,
  where it has them
- the board it came from and the number of jobs that board shows

### Why use it?

- **Know you got every job.** Each board read whole is checked against the
  board's own count, and the run's status says so.
- **Live, not a copy.** The jobs are read from the board when you run it, so
  a job taken down an hour ago is not in your data.
- **Big Workday sites past 2,000.** One Workday search lists at most 2,000
  jobs; a larger site is read further: 2,711 of the 2,713 jobs a Workday site
  showed, in one run.
- **Five systems, one record.** Greenhouse, Lever, Ashby, SmartRecruiters and
  Workday jobs come out with the same fields, ready to merge.
- **Your filters kept.** A Lever link's location, team, department and
  commitment filters, and a Workday link's search and filters, are applied.

### How to use it

1. Paste one or more **Career board links**.
2. Optionally, set **Max jobs per board**.
3. Click **Start**. When the run ends, open the **Output** tab to view the
   jobs or download them.

Run it with no input to see a sample: 30 jobs from each of five boards,
charged as usual.

#### Links that work

| System          | A board link looks like                                    |
| --------------- | ---------------------------------------------------------- |
| Greenhouse      | `https://job-boards.greenhouse.io/airbnb`                  |
| Lever           | `https://jobs.lever.co/spotify`                            |
| Ashby           | `https://jobs.ashbyhq.com/ramp`                            |
| SmartRecruiters | `https://jobs.smartrecruiters.com/Canva`                   |
| Workday         | `https://adobe.wd5.myworkdayjobs.com/external_experienced` |

A link to one job on these boards reads its whole board. Greenhouse's older
`boards.greenhouse.io` links and its embedded boards (`?for=<company>`)
work too. A company's career page on its own domain is not read: open one of
its jobs and paste the link the job sits on. Other sites stop the run before
anything is read, naming the link.

### Input

| Field                                      | What it does                                        | Default |
| ------------------------------------------ | --------------------------------------------------- | ------- |
| **Career board links** (`startUrls`)       | Board links on the five systems, one board per link | —       |
| **Max jobs per board** (`maxJobsPerBoard`) | Stop each board after this many jobs, 1 to 10,000   | `1000`  |

Example input:

```json
{
  "startUrls": [
    { "url": "https://job-boards.greenhouse.io/airbnb" },
    { "url": "https://jobs.lever.co/spotify?team=Marketing" },
    { "url": "https://adobe.wd5.myworkdayjobs.com/external_experienced" }
  ],
  "maxJobsPerBoard": 5000
}
```

### Output

One row per job. An example, with made-up values and the longer texts cut:

```json
{
  "job_key": "ashby:example:0f1e2d3c-4b5a-6978-8796-a5b4c3d2e1f0",
  "platform": "ashby",
  "board": "example",
  "board_url": "https://jobs.ashbyhq.com/example",
  "board_total": 169,
  "company_name": null,
  "job_id": "0f1e2d3c-4b5a-6978-8796-a5b4c3d2e1f0",
  "title": "Senior Product Designer",
  "url": "https://jobs.ashbyhq.com/example/0f1e2d3c-4b5a-6978-8796-a5b4c3d2e1f0",
  "apply_url": "https://jobs.ashbyhq.com/example/0f1e2d3c-4b5a-6978-8796-a5b4c3d2e1f0/application",
  "location": "New York, NY",
  "locations": ["New York, NY", "Remote (US)"],
  "city": "New York",
  "region": "NY",
  "country": "USA",
  "country_code": null,
  "postal_code": null,
  "street_address": null,
  "latitude": null,
  "longitude": null,
  "addresses": [
    { "location": "New York, NY", "city": "New York", "region": "NY", "country": "USA" },
    { "location": "Remote (US)", "city": null, "region": null, "country": "USA" }
  ],
  "is_remote": false,
  "workplace_type": "hybrid",
  "hybrid_description": null,
  "employment_type": "FullTime",
  "department": "Design",
  "departments": ["Design"],
  "team": "Product Design",
  "offices": [],
  "experience_level": null,
  "industry": null,
  "job_function": null,
  "education": null,
  "published_at": "2026-10-02T15:00:00.000Z",
  "updated_at": null,
  "closes_at": null,
  "requisition_id": null,
  "language": null,
  "salary_text": "$150K - $190K",
  "salary_min": 150000,
  "salary_max": 190000,
  "salary_currency": "USD",
  "salary_interval": "1 YEAR",
  "compensation_tiers": [
    {
      "title": "Zone A",
      "summary": "$150K – $190K • Offers Equity",
      "details": null,
      "components": [
        {
          "type": "Salary",
          "summary": "$150K – $190K",
          "interval": "1 YEAR",
          "currency": "USD",
          "min": 150000,
          "max": 190000
        },
        {
          "type": "EquityPercentage",
          "summary": "Offers Equity",
          "interval": "NONE",
          "currency": null,
          "min": null,
          "max": null
        }
      ]
    }
  ],
  "description_text": "About the role\nYou will design…",
  "description_html": "<p><strong>About the role</strong></p><p>You will design…</p>",
  "sections": [],
  "custom_fields": [],
  "recruiter_name": null,
  "is_listed": true,
  "can_apply": null
}
```

| Field                                | What it holds                                                                             |
| ------------------------------------ | ----------------------------------------------------------------------------------------- |
| `job_key`                            | The job's key: system, board and the job's id on it                                       |
| `platform`                           | `greenhouse`, `lever`, `ashby`, `smartrecruiters` or `workday`                            |
| `board`                              | The board's name on its system (`tenant/site` on Workday)                                 |
| `board_url`                          | The board, as read                                                                        |
| `board_total`                        | How many jobs the board shows (on Lever, how many it listed)                              |
| `company_name`                       | The company, where the board states it (Greenhouse, SmartRecruiters, Workday)             |
| `job_id`                             | The job's id on its board                                                                 |
| `title`                              | The job's title                                                                           |
| `url`                                | The job's page on the board                                                               |
| `apply_url`                          | Where to apply, where the board gives a separate link                                     |
| `location`                           | The main location, as the board shows it                                                  |
| `locations`                          | Every location the job lists                                                              |
| `city`, `region`, `country`          | The place, where the board splits it out                                                  |
| `country_code`                       | The country as a two-letter code, where the board gives one                               |
| `postal_code`, `street_address`      | The address, where the board gives one (SmartRecruiters)                                  |
| `latitude`, `longitude`              | Where the job is on a map (SmartRecruiters)                                               |
| `addresses`                          | Each location with its city, region and country (Ashby)                                   |
| `is_remote`                          | `true` for a remote job; empty when the board does not say                                |
| `workplace_type`                     | `remote`, `hybrid` or `onsite`, where the board says                                      |
| `hybrid_description`                 | The board's note on hybrid work (SmartRecruiters)                                         |
| `employment_type`                    | Full-time, part-time, contract… as the board words it                                     |
| `department`, `departments`          | The job's department, and all of them where the board lists several                       |
| `team`                               | The team (Lever, Ashby)                                                                   |
| `offices`                            | The offices the job belongs to (Greenhouse)                                               |
| `experience_level`, `industry`       | Seniority and industry (SmartRecruiters)                                                  |
| `job_function`                       | The job's function (SmartRecruiters)                                                      |
| `education`                          | The education the job asks for, where the board states it (Greenhouse)                    |
| `published_at`                       | When the job was published (on Workday, the day it opened)                                |
| `updated_at`                         | When the job was last changed (Greenhouse)                                                |
| `closes_at`                          | When applications close, where the board says                                             |
| `requisition_id`                     | The employer's own reference for the job                                                  |
| `language`                           | The job's language, where the board states it                                             |
| `salary_text`                        | The pay, as shown. Empty when the board shows none                                        |
| `salary_min`, `salary_max`           | The pay as numbers                                                                        |
| `salary_currency`, `salary_interval` | The pay's currency, and its period                                                        |
| `compensation_tiers`                 | Every pay tier with its parts (salary, equity, bonus), where the board lists them (Ashby) |
| `description_text`                   | The full description, as plain text                                                       |
| `description_html`                   | The full description, with its formatting                                                 |
| `sections`                           | The description's sections with their titles (Lever, SmartRecruiters)                     |
| `custom_fields`                      | The board's own extra fields for the job, by name (Greenhouse, SmartRecruiters)           |
| `recruiter_name`                     | The recruiter, where the board names one (SmartRecruiters)                                |
| `is_listed`                          | `false` for a job the board hides from its list (Ashby)                                   |
| `can_apply`                          | `false` when the job no longer takes applications (Workday)                               |

Which fields are filled depends on the system: each board shows what its
system holds. Pay comes from Ashby and Lever boards that list it; on the
other systems it is often written in the description.

### How much does it cost?

No surcharges and no paid options; an item that fails is not charged.

You pay for what you get:

- **$1 per 1,000 jobs** ($0.001 a job). Each job is charged once per run.
- No start fee, and nothing per board.

So 5,000 jobs cost $5. If you set a maximum cost for a run, the Actor stops
when it reaches it and keeps every job saved so far.

### How long does a run take?

About 150 jobs from five boards in under a minute, and 846 jobs from five
whole boards in 3 minutes. Greenhouse, Lever and Ashby boards are the
quickest; on SmartRecruiters and Workday each job is read on its own, so a
large board takes longer.

### Good to know

- **One job, one row.** A job found again in the same run is saved and
  charged once.
- **The count check.** A board read to its end is set against the count it
  shows (on Lever and Ashby, the jobs it lists); the run's status names any
  board where they differ. A board stopped by your limit is marked as such.
  When a very large Workday site shows no reliable count, the status says no
  count was shown for it.
- **A job closed during the run.** On SmartRecruiters and Workday each job is
  read on its own; a job taken down between the board's list and its own
  page makes the run's status list that board under "Could not read"; its
  other jobs are still saved.
- **The same board twice.** A job is saved once per run, so a board pasted
  twice with different filters counts its shared jobs under the first link.
- **A board that cannot be read** (a wrong link, a company that left the
  system) is reported in the run's status; the other boards carry on. The
  run fails only when none could be read.
- **Running it daily?** Remove repeats by `job_key`; a job that is gone from
  its board is gone from the next run.

### More Actors from us

- [AliExpress Product Scraper: Search Results & Prices](https://apify.com/luzivanlt/aliexpress-products-scraper): Every product of an AliExpress search to its last page, with exact sold counts and ratings.
- [Amazon Product Scraper: Search Results & Prices](https://apify.com/luzivanlt/amazon-products-scraper): Every product on Amazon's search pages to the last page, sponsored marked, with monthly sales.
- [App Store Reviews Scraper: All Reviews, Not 500](https://apify.com/luzivanlt/app-store-reviews-scraper): Every written App Store review of an app, not just the newest 500.
- [Woolworths Coles ALDI Scraper: AU Grocery Prices](https://apify.com/luzivanlt/au-supermarkets-scraper): Woolworths, Coles and ALDI products for any search in one run, every results page to the end.
- [Bilibili Video Scraper: Search & Channel Videos](https://apify.com/luzivanlt/bilibili-videos-scraper): Bilibili videos from searches or whole channels, each with its full detail page's data.
- [Facebook Ads Library Scraper: Meta Ads by Keyword or Page](https://apify.com/luzivanlt/facebook-ads-library-scraper): Meta Ad Library ads by keyword, Page or Ad Library link, with text, images, videos and dates.

### Use it from an AI agent or the API

One call starts a run and returns its items (Apify waits up to 300 seconds; for a
longer run, start it with `POST /v2/acts/…/runs` and read its dataset):

```text
POST https://api.apify.com/v2/acts/luzivanlt~career-site-jobs-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>
```

With the sample input as its JSON body:

```json
{
  "startUrls": [
    {
      "url": "https://job-boards.greenhouse.io/airbnb"
    },
    {
      "url": "https://jobs.lever.co/spotify"
    },
    {
      "url": "https://jobs.ashbyhq.com/ramp"
    },
    {
      "url": "https://jobs.smartrecruiters.com/Canva"
    },
    {
      "url": "https://adobe.wd5.myworkdayjobs.com/external_experienced"
    }
  ],
  "maxJobsPerBoard": 30
}
```

Its inputs, in the order of the input form:

| Input                                  | What it takes                                                                                                                                                                                                                             | Default |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `startUrls` (Career board links)       | Links to companies' job boards on Greenhouse, Lever, Ashby, SmartRecruiters or Workday (myworkdayjobs.com), one board per link, e.g. https://job-boards.greenhouse.io/airbnb or https://adobe.wd5.myworkdayjobs.com/external_experienced. | —       |
| `maxJobsPerBoard` (Max jobs per board) | Stop each board after this many jobs, from 1 to 10,000.                                                                                                                                                                                   | `1000`  |

Apify's MCP server, `https://mcp.apify.com`, lists it as `luzivanlt/career-site-jobs-scraper`. To give an
AI agent this Actor as a tool, add the server to the agent's MCP config:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=luzivanlt/career-site-jobs-scraper"
    }
  }
}
```

The client signs in with OAuth, or add `"headers": { "Authorization": "Bearer <APIFY_TOKEN>" }`.

Charged per job delivered; the sample input above costs at most $0.15.

### FAQ

**Do I need an account or cookies?**
No. The Actor reads the career boards the companies publish for everyone.

**Can it search jobs across all companies by keyword?**
No. It reads the boards you link to, in full. To cover many companies, paste
many links.

**Can I run it from my own code, on a schedule, or with other apps?**
Yes. Like any Apify Actor, you can start it through the Apify API, run it on a
schedule, and connect it to other apps with Apify's integrations and webhooks.

### Is it legal to scrape career sites?

This Actor reads only public job listings that companies publish to attract
applicants. A listing can name a person (a recruiter, a hiring manager);
treat those as personal data. Check each site's terms and the laws that
apply to you (such as the GDPR or the CCPA) before you use the data. If you
are unsure, ask a lawyer.

### Support

Found a problem or missing a feature? Open an issue on the **Issues** tab and
include the run's link.

***

This Actor is not affiliated with, endorsed by or sponsored by Greenhouse,
Lever, Ashby, SmartRecruiters or Workday.

# Changelog

This Actor's version history is a separate document: https://apify.com/luzivanlt/career-site-jobs-scraper/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Links to companies' job boards on Greenhouse, Lever, Ashby, SmartRecruiters or Workday (myworkdayjobs.com), one board per link, e.g. https://job-boards.greenhouse.io/airbnb or https://adobe.wd5.myworkdayjobs.com/external_experienced. A link to one job reads its whole board. A Lever link's location, team, department and commitment filters, and a Workday link's search and filters, are kept. Other sites are refused before anything is read.

## `maxJobsPerBoard` (type: `integer`):

Stop each board after this many jobs, from 1 to 10,000. Default 1,000. Each job is charged once ($1 per 1,000 jobs), so this caps what one board costs: 1,000 jobs cost at most $1. A board read whole is checked against the count the board itself shows. Example: 5000.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://job-boards.greenhouse.io/airbnb"
    },
    {
      "url": "https://jobs.lever.co/spotify"
    },
    {
      "url": "https://jobs.ashbyhq.com/ramp"
    },
    {
      "url": "https://jobs.smartrecruiters.com/Canva"
    },
    {
      "url": "https://adobe.wd5.myworkdayjobs.com/external_experienced"
    }
  ],
  "maxJobsPerBoard": 30
}
```

# Actor output Schema

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

Every job the run saved, one row per job.

## `allFields` (type: `string`):

The same rows with every field.

# 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 = {
    "startUrls": [
        {
            "url": "https://job-boards.greenhouse.io/airbnb"
        },
        {
            "url": "https://jobs.lever.co/spotify"
        },
        {
            "url": "https://jobs.ashbyhq.com/ramp"
        },
        {
            "url": "https://jobs.smartrecruiters.com/Canva"
        },
        {
            "url": "https://adobe.wd5.myworkdayjobs.com/external_experienced"
        }
    ],
    "maxJobsPerBoard": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("luzivanlt/career-site-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 = {
    "startUrls": [
        { "url": "https://job-boards.greenhouse.io/airbnb" },
        { "url": "https://jobs.lever.co/spotify" },
        { "url": "https://jobs.ashbyhq.com/ramp" },
        { "url": "https://jobs.smartrecruiters.com/Canva" },
        { "url": "https://adobe.wd5.myworkdayjobs.com/external_experienced" },
    ],
    "maxJobsPerBoard": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("luzivanlt/career-site-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 '{
  "startUrls": [
    {
      "url": "https://job-boards.greenhouse.io/airbnb"
    },
    {
      "url": "https://jobs.lever.co/spotify"
    },
    {
      "url": "https://jobs.ashbyhq.com/ramp"
    },
    {
      "url": "https://jobs.smartrecruiters.com/Canva"
    },
    {
      "url": "https://adobe.wd5.myworkdayjobs.com/external_experienced"
    }
  ],
  "maxJobsPerBoard": 30
}' |
apify call luzivanlt/career-site-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,luzivanlt/career-site-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/cjpwhd06350vZHxX0/builds/7406CuRpHwpbecK6F/openapi.json
