# Greenhouse Jobs Scraper: Export Any Greenhouse Job Board (`pulsedata/greenhouse-jobs-scraper`) Actor

Scrape all open jobs from any Greenhouse job board: title, location, remote flag, department, employment type, posting date, salary when published, full description and apply URL. Paste a board URL or just the board token. No API key. $2.00 per 1,000 jobs.

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

## Pricing

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

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: Export Any Greenhouse Job Board

Greenhouse Jobs Scraper exports every open job from one or more Greenhouse job boards as JSON, CSV or Excel. You give it board URLs or just board tokens such as `stripe`, and it returns one record per job with title, location, offices, department, posting and update dates, the full description and the job URL. It costs $2.00 per 1,000 jobs, so a 500-job board costs about $1.00.

### Features

- **Scrape Greenhouse job boards** by URL or by board token. A bare token like `airbnb` is expanded to `https://job-boards.greenhouse.io/airbnb`.
- **Export Greenhouse jobs to CSV, JSON or Excel** with the full description as HTML and plain text.
- **Scrape EU Greenhouse boards** on `boards.eu.greenhouse.io` and `job-boards.eu.greenhouse.io` (pass the full URL for those).
- **Find the Greenhouse board behind a company careers page.** Paste `https://company.com/careers` and the actor looks in the page HTML for a Greenhouse embed or link.
- **Filter Greenhouse jobs by keyword, office location, remote and posting date** before they are saved.
- **Monitor new Greenhouse job postings** on a schedule with `postedWithinDays`.
- **No API key, no login and no proxy.** Greenhouse publishes every board through its public Job Board API, which is what this actor reads.

### Use cases

- **Job board aggregation:** keep a list of 200 Greenhouse companies in one input and refresh your own board daily.
- **Recruiting and sourcing:** see which departments a competitor is hiring into and in which offices.
- **Market research:** count open roles by Greenhouse department over time to track team growth at a set of companies.
- **Lead generation:** a company opening several "Data Engineer" roles is a likely buyer of data tooling. Put those titles in `keywords` and run weekly.

### Input

```json
{
  "startUrls": [
    "https://job-boards.greenhouse.io/stripe",
    "airbnb",
    "https://job-boards.eu.greenhouse.io/examplecompany"
  ],
  "keywords": ["engineer", "analyst"],
  "locations": ["Dublin", "London", "Remote"],
  "remoteOnly": false,
  "postedWithinDays": 14,
  "includeDescription": true,
  "maxJobsPerCompany": 0
}
```

| Field | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | array of strings | (required) | Greenhouse board URLs or bare board tokens, one per line. |
| `keywords` | array | `[]` | Keep only jobs whose title contains one of these words (case-insensitive). |
| `locations` | array | `[]` | Keep only jobs whose location or office names contain one of these strings. |
| `remoteOnly` | boolean | `false` | Keep only jobs whose location text mentions remote, anywhere or similar. |
| `postedWithinDays` | integer | `0` | Keep only jobs first published in the last N days (the update date is used when there is no publish date). 0 means no limit. |
| `includeDescription` | boolean | `true` | Include `descriptionHtml` and `descriptionText`. Greenhouse returns them in the same request, so this adds no extra requests. |
| `maxJobsPerCompany` | integer | `0` | Cap per board, applied after the filters. 0 means no limit. |
| `proxyConfiguration` | object | `{ "useApifyProxy": false }` | Optional Apify Proxy. |

**Accepted Greenhouse URL formats:**

- `https://job-boards.greenhouse.io/stripe`
- `https://boards.greenhouse.io/stripe`
- `https://boards.greenhouse.io/embed/job_board?for=stripe` (the embed URL)
- `https://job-boards.eu.greenhouse.io/company` and `https://boards.eu.greenhouse.io/company` (EU-hosted boards, read from the EU API)
- `stripe` (bare token, always expanded to the US host, so use the full URL for EU boards)
- `https://company.com/careers` (a page that embeds or links a Greenhouse board)

The board token is the last part of the board URL: for `https://job-boards.greenhouse.io/stripe` it is `stripe`.

### Output

One item per job:

```json
{
  "title": "Abuse Investigator",
  "company": "Stripe",
  "location": "Dublin",
  "locations": ["Dublin", "Dublin, Ireland"],
  "country": null,
  "remote": false,
  "workplaceType": null,
  "department": "8611 Security Analytics",
  "team": null,
  "employmentType": null,
  "seniority": null,
  "salary": null,
  "postedAt": "2026-09-03T17:32:53.000Z",
  "updatedAt": "2026-09-18T09:04:11.000Z",
  "url": "https://stripe.com/jobs/search?gh_jid=8172508",
  "applyUrl": "https://stripe.com/jobs/search?gh_jid=8172508",
  "descriptionHtml": "<h2>Who we are</h2><p>…</p>",
  "descriptionText": "Who we are\n\nStripe is a financial infrastructure platform…",
  "ats": "greenhouse",
  "atsJobId": "8172508",
  "sourceUrl": "https://job-boards.greenhouse.io/stripe",
  "scrapedAt": "2026-09-25T08:15:02.000Z"
}
```

What Greenhouse exposes, and how it maps:

- `company` is the company name Greenhouse returns for the board (falls back to the token).
- `location` is the job's location text; `locations` adds the names of every office the job is attached to.
- `department` joins all Greenhouse departments of the job with commas.
- `postedAt` is Greenhouse's first published date and `updatedAt` its last update.
- `url` and `applyUrl` are Greenhouse's absolute URL for the job. Many companies point this at their own careers site, as Stripe does above.
- `employmentType` is filled only if the company has a custom Greenhouse field whose name contains "employment" or "type".
- Greenhouse has no salary field in its public API. `salary` is filled only when a pay range appears near the start of the description text.
- `team`, `country`, `workplaceType` and `seniority` are not published by Greenhouse and stay `null`.

If a token does not exist, the dataset gets one row with `sourceUrl`, `ats`, `slug` and an `error` message such as `HTTP 404`. Error rows are not charged.

### Pricing

Pay per event: **$0.002 per job** saved to the dataset ($2.00 per 1,000 jobs). There is no start fee.

Worked example: you track 40 Greenhouse boards with about 150 open roles each, so 6,000 jobs per full run cost $12.00. Filter with `keywords: ["engineer"]` and keep, say, 1,800 of them, and the run costs $3.60, because jobs removed by filters are never charged. A daily run with `postedWithinDays: 1` over the same boards typically returns a few dozen jobs and costs cents.

### FAQ

**Do I need an API key or a Greenhouse account?**
No. Greenhouse job boards are public and the actor reads them through the public Job Board API.

**How many jobs can it get from one board?**
All of them. Greenhouse returns the whole board in one response, so there is no pagination limit. Use `maxJobsPerCompany` if you want fewer.

**What can it not do?**
It only sees jobs the company publishes on its external board. Internal postings, application questions, hiring managers and candidate data are not available. It does not render JavaScript, so if a careers page loads Greenhouse through a script the actor cannot see, paste the board URL or the token instead.

**Do I need proxies?**
Normally no. The actor retries rate limits and server errors with backoff. Enable `proxyConfiguration` only for very large lists that hit HTTP 429.

**Can I paste boards from other ATS here?**
This actor is set up for Greenhouse. For mixed lists (Lever, Ashby, Workday, Workable and others) use the [Career Page Jobs Scraper](https://apify.com/pulsedata/career-page-jobs-scraper), which auto-detects 12 systems.

**How do I export or automate the results?**
Download the dataset as JSON, CSV, Excel, XML or HTML, call the actor through the Apify API or SDKs, or connect it to Google Sheets, Make, Zapier or n8n.

**Can I run it on a schedule?**
Yes. Create a schedule in Apify Console and set `postedWithinDays` so each run only returns new postings.

### Related actors

- [Career Page Jobs Scraper (12 ATS)](https://apify.com/pulsedata/career-page-jobs-scraper): the multi-ATS version with auto-detection, for lists that mix Greenhouse with other systems.
- [Lever Jobs Scraper](https://apify.com/pulsedata/lever-jobs-scraper): the same output for Lever boards, which also publish salary ranges and workplace type.
- [Ashby Jobs Scraper](https://apify.com/pulsedata/ashby-jobs-scraper): the same output for Ashby boards, common among newer startups.
- [Workday Jobs Scraper](https://apify.com/pulsedata/workday-jobs-scraper): for large enterprises that run their careers site on Workday.
- [Website Tech Stack Detector](https://apify.com/pulsedata/website-tech-stack-detector): add each hiring company's tech stack to score leads.

# Actor input Schema

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

Greenhouse board URLs such as `https://job-boards.greenhouse.io/stripe` or `https://boards.greenhouse.io/stripe`, or just the board token (`stripe`). A company's own careers page works too when it embeds a Greenhouse board.

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

Only keep jobs whose title contains at least one of these words/phrases (case-insensitive). Leave empty for all jobs.

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

Only keep jobs whose location contains one of these strings (e.g. `Berlin`, `Germany`, `Remote`, `United States`).

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

Keep only jobs flagged as remote by the ATS or whose location mentions remote.

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

Only jobs posted or updated within the last N days. Jobs whose ATS publishes no date are kept. 0 = no limit.

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

Return the full description (HTML + plain text). For Workday, SmartRecruiters, BambooHR, Workable and Breezy this requires one extra request per job.

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

Maximum jobs returned per career page, counted after the keyword, location, remote and date filters (0 = no limit).

## `proxyConfiguration` (type: `object`):

Optional. ATS APIs are public and rarely block; enable Apify Proxy only if you hit rate limits.

## Actor input object example

```json
{
  "startUrls": [
    "https://job-boards.greenhouse.io/stripe",
    "airbnb"
  ],
  "keywords": [],
  "locations": [],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": true,
  "maxJobsPerCompany": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Results stored in the default dataset (JSON/CSV/Excel via the dataset API).

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

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

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

```

## MCP server setup

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