# Greenhouse Jobs Scraper & API: Salary, Remote (`data_factory_nerd/greenhouse-jobs-scraper`) Actor

Extract all open jobs from any company's Greenhouse careers page: title, location, salary range, remote flag, department, posted date and full description. Filter by keyword, location, remote and date. Official public board API: no login, no API key. $1.50 per 1,000 jobs.

- **URL**: https://apify.com/data_factory_nerd/greenhouse-jobs-scraper.md
- **Developed by:** [Joe Pena](https://apify.com/data_factory_nerd) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.35 / 1,000 results

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

### What is Greenhouse Jobs Scraper?

**Greenhouse Jobs Scraper** extracts **every open job from any company's Greenhouse careers page** (boards.greenhouse.io and job-boards.greenhouse.io) into clean JSON, CSV or Excel. For each job you get the title, location, remote flag, **salary range**, department, office, posted date, apply URL and the full plain-text job description.

Paste one or more company names (Greenhouse board slugs such as `airbnb` or `stripe`) or careers-page URLs, click **Start**, and download the data a few seconds later. It reads Greenhouse's official public Job Board API, the same feed that powers each company's careers page. So there's **no login, no API key, no proxies and no browser**, and runs are fast and cheap.

Need Lever, Ashby, Workable, Recruitee or SmartRecruiters too? See the [Multi-ATS Jobs Scraper](https://apify.com/data_factory_nerd/ats-jobs-scraper).

### What data can you extract from Greenhouse?

| Field | Example |
|---|---|
| `title` | Senior Machine Learning Engineer, Relevance |
| `company` | Airbnb |
| `location` | United States |
| `isRemote` | false |
| `salaryMin` / `salaryMax` / `salaryCurrency` / `salaryInterval` | 200000 / 235000 / USD / year |
| `departments` / `offices` | \["Engineering"] / \["United States"] |
| `postedAt` / `updatedAt` | 2026-11-04T17:21:08+00:00 |
| `url` | Direct link to the job posting |
| `description` | Full job description as plain text (HTML removed) |

Also included: `jobId`, `companySlug`, `ats`, `workplaceType`, `employmentType`, `salarySource`, `requisitionId`, `scrapedAt`.

### Greenhouse Jobs Scraper features

- 🏢 **Many companies in one run**: slugs, `boards.greenhouse.io` URLs, `job-boards.greenhouse.io` URLs or embed URLs with `?for=company`
- 🔎 **Filters**: title keywords, excluded words, location, remote only, posted within the last N days, max jobs per company
- 💰 **Salary data**: the pay-transparency range is parsed into min, max, currency and interval
- 🧾 **LLM-ready text**: clean plain-text descriptions for AI pipelines, search indexes and embeddings
- ⚠️ **No silent failures**: a `SUMMARY` record in the key-value store lists every company and whether its board was found
- 🔔 **Monitor mode**: return only jobs that are new since the last run, perfect for scheduled daily alerts
- 🔁 **Apify platform built in**: scheduling, API access, webhooks, and integrations with Google Sheets, Slack, Make, Zapier and more

### How to scrape Greenhouse jobs

1. Open the **Input** tab and add companies. The slug is the last part of the careers URL, e.g. `https://job-boards.greenhouse.io/`**`stripe`**.
2. Optionally add title keywords (`engineer`, `data`), locations (`New York`, `Remote`) or **Posted within last N days**.
3. Click **Start**.
4. Download the results from the **Output** tab as JSON, CSV, Excel or HTML, or read them through the Apify API.

#### Input example

```json
{
  "companies": ["airbnb", "https://job-boards.greenhouse.io/stripe", "discord"],
  "keywords": ["engineer"],
  "locations": ["United States", "Remote"],
  "postedWithinDays": 14,
  "maxItems": 500
}
```

#### Output example

```json
{
  "jobId": "8374537",
  "title": "Senior Security Engineer, Threat Detection & Incident Response",
  "company": "Airbnb",
  "companySlug": "airbnb",
  "ats": "greenhouse",
  "url": "https://careers.airbnb.com/positions/8374537?gh_jid=8374537",
  "location": "London, United Kingdom",
  "isRemote": false,
  "departments": [
    "Security"
  ],
  "postedAt": "2026-11-10T21:34:40+00:00",
  "salaryMin": 96000.0,
  "salaryMax": 120000.0,
  "salaryCurrency": "GBP",
  "salaryInterval": "year",
  "salarySource": "parsed_from_description",
  "description": "Airbnb was born in 2007 when two hosts welcomed three guests..."
}
```

### Monitor mode: only new jobs since the last run

Turn on **Only new jobs since last run** (`onlyNew: true`) and the Actor remembers every job it has returned for that search. The next run returns only jobs it hasn't returned before, so you pay only for new results.

- The first run returns everything that currently matches and saves it as the baseline.
- Seen IDs are stored in a named key-value store in **your** Apify account (`data-factory-greenhouse-monitor`), one record per search. The record name comes from your search filters, so different searches keep separate histories.
- Want to keep one history while you adjust filters? Set **Monitor name** (`monitorKey`), e.g. `"daily-alert"`.
- To start over, delete that record (or the whole store) in **Storage → Key-value stores**.

#### Schedule it for daily alerts

1. Configure your search, turn on **Only new jobs since last run**, and save it as a task.
2. Create an Apify Schedule for that task (daily or hourly).
3. Add an integration (Slack, email, Google Sheets, Zapier, Make or a webhook) to push each run's new jobs where your team works.

```json
{ "companies": ["stripe", "airbnb", "databricks"], "keywords": ["engineer"], "onlyNew": true, "maxItems": 500 }
```

### How much does it cost to scrape Greenhouse jobs?

This Actor uses **pay-per-result** pricing: **$1.50 per 1,000 jobs** ($0.0015 per job). You only pay for jobs saved to your dataset. Companies with no matching jobs cost nothing.

- 1,000 Greenhouse jobs = $1.50
- 10,000 Greenhouse jobs = $15
- Apify's free plan includes $5 of monthly usage, which covers roughly 3,000 jobs with this Actor.

Use **Max jobs in total** to cap the cost of any run.

### Use cases for Greenhouse job data

- **Job boards and job aggregators**: ingest thousands of tech jobs every day
- **Sales prospecting**: companies hiring for a role are showing a buying signal
- **Salary benchmarking** from pay-transparency ranges
- **Competitive intelligence**: track hiring by department and location at competitors
- **Job alerts**: schedule a daily run with **Posted within last N days = 1** and send new jobs to Slack or email

### Greenhouse API and integrations

You can run the Greenhouse Jobs Scraper from your own code with the [Apify API](https://docs.apify.com/api/v2) or the Python and JavaScript clients:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("data_factory_nerd/greenhouse-jobs-scraper").call(
    run_input={"companies": ["airbnb", "stripe"], "keywords": ["engineer"], "maxItems": 200}
)
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["location"], job["salaryMin"])
```

### FAQ

#### Is it legal to scrape Greenhouse jobs?

This Actor only reads job postings that companies publish publicly through Greenhouse's public Job Board API. It doesn't log in and doesn't collect personal data about candidates. Always use the data in line with the laws that apply to you.

#### Why is a company "not found"?

The company may not use Greenhouse, or it uses a different board slug. Open the company's careers page, copy its URL into the input, and check the `SUMMARY` record after the run.

#### Can I get only new Greenhouse jobs every day?

Yes. Turn on **Only new jobs since last run** and schedule the Actor daily (see **Monitor mode** above). Each run returns only jobs you haven't seen before.

#### Does it return salaries?

When a company publishes a pay range in the job post (common in US pay-transparency states), it is parsed into `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryInterval`. Otherwise these fields are empty.

#### Found a bug or need a field?

Open an issue on the **Issues** tab. We monitor it and reply quickly.

### Related Actors by data_factory_nerd

| Actor | What it does |
|---|---|
| [Multi-ATS Jobs Scraper](https://apify.com/data_factory_nerd/ats-jobs-scraper) | Greenhouse, Lever, Ashby, Workable, Recruitee and SmartRecruiters jobs in one unified dataset |
| [SAM.gov Contract Opportunities Scraper](https://apify.com/data_factory_nerd/sam-gov-contract-opportunities) | US federal contract opportunities with NAICS, set-aside, deadlines and contacts |

# Actor input Schema

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

Greenhouse board token (e.g. airbnb, stripe) or any Greenhouse careers URL such as https://boards.greenhouse.io/airbnb, https://job-boards.greenhouse.io/stripe or an embed URL with ?for=slug.

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

Keep jobs whose title contains ANY of these words (case-insensitive). Leave empty for all jobs.

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

Drop jobs whose title contains any of these words, e.g. intern, senior.

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

Keep jobs whose location contains ANY of these strings, e.g. 'New York', 'Germany', 'Remote'.

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

Keep only jobs flagged remote by the ATS or with 'remote' in title/location.

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

Keep only jobs first published within this many days. Empty = any date.

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

Adds the plain-text description and parses salary ranges from it.

## `maxItemsPerCompany` (type: `integer`):

0 = no limit. Newest jobs are kept first.

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

Stop after this many jobs (controls cost). 0 = no limit.

## `onlyNew` (type: `boolean`):

Return only jobs not returned by a previous run of this same search. Seen job IDs are stored in a named key-value store in your account. The first run returns everything and remembers it. Ideal with Apify Schedules for daily new-job alerts.

## `monitorKey` (type: `string`):

Optional name for this monitor's memory. By default it is derived from your search (companies + filters), so changing the search starts a fresh history. Set a name to keep one history while you tweak filters.

## `maxConcurrency` (type: `integer`):

Polite default. Raise only for very large company lists.

## Actor input object example

```json
{
  "companies": [
    "airbnb",
    "https://job-boards.greenhouse.io/stripe"
  ],
  "keywords": [],
  "remoteOnly": false,
  "includeDescription": true,
  "maxItemsPerCompany": 25,
  "maxItems": 50,
  "onlyNew": false,
  "maxConcurrency": 6
}
```

# 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": [
        "airbnb",
        "https://job-boards.greenhouse.io/stripe"
    ],
    "keywords": [],
    "maxItemsPerCompany": 25,
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("data_factory_nerd/greenhouse-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": [
        "airbnb",
        "https://job-boards.greenhouse.io/stripe",
    ],
    "keywords": [],
    "maxItemsPerCompany": 25,
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("data_factory_nerd/greenhouse-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": [
    "airbnb",
    "https://job-boards.greenhouse.io/stripe"
  ],
  "keywords": [],
  "maxItemsPerCompany": 25,
  "maxItems": 50
}' |
apify call data_factory_nerd/greenhouse-jobs-scraper --silent --output-dataset

```

## MCP server setup

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