# Greenhouse Job Board Scraper – Salaries (`chain_link/greenhouse-job-board-scraper`) Actor

Extract every open job from any company's Greenhouse board through the public Job Board API. Accepts tokens or careers URLs, supports keyword, location, department and updated-since filters, and parses salary ranges. $1 per 1,000 jobs.

- **URL**: https://apify.com/chain_link/greenhouse-job-board-scraper.md
- **Developed by:** [James White](https://apify.com/chain_link) (community)
- **Categories:** Jobs
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 job scrapeds

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

## Greenhouse Job Board Scraper \u2013 Salaries

Collect every open job from any company that hires through Greenhouse. Give it a company's board token (for example `airbnb`) or simply paste their Greenhouse careers link, and you get a clean table of jobs with titles, locations, departments, offices, links, dates, full descriptions and, where the posting shows one, a parsed salary range.

The data comes from Greenhouse's public, documented Job Board API, the same source that powers companies' own careers pages. There is no fragile page scraping, so results are consistent run after run.

### Price

**$1 per 1,000 jobs** ($0.001 per job saved). Filters are applied *before* a job is saved, so you only pay for the jobs that match what you asked for.

### Typical uses

- Track hiring at competitors, customers or prospects
- Build job boards or niche job newsletters
- Salary benchmarking from pay-transparency ranges
- Daily monitoring of new or changed postings with the "Updated since" option
- Recruiting and sales-intelligence research

### Inputs

| Input | What it does |
|---|---|
| **Board tokens or careers URLs** (`boardTokens`, required) | A list of companies. Enter either the Greenhouse board token (e.g. `airbnb`, `stripe`) or a Greenhouse careers link such as `https://boards.greenhouse.io/stripe`, `https://job-boards.greenhouse.io/stripe` or an embed link containing `?for=stripe`. The token is detected automatically. |
| **Title keywords** (`keywords`) | Keep only jobs whose title contains any of these words (not case-sensitive). Leave empty for all jobs. |
| **Location filter** (`locations`) | Keep only jobs whose location or office contains any of these words, e.g. `London` or `Remote`. |
| **Department filter** (`departments`) | Keep only jobs in departments whose name contains any of these words, e.g. `Engineering`. |
| **Remote only** (`remoteOnly`) | Return only jobs detected as remote (see Limits). Default: off. |
| **Updated since** (`updatedSince`) | Return only jobs updated on or after this date, e.g. `2024-06-01`. Ideal for cheap daily runs. |
| **Include description** (`includeDescription`) | Include the full job description as HTML and plain text. Default: on. Salary is parsed either way. |
| **Max jobs** (`maxItems`) | The most jobs to return across all boards. Default: 1000. The run stops as soon as this number is reached. |

### Example input

```json
{
  "boardTokens": ["airbnb", "https://boards.greenhouse.io/stripe"],
  "keywords": ["manager", "engineer"],
  "locations": [],
  "departments": [],
  "remoteOnly": false,
  "updatedSince": "2024-06-01",
  "includeDescription": true,
  "maxItems": 100
}
```

### Output fields

| Field | Description |
|---|---|
| `boardToken` | Greenhouse board token of the company |
| `companyName` | Company name |
| `jobId` | Greenhouse job ID |
| `title` | Job title |
| `location` | Location as posted |
| `isRemote` | `true` if the job looks remote (based on location, offices, title and workplace-type info) |
| `departments` | Department names |
| `offices` | Office names and locations |
| `absoluteUrl` | Link to the public job posting |
| `updatedAt` | When the posting was last updated |
| `firstPublished` | When the posting was first published, if provided |
| `requisitionId` | The company's internal requisition ID, if provided |
| `descriptionHtml` | Full description in HTML (when descriptions are included) |
| `descriptionText` | Full description as plain text (when descriptions are included) |
| `salaryMin` | Lowest salary in the posted range, if one was found |
| `salaryMax` | Highest salary in the posted range, if one was found |
| `salaryCurrency` | Currency code of the salary, e.g. `GBP` |
| `scrapedAt` | When the job was collected |

### Example output row

```json
{
  "boardToken": "airbnb",
  "companyName": "Airbnb",
  "jobId": 8184174,
  "title": "Account Manager",
  "location": "London, United Kingdom",
  "isRemote": false,
  "departments": ["Business Development"],
  "offices": [{"name": "London, United Kingdom", "location": "London, United Kingdom"}],
  "absoluteUrl": "https://careers.airbnb.com/positions/8184174?gh_jid=8184174",
  "updatedAt": "2026-09-29T20:00:54-04:00",
  "firstPublished": "2026-09-09T04:35:19-04:00",
  "requisitionId": "MULTI",
  "descriptionHtml": "<div class=\"content-intro\"><p>Airbnb was born in 2007 ...</p></div>",
  "descriptionText": "Airbnb was born in 2007 ...",
  "salaryMin": 46000,
  "salaryMax": 54000,
  "salaryCurrency": "GBP",
  "scrapedAt": "2026-10-08T12:00:00+00:00"
}
```

### Privacy

The tool collects job postings only. Any email addresses that appear inside job descriptions (such as recruiter contact addresses) are replaced with `[email removed]` before the data is saved.

### Limits

- Only jobs a company has published on its Greenhouse board are available. Companies that do not use Greenhouse, or that have no public board, return nothing.
- Salary fields are filled only when the posting states a range with a currency. Single figures, hourly vs. annual distinctions and complex multi-region ranges may not be captured; when a posting lists several ranges, the first one found is returned.
- The remote flag is a best-effort guess based on words like "Remote" or "Anywhere" in the location, offices, title or workplace-type fields.
- Filters use simple "contains" matching on the text the company published.
- If Greenhouse refuses requests or rate-limits the tool, the run stops and logs the reason instead of retrying indefinitely.

### Terms

This tool reads Greenhouse's public Job Board API, which is intended for displaying published job posts. You are responsible for using the data in line with applicable laws and the terms of Greenhouse and of the companies whose jobs you collect. Job content remains the property of the respective employers.

# Actor input Schema

## `boardTokens` (type: `array`):

Greenhouse board tokens (e.g. 'airbnb') or any Greenhouse careers URL; the token is extracted automatically.

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

Keep only jobs whose title contains any of these keywords (case-insensitive). Leave empty for all.

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

Keep only jobs whose location contains any of these strings (e.g. 'Remote', 'London').

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

Keep only jobs in departments whose name contains any of these strings.

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

Return only jobs detected as remote.

## `updatedSince` (type: `string`):

Return only jobs updated on or after this date, e.g. 2024-06-01, for incremental monitoring.

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

Include the full job description as HTML and plain text, and use it for salary parsing.

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

Maximum number of jobs to return across all boards.

## Actor input object example

```json
{
  "boardTokens": [
    "airbnb"
  ],
  "keywords": [],
  "locations": [],
  "departments": [],
  "remoteOnly": false,
  "updatedSince": "",
  "includeDescription": true,
  "maxItems": 1000
}
```

# Actor output Schema

## `results` (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 = {
    "boardTokens": [
        "airbnb"
    ],
    "keywords": [],
    "locations": [],
    "departments": [],
    "remoteOnly": false,
    "updatedSince": "",
    "includeDescription": true,
    "maxItems": 1000
};

// Run the Actor and wait for it to finish
const run = await client.actor("chain_link/greenhouse-job-board-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 = {
    "boardTokens": ["airbnb"],
    "keywords": [],
    "locations": [],
    "departments": [],
    "remoteOnly": False,
    "updatedSince": "",
    "includeDescription": True,
    "maxItems": 1000,
}

# Run the Actor and wait for it to finish
run = client.actor("chain_link/greenhouse-job-board-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 '{
  "boardTokens": [
    "airbnb"
  ],
  "keywords": [],
  "locations": [],
  "departments": [],
  "remoteOnly": false,
  "updatedSince": "",
  "includeDescription": true,
  "maxItems": 1000
}' |
apify call chain_link/greenhouse-job-board-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chain_link/greenhouse-job-board-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/dk1icTY5xdbwlttsT/builds/9Id34h0m2sq3EIsnS/openapi.json
