# Greenhouse Jobs Scraper (`khadinakbar/greenhouse-jobs-scraper`) Actor

Extract public Greenhouse job boards through the official Job Board API. Returns validated job postings with descriptions, departments, offices, timestamps, and application URLs for recruiting and job-market research.

- **URL**: https://apify.com/khadinakbar/greenhouse-jobs-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Jobs, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 validated greenhouse job returneds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Greenhouse Jobs Scraper

Greenhouse Jobs Scraper extracts one structured dataset record for each public Greenhouse opening. Recruiters, talent-intelligence teams, and job-market researchers can provide known board tokens or board URLs and receive titles, locations, departments, descriptions, application URLs, timestamps, and source provenance for current hiring analysis.

### Best fit for this Actor

- Choose this actor when a company already exposes a public Greenhouse board and you need the board's current job records in a consistent dataset.
- Use board tokens or public board URLs, then filter on title, location, or department before results are written.
- Use each returned `sourceApiUrl`, `jobUrl`, and `scrapedAt` field to support a source-linked recruiting or market-research workflow.

### Focused standalone workflow

This actor is designed as a focused standalone workflow for public Greenhouse boards. It works well for teams that already know the employer boards they want to monitor and want a clear, source-linked dataset for each collection.

### Recruiting workflow: from board token to outreach priority

A talent researcher starts with a shortlist of employers that use Greenhouse. They provide the board tokens, then filter for engineering and remote roles. The actor returns `title`, `location`, `departmentNames`, `updatedAt`, and `applyUrl`; next, the researcher exports the dataset to compare open roles and prioritize employer outreach or job-market reporting.

### Quick start input

```json
{
  "boardTokens": ["stripe", "https://job-boards.greenhouse.io/openai"],
  "maxResultsPerBoard": 100,
  "titleIncludes": "engineer",
  "locationIncludes": "remote",
  "departmentIncludes": "engineering",
  "includeDescriptions": true
}
```

`boardTokens` accepts raw Greenhouse tokens and public board URLs. `maxResultsPerBoard` sets a clear collection boundary for each supplied board.

### Input reference

| Field | Type | What it controls |
| --- | --- | --- |
| `boardTokens` | array | One or more public Greenhouse board tokens or board URLs. |
| `maxResultsPerBoard` | integer | Validated result boundary for each board. |
| `titleIncludes` | string | Case-insensitive title text selection. |
| `locationIncludes` | string | Case-insensitive public location selection. |
| `departmentIncludes` | string | Case-insensitive public department selection. |
| `includeDescriptions` | boolean | Detailed public description HTML and clean text in each record. |

### What data you receive

Each dataset item is one public Greenhouse job post. Source URLs and collection timestamps make the item useful for current, reviewable downstream work.

| Field | Meaning |
| --- | --- |
| `jobId`, `boardToken`, `companyName` | Stable public identity for the job and its board. |
| `title`, `location`, `departmentNames` | Public role and organization fields for filtering and analysis. |
| `descriptionText`, `applyUrl` | Public role detail and direct employer application path. |
| `updatedAt`, `scrapedAt`, `sourceApiUrl` | Freshness and provenance for each observation. |

```json
{
  "jobId": "127817",
  "internalJobId": "144381",
  "companyName": "Example Labs",
  "boardToken": "example",
  "title": "Senior Software Engineer",
  "location": "Remote — United States",
  "departmentNames": ["Engineering"],
  "officeNames": ["New York"],
  "officeLocations": ["New York, NY"],
  "descriptionHtml": "<p>Build reliable APIs.</p>",
  "descriptionText": "Build reliable APIs.",
  "applyUrl": "https://boards.greenhouse.io/example/jobs/127817",
  "jobUrl": "https://boards.greenhouse.io/example/jobs/127817",
  "requisitionId": "REQ-50",
  "language": "en",
  "metadata": null,
  "sourceApiUrl": "https://boards-api.greenhouse.io/v1/boards/example/jobs?content=true"
}
```

### Use through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~greenhouse-jobs-scraper/runs?token=$APIFY_TOKEN" \
  -H "content-type: application/json" \
  -d '{"boardTokens":["stripe"],"maxResultsPerBoard":25}'
```

Read the default dataset after the collection completes. `OUTPUT` provides the compact outcome and `RUN_SUMMARY` provides board coverage, source diagnostics, and charged event counts.

### Use with AI agents through Apify MCP

> As an AI agent, collect up to 25 current public engineering roles from the Greenhouse board `stripe`. Return each title, location, department, application URL, updated timestamp, and source URL. Read the dataset and report the run outcome, preserve provenance, and keep the collection within the stated result boundary and cost scope.

The actor is read-only and returns the dataset plus an `OUTPUT` outcome. An agent can use `sourceApiUrl`, `jobUrl`, and `scrapedAt` to present a current, traceable collection.

### Pricing

This actor uses Pay per event plus Apify platform usage. A validated job written to the dataset is the billable event; filters are applied before dataset writes. Open the live Pricing tab for current event details, and use the result boundary to align collection cost with the workflow.

### Best results

- Provide known, public Greenhouse board tokens when the workflow starts with selected employers.
- Use title, location, and department text to create a focused current dataset for a specific recruiting question.
- Schedule repeat collections when ongoing hiring changes inform a decision, and compare `updatedAt` with `scrapedAt` for freshness context.
- Preserve `sourceApiUrl` and `jobUrl` when sharing results so collaborators can validate each public opening.

### Builder's note

I designed the output around one public job post because that keeps filtering, dataset readback, and employer-level joins clear. I found that preserving both the public application URL and the Greenhouse API source gives researchers useful provenance while the clean description text supports direct analysis.

### Responsible use

Use public or authorized data in accordance with applicable laws, site terms, and your organization's data-handling practices. Keep source URLs with shared records so recipients can review the employer's public posting.

# Actor input Schema

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

Enter one public Greenhouse board token or board URL per line, such as stripe or https://job-boards.greenhouse.io/stripe. The actor extracts the token and accepts up to 25 unique boards. This is required and is not a company website URL, login URL, individual job URL, or application form.

## `maxResultsPerBoard` (type: `integer`):

Caps validated job records returned for each Greenhouse board. Enter an integer such as 100. It defaults to 100 and accepts 1 through 1,000. This is a per-board result cap, not a page count or a global budget across every board.

## `titleIncludes` (type: `string`):

Optionally keep only jobs whose public title contains this text, such as engineer. Matching is case-insensitive and uses literal text. Leave blank to keep all titles. This is not a Boolean query or a full-text search across descriptions.

## `locationIncludes` (type: `string`):

Optionally keep only jobs whose public Greenhouse location contains this text, such as remote or london. Matching is case-insensitive and uses the location text supplied by the board. Leave blank to keep every location. This does not geocode jobs or search office addresses.

## `departmentIncludes` (type: `string`):

Optionally keep only jobs assigned to a public Greenhouse department containing this text, such as engineering. Matching is case-insensitive across the public department names. Leave blank to keep all departments. This does not infer a department from the job description.

## `includeDescriptions` (type: `boolean`):

Controls whether each output record includes the public Greenhouse description in HTML and clean text. Set true for detailed recruiting and research data or false for a smaller, faster result. It defaults to true. This does not retrieve private hiring notes, candidates, or application answers.

## Actor input object example

```json
{
  "boardTokens": [
    "stripe",
    "https://job-boards.greenhouse.io/openai"
  ],
  "maxResultsPerBoard": 100,
  "titleIncludes": "engineer",
  "locationIncludes": "remote",
  "departmentIncludes": "engineering",
  "includeDescriptions": true
}
```

# Actor output Schema

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

Validated public Greenhouse job records returned by this run.

## `output` (type: `string`):

Compact outcome, item counts, warnings, and charged event totals.

## `runSummary` (type: `string`):

Detailed board coverage, diagnostics, and billing information for this run.

# 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": [
        "stripe"
    ],
    "maxResultsPerBoard": 100,
    "titleIncludes": "",
    "locationIncludes": "",
    "departmentIncludes": "",
    "includeDescriptions": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/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 = {
    "boardTokens": ["stripe"],
    "maxResultsPerBoard": 100,
    "titleIncludes": "",
    "locationIncludes": "",
    "departmentIncludes": "",
    "includeDescriptions": True,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/greenhouse-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "stripe"
  ],
  "maxResultsPerBoard": 100,
  "titleIncludes": "",
  "locationIncludes": "",
  "departmentIncludes": "",
  "includeDescriptions": true
}' |
apify call khadinakbar/greenhouse-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/greenhouse-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VWE9UWysLxkHbOETu/builds/2nADWQntFA0uzAkk3/openapi.json
