# Greenhouse, Lever & Ashby Jobs Scraper (`steadyscrape/greenhouse-lever-ashby-jobs-scraper`) Actor

Scrape every open job from Greenhouse, Lever and Ashby job boards by company (board link, careers page, domain or name) or search a directory of 10,000+ company boards by title and location. Salary, remote, department, posted date, apply link. Export to JSON, CSV or Excel, or via API.

- **URL**: https://apify.com/steadyscrape/greenhouse-lever-ashby-jobs-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Jobs, Lead generation
- **Features:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 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.

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

## Greenhouse, Lever & Ashby Jobs Scraper

Scrape **every open job from Greenhouse, Lever and Ashby job boards**, straight from the employer. This Greenhouse jobs
scraper, Lever jobs scraper and Ashby jobs scraper reads the boards of the tens of thousands of startups and tech
companies hiring on those three applicant tracking systems (ATS), one row per job: **company**, **title**, **department
and team**, **locations**, **remote / hybrid / on-site**, **employment type**, **salary range with currency and period**
where the employer publishes it, **posted date**, the **direct apply link** and the **full description** as text and HTML.

Two ways to use it:

- **By company**: give board links (`job-boards.greenhouse.io/airbnb`, `jobs.lever.co/palantir`, `jobs.ashbyhq.com/ramp`),
  job links, careers pages, domains (`ramp.com`) or just names (`Palantir Technologies`). A name or domain is looked up in
  the **bundled directory of 10,000+ Greenhouse, Lever and Ashby boards**, so it lands on the company's exact board
  instead of a guessed slug.
- **Across companies**: turn on **Search the directory** and get every job matching a **title keyword** and a **location**
  (or remote, or a department) across up to 1,000 company boards — no company list needed.

Filter by title keywords, excluded words, location, remote, department and posting date, and schedule it with **only new
jobs** to get each new opening once. Export to JSON, CSV or Excel, or read it through the Apify API.

### What you can do with this Greenhouse, Lever and Ashby jobs scraper

- **Find jobs across startups**: "product designer" in "Berlin", "machine learning" and remote, "account executive" in
  "London" — read straight from the employers' Greenhouse, Lever and Ashby boards, with the employer's own apply link.
- **Build a job board or a job feed** from employers' own postings, refreshed daily with *only new jobs*.
- **Track hiring at target companies**: which teams are hiring, where and how fast — for sales prospecting, investing,
  competitive intelligence or recruiting.
- **Salary research**: Greenhouse pay ranges, Ashby compensation and Lever salary ranges, with currency and period.
- **Feed an AI agent or a spreadsheet** with clean, uniform job data from the three ATSs startups use most.

Using Workday, Recruitee, Personio, BambooHR or Breezy too? [Career Site Jobs Scraper](https://apify.com/steadyscrape/career-site-jobs-scraper)
reads all eight ATSs with the same output. Looking for jobs by search query on Google instead?
[Google Jobs Scraper](https://apify.com/steadyscrape/google-jobs-scraper).

### Input

| Field | What it does |
| --- | --- |
| **Companies** | One per line: a Greenhouse, Lever or Ashby board or job link, a careers page, a domain or a company name. Leave empty to search the directory. |
| **Max jobs per company** | Stop each company (or each directory board) after this many jobs, newest first (0 = every open job). |
| **Search the directory of companies** | Also read the directory's boards that can match your filters, largest first. |
| **Platforms to search** | Greenhouse, Lever, Ashby, or any of them (empty = all three). |
| **Max companies to search** | How many directory boards one search reads (1–1,000, default 100). |
| **Title keywords** / **Exclude title keywords** | Keep jobs whose title has a word starting with one of these; drop those with an excluded one. |
| **Location contains** | Keep jobs with a location or country containing one of these (`London`, `Germany`, `Remote`). |
| **Remote only** | Keep jobs the board marks remote, or whose locations say Remote. |
| **Department contains** | Keep jobs whose department or team contains one of these. |
| **Posted within (days)** | Keep jobs posted in the last N days. |
| **Only jobs not seen before** | Monitoring: skip jobs an earlier run with the same companies, search and filters delivered. |

Jobs at named companies:

```json
{
    "companies": ["https://job-boards.greenhouse.io/airbnb", "https://jobs.lever.co/palantir", "Ramp", "notion.com"],
    "titleKeywords": ["engineer"],
    "remoteOnly": true,
    "maxJobsPerCompany": 50
}
```

A search across the directory — every engineering job in San Francisco on up to 200 boards:

```json
{
    "searchDirectory": true,
    "titleKeywords": ["software engineer", "data engineer"],
    "locations": ["San Francisco"],
    "maxCompanies": 200,
    "maxJobsPerCompany": 20
}
```

#### How a company is found

- **A board or job link** of Greenhouse (`boards.`, `job-boards.` and `.eu.` hosts, embeds), Lever (`jobs.lever.co`,
  `jobs.eu.lever.co`) or Ashby (`jobs.ashbyhq.com`) is read directly — the surest way.
- **A company name** is looked up in the directory by the name the board publishes (Greenhouse's board name, Lever's page
  title, Ashby's organization) or by its slug; legal words are ignored ("Ramp, Inc." finds Ramp) but the whole name must
  match ("Ramp Network" does not get Ramp). A name the directory does not know is tried as a board slug on the three ATSs.
- **A domain** is looked up by the company website the board links (Ashby), then by its label (`figma.com` → Figma);
  otherwise it is tried as a slug and then read as a website for the board it links.
- **A careers page** is read for the Greenhouse, Lever or Ashby link or embed it carries.
- The row's `resolvedBy` says how: `board_link`, `directory`, `directory_search`, `careers_page` or `name_guess`.

#### How the directory search works

The directory was built from the public web (the Common Crawl URL index of the three ATSs' board hosts), and each board
was read once to keep its company name, its number of open jobs and the words of its job titles, places and departments.
A search keeps the boards whose words can match your title keywords, locations, departments and remote filter, reads the
largest of them live (up to **Max companies to search**), and applies your filters to every job. Jobs posted since the
directory was built are found, because every board is read live; a company that started hiring for a new title or place
since then can be missed by the narrowing. Boards are read round-robin over Greenhouse, Lever and Ashby, at each host's pace
(Lever asks crawlers for one request a second).

A search's time goes with the jobs on the boards it reads. Measured on 512 MB, a run read about 135 a second on the
largest boards: "designer" in "Berlin" (100 boards, ~22,000 jobs) takes about 3 minutes, "software engineer" (the 100
largest of 3,100 boards, ~57,000 jobs) about 7, and the 100 largest boards with no filter (~89,000 jobs) about 11. The
default run memory is 1,024 MB, and Apify gives a run twice the CPU of a 512 MB one. The log says how far it got every 10 boards.

### Output: Greenhouse, Lever and Ashby jobs data

```json
{
    "rowType": "job",
    "status": "ok",
    "input": "https://jobs.ashbyhq.com/ramp",
    "resolvedBy": "board_link",
    "companyName": "Ramp",
    "ats": "ashby",
    "boardSlug": "ramp",
    "boardUrl": "https://jobs.ashbyhq.com/ramp",
    "jobId": "f9d015d7-d5cb-450b-9936-afd8d1c4f4cc",
    "requisitionId": null,
    "title": "Manager, Account Executive, Strategic",
    "department": "Sales",
    "team": "Account Executive",
    "location": "Remote (US)",
    "locations": ["Remote (US)", "San Francisco, CA", "New York, NY (HQ)"],
    "country": "United States",
    "remote": true,
    "workplaceType": "remote",
    "employmentType": "full_time",
    "employmentTypeText": "FullTime",
    "salaryMin": 520000,
    "salaryMax": 620000,
    "salaryCurrency": "USD",
    "salaryPeriod": "year",
    "salaryText": "$520K - $620K",
    "postedAt": "2026-11-07T02:57:03.574Z",
    "updatedAt": null,
    "url": "https://jobs.ashbyhq.com/ramp/f9d015d7-d5cb-450b-9936-afd8d1c4f4cc",
    "applyUrl": "https://jobs.ashbyhq.com/ramp/f9d015d7-d5cb-450b-9936-afd8d1c4f4cc/application",
    "description": "About Ramp\nRamp is building the smart infrastructure for finance teams, embedded in the tr…",
    "descriptionHtml": "<h1><strong>About Ramp</strong></h1><p style=\"min-height:1.5em\">Ramp i…",
    "position": 1,
    "scrapedAt": "2026-11-08T07:57:58.941Z"
}
```

A company that gives no job gets one **free** row saying why (a directory search that finds nothing gets one, too):

```json
{
    "rowType": "status",
    "status": "invalid_input",
    "input": "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "ats": null,
    "url": null,
    "reason": "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite is a Workday board; this Actor reads Greenhouse, Lever and Ashby. Career Site Jobs Scraper (steadyscrape/career-site-jobs-scraper) reads Workday too.",
    "scrapedAt": "2026-11-08T10:00:00.000Z"
}
```

### Greenhouse, Lever and Ashby job fields

| Field | Description |
| --- | --- |
| `companyName` | The name the board publishes (Greenhouse); otherwise the board slug in Title Case (Lever, Ashby). |
| `ats` | `greenhouse`, `lever` or `ashby`. |
| `boardSlug`, `boardUrl` | The company's id on its ATS and its job board. |
| `jobId`, `requisitionId` | The job's id on the board; the requisition id where Greenhouse publishes it. |
| `title`, `department`, `team` | As the board names them. |
| `location`, `locations`, `country` | The primary location, every location, and the country where the board states it. |
| `remote`, `workplaceType` | `true`/`false`/`null`; `remote`, `hybrid`, `onsite` or `null`. |
| `employmentType`, `employmentTypeText` | `full_time`, `part_time`, `contract`, `temporary`, `internship` or `null`, and the board's own words. |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryText` | The pay range when the board publishes it. |
| `postedAt`, `updatedAt` | ISO 8601 UTC. |
| `url`, `applyUrl` | The job page and the direct application link. |
| `description`, `descriptionHtml` | The full description as text and as HTML. |
| `input`, `resolvedBy` | The company as you wrote it (the board link for a directory search), and how its board was found. |
| `position`, `scrapedAt` | The job's place in its company's results, and when it was read. |
| `rowType`, `status`, `reason` | `job`/`ok`, or `status` with `invalid_input`, `not_found`, `no_ats_detected`, `no_open_jobs`, `no_matching_jobs` or `blocked` and the reason. |

### Pricing

Pay per event: **US$0.0015 per job** delivered, description, salary and apply link included, whether the company was
named or found by a directory search. Status rows (company not found, another ATS, no open jobs, nothing matching the
filters, invalid input, blocked) are **free**, boards a search reads without a match cost nothing, and there is no start
fee. 1,000 jobs cost US$1.50. Set a maximum cost per run and the Actor stops exactly there.

### Limits

- Greenhouse, Lever and Ashby only: a Workday, Recruitee, Personio, BambooHR or Breezy board gets a free row pointing to
  [Career Site Jobs Scraper](https://apify.com/steadyscrape/career-site-jobs-scraper), which reads them.
- The directory holds the boards the public web crawls had met; a company missing from it is still read from its board
  link, careers page or domain. Its counts and words date from when it was built (see `directoryBuiltAt` in the run's
  SUMMARY record).
- Salaries come only where the employer publishes them: Greenhouse on boards with pay transparency, Ashby and Lever where set.
- Lever asks crawlers to wait a second between requests, so a search of many Lever boards takes longer than one of
  Greenhouse or Ashby boards.

### Is it legal to scrape Greenhouse, Lever and Ashby jobs?

Job postings are published by employers to be found and applied to, and this Actor reads them through the public
job-board APIs the three vendors run to put those postings on career sites (Greenhouse's Job Board API, Lever's Postings
API, Ashby's posting API). No login, no personal data of candidates, robots.txt honoured on every host, and each host paced
(Lever's crawl delay included). Check that your use of the data complies with the laws that apply to you and with the
employers' terms.

This Actor is not affiliated with, endorsed by or sponsored by Greenhouse Software, Lever, Ashby or any employer whose jobs
it reads; their names are used only to say which job boards it reads.

# Actor input Schema

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

One company per line, in any of these forms: its job board link (<code>https://job-boards.greenhouse.io/airbnb</code>, <code>https://jobs.lever.co/palantir</code>, <code>https://jobs.ashbyhq.com/ramp</code>) or any job link of it; the company's careers page (<code>https://www.notion.com/careers</code>), read for the Greenhouse, Lever or Ashby link or embed it carries; a domain (<code>figma.com</code>); or a company name (<code>Palantir Technologies</code>), looked up in the bundled directory of boards first and then tried as a board slug. Leave empty to search the directory instead.

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

Stop each company after this many jobs (newest first where the board dates them). 0 means every open job.

## `searchDirectory` (type: `boolean`):

Also read the boards of companies in the bundled directory of Greenhouse, Lever and Ashby boards (built from public web crawls), keeping the jobs that pass the filters below. The directory is narrowed first by what each board listed when it was built: with <code>titleKeywords</code> or <code>locations</code> set, only boards that had such titles or places are read, the largest first.

## `platforms` (type: `array`):

Which ATSs the directory search reads. Leave empty for all three.

## `maxCompanies` (type: `integer`):

How many directory boards one search reads, largest first, at most 1000. Each board is one request. Measured on 512 MB, a run read about 135 of their jobs a second (the 100 largest boards in about 11 minutes, 100 boards matching a title and a city in a few); the default 1,024 MB has twice that CPU.

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

Keep only jobs whose title has one of these words or phrases at the start of a word, case and accents ignored: <code>engineer</code> finds "Software Engineering Manager", <code>AI</code> finds "AI Researcher" but not "Maintenance". Leave empty to keep every title.

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

Drop jobs whose title has one of these, e.g. <code>senior</code>, <code>intern</code>, <code>manager</code>.

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

Keep only jobs with a location (or country) containing one of these, e.g. <code>London</code>, <code>Germany</code>, <code>Remote</code>, <code>NY</code>.

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

Keep only jobs the board marks remote (or whose locations say Remote).

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

Keep only jobs whose department or team contains one of these, e.g. <code>engineering</code>, <code>sales</code>.

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

Keep only jobs posted in the last N days. 0 means any date. A board that publishes no date for a job leaves it out when this is set.

## `onlyNewJobs` (type: `boolean`):

Return only jobs no earlier run with the same companies, search and filters delivered: schedule the Actor daily to get each new opening once. The memory lives in your account's key-value store <code>steadyscrape-greenhouse-lever-ashby-jobs-state</code>.

## Actor input object example

```json
{
  "companies": [
    "https://job-boards.greenhouse.io/airbnb",
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/ramp"
  ],
  "maxJobsPerCompany": 5,
  "searchDirectory": false,
  "platforms": [],
  "maxCompanies": 100,
  "titleKeywords": [],
  "excludeTitleKeywords": [],
  "locations": [],
  "remoteOnly": false,
  "departments": [],
  "postedWithinDays": 0,
  "onlyNewJobs": false
}
```

# Actor output Schema

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

No description

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

No description

# 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://job-boards.greenhouse.io/airbnb",
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/ramp"
    ],
    "maxJobsPerCompany": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/greenhouse-lever-ashby-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://job-boards.greenhouse.io/airbnb",
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/ramp",
    ],
    "maxJobsPerCompany": 5,
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/greenhouse-lever-ashby-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/hVUnkc6ydG6uRWPxj/builds/hg39TSpKZ4G7FcIKB/openapi.json
