# Greenhouse Jobs Scraper – Job Board API with Salaries (`chris_elder/greenhouse-jobs-scraper`) Actor

Scrape open jobs from any Greenhouse job board: title, location, department, remote/hybrid, salary range, description, application questions and apply link. Paste board slugs, Greenhouse links or careers pages. Only-new-jobs mode for alerts. $1.70 per 1,000 jobs; failed boards free.

- **URL**: https://apify.com/chris_elder/greenhouse-jobs-scraper.md
- **Developed by:** [Chris Elder](https://apify.com/chris_elder) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 job listeds

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 Jobs Scraper: Job Board API with Salaries

**Pull every open job from any company that hires through Greenhouse, as clean rows with location, department, remote flag, apply link and the published salary range. $1.70 per 1,000 jobs, failed boards free.**

[▶ Try it with one click](#how-to-use-it) · [📄 Real example output](#output-example-from-a-real-public-run) · [💲 Pricing](#how-much-does-it-cost-to-scrape-greenhouse-jobs) · [🔌 API & integrations](#integrations-api-ai-agents-make-zapier) · [❓ FAQ](#faq) · [🛟 Support](#support-reliability-and-feature-requests)

### What does Greenhouse Jobs Scraper do?

- 🏢 **Any Greenhouse company, many at once**: give board slugs (`gitlab`), Greenhouse links (`job-boards.greenhouse.io/figma`, `boards.greenhouse.io/embed/job_board?for=stripe`) or a careers page URL and it finds the board for you
- 💰 **Salary ranges**: reads the pay transparency range the employer publishes (min, max, currency, period), with a fallback that picks up ranges written in the job text
- 🌍 **Remote and hybrid flags**: `workplaceType` is set to `remote` or `hybrid` when the location or title says so
- 🔎 **Filters that cost nothing**: keywords, exclude words, locations, departments, remote only and posted within N days. You pay only for jobs you keep
- 🔔 **New job alerts**: **Only new jobs** remembers what you have already received, so a daily schedule returns just the fresh postings (already-seen jobs are free)
- 📝 **Full descriptions and application questions** on request (plain text and HTML; question labels, types and options)
- 📦 **Export** to JSON, CSV, Excel, Google Sheets or straight into your app through the API

It uses the official public Greenhouse Job Board API, the same feed that powers each company's own careers page. No login, no proxies, no browser.

### Use cases

- **Job boards and aggregators**: keep a niche board (remote, climate, AI, fintech) filled with fresh roles from hundreds of companies
- **Recruiters and talent teams**: watch target companies and get only the new openings each morning
- **Job seekers**: one sheet of every matching role across your dream companies, with salaries side by side
- **Market and salary research**: compare published pay ranges by role, location and company
- **Sales intelligence**: hiring signals (a company opening 20 data roles is buying data tools)
- **AI agents**: give an assistant live, structured job data through MCP

### How to use it

1. Click **Try for free** and keep the prefilled input (GitLab and Figma, 10 jobs each).
2. Replace the companies with your own list: one slug, Greenhouse link or careers page per line.
3. Add filters if you want (keywords, locations, remote only, posted within days).
4. Tick **Include salary** for pay transparency ranges, and **Include description** for full text.
5. Click **Start**, then download the results or connect them to your tools.

Not sure of the slug? It is the last part of the company's Greenhouse link, e.g. `job-boards.greenhouse.io/`**`figma`**. Or just paste the careers page and let the Actor find it.

#### Input example

```json
{
  "companies": ["gitlab", "figma", "https://job-boards.greenhouse.io/stripe"],
  "keywords": ["engineer", "data"],
  "excludeKeywords": ["intern"],
  "locations": ["United Kingdom", "Remote"],
  "postedWithinDays": 30,
  "includeSalary": true,
  "includeDescription": false,
  "onlyNewJobs": false
}
```

### Output example (from a real public run)

A row from the [public example run](https://console.apify.com/view/runs/Fla1tDCWuSCu31GK9) (20 jobs from GitLab and Figma, 26 Oct 2026):

```json
{
  "company": "GitLab",
  "board": "gitlab",
  "jobId": "8638232002",
  "title": "AI Transformation Owner, CRO",
  "location": "Remote, United States",
  "offices": [],
  "departments": ["Enablement"],
  "workplaceType": "remote",
  "employmentType": null,
  "firstPublished": "2026-07-22T13:38:40-04:00",
  "updatedAt": "2026-10-15T15:24:46-04:00",
  "applicationDeadline": null,
  "applyUrl": "https://job-boards.greenhouse.io/gitlab/jobs/8638232002",
  "requisitionId": "6682",
  "language": "en",
  "salary": {
    "min": 139200,
    "max": 235200,
    "currency": "USD",
    "period": "year",
    "source": "description",
    "label": null
  },
  "metadata": { "Quota Coverage Type": "n/a" },
  "scrapedAt": "2026-10-26T01:46:21.110Z"
}
```

With **Include salary** on, `salary.source` is `pay_transparency` when the employer publishes a range on the job. With **Include description** on, rows also carry `descriptionText` and `descriptionHtml`. A board that cannot be read gives one free row with `error` and `errorCode` so you can see what went wrong. A run summary (boards read, jobs listed, jobs filtered, errors) is saved as `RUN_SUMMARY` in the key-value store.

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

Pay per result. You pay only for jobs delivered to your dataset.

| Event | Price |
|---|---|
| Job listed | **$0.0017** ($1.70 per 1,000) |
| Job listed, Silver plan | $0.0014 ($1.40 per 1,000) |
| Job listed, Gold plan and above | $0.0012 ($1.20 per 1,000) |
| Run start | $0.0005 per GB of memory (default 512 MB = $0.0005) |
| Failed boards, filtered-out jobs, already-seen jobs | **Free** |

Worked examples (Free and Bronze plans):

- **100 jobs** from a few companies: 100 x $0.0017 + $0.0005 = **$0.1705**
- **1,000 jobs** across 20 companies: **$1.7005**
- **Daily alert** with Only new jobs, about 20 new jobs a day: 600 jobs + 30 starts = **about $1.04 a month**
- Apify's free $5 monthly credit covers roughly **2,900 jobs** a month

Set **Max cost per run** in the run options and the Actor stops cleanly when it is reached.

### Integrations (API, AI agents, Make, Zapier)

**API**: run and get the jobs in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/chris_elder~greenhouse-jobs-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"companies":["gitlab","figma"],"remoteOnly":true,"includeSalary":true}'
```

```python
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("chris_elder/greenhouse-jobs-scraper").call(run_input={
    "companies": ["gitlab", "figma", "stripe"],
    "keywords": ["data"],
    "includeSalary": True,
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job.get("company"), job.get("title"), job.get("location"), job.get("salary"))
```

**AI agents (MCP)**: add `https://mcp.apify.com/?tools=chris_elder/greenhouse-jobs-scraper` to Claude, Cursor, VS Code or any MCP client, and your agent can look up open roles at any Greenhouse company.

**Make, Zapier, n8n**: use the Apify app's **Run Actor** action with `chris_elder/greenhouse-jobs-scraper`, then send rows to Google Sheets, Airtable, Slack or your ATS. A **schedule** plus **Only new jobs** gives you a daily new-jobs feed; **webhooks** fire when a run finishes.

### Limits and good to know

- Works for companies whose jobs are hosted on Greenhouse (US job board host). Companies on Workday, Lever, Ashby or other systems are not covered here; see [Multi-ATS Jobs API](https://apify.com/chris_elder/multi-ats-jobs-api) for Workday, Lever, Ashby, SmartRecruiters, Recruitee and Workable.
- Salary is only as good as what the employer publishes. Many companies publish ranges for US roles only; others publish none.
- `employmentType` comes from the employer's own custom fields and is often empty.
- Careers pages that load jobs with JavaScript may hide the board link. The Actor then tries the company's domain as a slug and only accepts it if the board name matches. If that fails, give the slug directly.
- **Only new jobs** keeps up to 20,000 job IDs per alert name.

### Is it legal to scrape Greenhouse job boards?

This Actor reads the public Greenhouse Job Board API, which Greenhouse provides so that anyone can display a company's open jobs. It collects job advertisements only: titles, locations, departments, descriptions, salary ranges and application question labels. It does not collect candidate data, recruiter contact details or any other personal data, and it never submits applications. You are responsible for how you use the data; if you republish job ads, link back to the employer's apply URL (provided in every row).

### FAQ

**How do I find a company's Greenhouse slug?**
Open one of its jobs. The link looks like `job-boards.greenhouse.io/<slug>/jobs/123`. Or paste the company's careers page and the Actor will look for the board.

**Can I get only remote jobs?**
Yes. Tick **Remote only**, or add `Remote` to **Locations** to keep remote plus other places you list.

**How do I get alerts for new jobs?**
Tick **Only new jobs**, give the alert a **Monitor name**, and schedule the Actor daily. The first run returns everything; later runs return only new postings. Already-seen jobs are free.

**Why is salary empty for some jobs?**
The employer did not publish a range for that job. Tick **Include salary** to read the official pay transparency field as well as the job text.

**Is there a limit on how many companies I can add?**
No hard limit. Big runs with hundreds of companies are fine; use **Max jobs total** or **Max cost per run** to cap spend.

**What happens if a slug is wrong?**
You get one free row with `error: "...(not charged)"` and the run carries on with the other companies.

### Support, reliability and feature requests

- **Failed boards are free.** You pay only for jobs delivered.
- **Tested on real boards before every release** (GitLab, Figma, Stripe, Airbnb and more, plus wrong slugs and JavaScript careers pages).
- **Issues answered within 2 business days.** Open an issue on the **Issues** tab with your input.
- **Feature requests welcome**: open an issue titled "Feature request: ...".
- Built by GPT Shop Ltd with AI-assisted development; every release is reviewed and tested before it ships.

### More tools from GPT Shop Ltd

- [Multi-ATS Jobs API](https://apify.com/chris_elder/multi-ats-jobs-api): Workday, Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable jobs in one run
- [UK Companies House Search](https://apify.com/chris_elder/uk-companies-house-search): UK company search with filters by status, type and date
- [Merge, Dedupe & Transform Datasets](https://apify.com/chris_elder/dataset-transformer): merge job runs, remove duplicates and export to CSV
- [Bulk File Downloader](https://apify.com/chris_elder/bulk-file-downloader): download thousands of files from link lists into one place
- All tools: [apify.com/chris_elder](https://apify.com/chris_elder)

# Actor input Schema

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

One per line: a board slug (gitlab), a Greenhouse link (https://job-boards.greenhouse.io/gitlab, boards.greenhouse.io/embed/job_board?for=gitlab) or a company careers page that embeds a Greenhouse board. Duplicate boards are fetched once.

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

Keep jobs whose title contains any of these words (case-insensitive). Leave empty for all jobs. Filtered-out jobs are free.

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

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

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

Keep jobs whose location or office contains any of these, e.g. London, United States, Remote.

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

Keep jobs in a department containing any of these, e.g. Engineering, Sales.

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

Keep only jobs whose location or title says remote (or anywhere / work from home). Hybrid jobs are not counted as remote.

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

Keep jobs first published in the last N days. 0 = any date.

## `postedAfter` (type: `string`):

Keep jobs first published on or after this date (YYYY-MM-DD).

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

Remembers job IDs between runs (in a named key-value store, greenhouse-jobs-monitor, in your account) and returns only jobs not seen before. Already-seen jobs are free. The first run returns every matching job. Ideal with a schedule for job alerts.

## `monitorName` (type: `string`):

Use a different name for each separate alert (e.g. engineering-uk) so their memories don't mix. Only used with Only new jobs.

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

Add the full description as plain text and HTML. No extra cost; makes the dataset larger.

## `includeSalary` (type: `boolean`):

Read the salary range the employer publishes for pay transparency (one extra request per kept job, so slower on big boards). No extra cost. Without this, a salary found in the description text is still returned.

## `includeQuestions` (type: `boolean`):

Add the application form questions (label, required, type, options) for each job. One extra request per kept job. No extra cost.

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

Stop after this many delivered jobs from one board.

## `maxJobsTotal` (type: `integer`):

Stop after this many delivered jobs in the whole run. Also respects Max cost per run.

## `requestDelayMs` (type: `integer`):

Pause between requests to Greenhouse, to stay polite.

## Actor input object example

```json
{
  "companies": [
    "gitlab",
    "figma"
  ],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "onlyNewJobs": false,
  "monitorName": "default",
  "includeDescription": false,
  "includeSalary": false,
  "includeQuestions": false,
  "maxJobsPerCompany": 10,
  "maxJobsTotal": 10000,
  "requestDelayMs": 250
}
```

# Actor output Schema

## `overview` (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": [
        "gitlab",
        "figma"
    ],
    "maxJobsPerCompany": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("chris_elder/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": [
        "gitlab",
        "figma",
    ],
    "maxJobsPerCompany": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("chris_elder/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": [
    "gitlab",
    "figma"
  ],
  "maxJobsPerCompany": 10
}' |
apify call chris_elder/greenhouse-jobs-scraper --silent --output-dataset

```

## MCP server setup

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