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

Track company hiring on Greenhouse. Collect open roles, departments and teams, offices, pay ranges, job metadata, posting dates, apply links, application questions and full job descriptions. Filter by keywords, location and remote status for recruiting and hiring-signal research.

- **URL**: https://apify.com/apt_marble/greenhouse-jobs-scraper.md
- **Developed by:** [Hamza](https://apify.com/apt_marble) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 jobs

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: Greenhouse Career Board Jobs in JSON, CSV and Excel

Track company hiring on Greenhouse job boards. Get every open role for the companies you choose: title, department, location, employment type, posting date, apply link and an optional full description. No login, no cookies, no browser, so runs finish fast.

### What you get

Company, job title, department and team, location and all locations, remote or workplace type, employment type, salary range where the company publishes it, posted and updated dates, job link, apply link and an optional plain-text description.

### Why use this actor

- **Keywords search the full job text.** A keyword matches the title, department, team and the whole job description, not only the title. Searching python finds every role that mentions python.
- **Many companies in one run.** Add company slugs or board links and run them in parallel.
- **Useful filters.** Location, department or team, and remote-only.
- **Clean fields** ready for spreadsheets, CRMs and hiring-signal dashboards.

### Use cases

- Recruiting and talent sourcing across target companies
- Hiring-signal research for sales and investors
- Salary research where companies publish pay ranges
- Job boards and newsletters that list roles from many employers
- Competitor and market tracking

### Input

| Field | What it does |
| --- | --- |
| Companies (`companies`) | Company board slugs or Greenhouse career-board URLs. Only this platform is accepted. |
| Keywords (`keywords`) | Keep only jobs where at least one of these words appears in the job title, department, team or full job description. Leave empty for all jobs. |
| Locations (`locations`) | Keep only jobs whose location contains at least one of these texts (for example London, Remote, Germany). |
| Departments or teams (`departments`) | Keep only jobs whose department or team contains one of these texts (for example Engineering, Sales). |
| Remote jobs only (`remoteOnly`) | Keep only jobs marked remote or with remote in the location. Default: `false`. |
| Include full job description (`includeDescription`) | Adds the job description (plain text and HTML) to every result. Billed at the higher job-with-description rate when on. Default: `true`. |
| Include pay ranges and application questions (`includeDetails`) | Makes one extra request per job to get pay ranges and the application form. Turn off for a faster run that skips them. Default: `true`. |
| Max jobs per company (`maxJobsPerCompany`) | Maximum number of jobs returned for each company. Default: `1000`. Range: 1-10000. |
| Parallel companies (`concurrency`) | How many companies are fetched at the same time. Default: `5`. Range: 1-20. |

#### Example input

```json
{
  "companies": [
    "stripe"
  ],
  "keywords": [
    "python"
  ],
  "remoteOnly": true,
  "maxJobsPerCompany": 100
}
```

You can paste a company slug (for example `stripe`) or a Greenhouse board link (for example `https://boards.greenhouse.io/airbnb`).

### Output

Each job carries everything the Greenhouse board API returns for it. Fields the API does not give for a job are left out of that record, so you never get columns full of nulls. Example (shortened):

```json
{
  "platform": "greenhouse",
  "company": "airbnb",
  "companyName": "Airbnb",
  "jobId": "8184174",
  "title": "Account Manager ",
  "department": "2. Business",
  "team": "Business Development",
  "departmentPaths": [
    "2. Business > Sales & Partnerships > Business Development"
  ],
  "departments": [
    {
      "id": 247,
      "name": "Business Development",
      "child_ids": [],
      "parent_id": 73691
    }
  ],
  "offices": [
    {
      "id": 151,
      "name": "London, United Kingdom",
      "location": "London, United Kingdom",
      "child_ids": [],
      "parent_id": 64290
    }
  ],
  "location": "London, United Kingdom",
  "locations": [
    "London, United Kingdom"
  ],
  "remote": false,
  "workplaceType": "hybrid",
  "metadata": [
    {
      "id": 9245691,
      "name": "Is this job part of ACC?",
      "value": false,
      "value_type": "yes_no"
    },
    {
      "id": 10216612,
      "name": "Workplace Type",
      "value": "Hybrid",
      "value_type": "single_select"
    }
  ],
  "salaryMin": 46000,
  "salaryMax": 54000,
  "salaryCurrency": "GBP",
  "salaryInterval": "year",
  "salaryText": "United Kingdom Annual Pay Range: GBP 46000 - 54000",
  "payRanges": [
    {
      "title": "United Kingdom Annual Pay Range",
      "min": 46000,
      "max": 54000,
      "currency": "GBP",
      "text": "How We'll Take Care of You:\n\nOur job titles may span more than one career level...."
    }
  ],
  "requisitionId": "MULTI",
  "internalJobId": "3541546",
  "language": "en",
  "postedAt": "2026-09-09T04:35:19-04:00",
  "updatedAt": "2026-09-29T20:00:54-04:00",
  "description": "Airbnb was born in 2007 when two hosts welcomed three guests to their San Francisco home, and has since grown to over 5 million hosts who have welcomed over 2 billion guest arrivals in almost every country across the globe. Every day, hosts offer unique stays and experiences that make it possible fo...",
  "descriptionHtml": "<div class=\"content-intro\"><p><span style=\"font-family: helvetica, arial, sans-serif; font-size: 12pt;\">Airbnb was born in 2007 when two hosts welcomed three guests to their San Francisco home, and ha...",
  "applicationQuestions": [
    {
      "description": null,
      "label": "First Name",
      "required": true,
      "fields": [
        {
          "name": "first_name",
          "type": "input_text",
          "values": []
        }
      ]
    }
  ],
  "locationQuestions": [
    {
      "description": null,
      "label": "Longitude",
      "required": false,
      "fields": [
        {
          "name": "longitude",
          "type": "input_hidden",
          "values": []
        }
      ]
    }
  ],
  "dataCompliance": [
    {
      "type": "gdpr",
      "requires_consent": false,
      "requires_processing_consent": false,
      "requires_retention_consent": false,
      "retention_period": null,
      "demographic_data_consent_applies": false
    }
  ],
  "jobUrl": "https://careers.airbnb.com/positions/8184174?gh_jid=8184174",
  "applyUrl": "https://careers.airbnb.com/positions/8184174?gh_jid=8184174",
  "scrapedAt": "2026-10-03T21:55:17.488Z"
}
```

Main fields: `department` and `team` (resolved from the board's department tree), `departments`, `offices`, `location`, `locations`, `remote`, `workplaceType` and `employmentType` (only when the company sets them in job metadata), `metadata`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryInterval`, `salaryText`, `payRanges`, `requisitionId`, `internalJobId`, `language`, `applicationDeadline`, `education`, `postedAt`, `updatedAt`, `description`, `descriptionHtml`, `applicationQuestions`, `locationQuestions`, `complianceQuestions`, `demographicQuestions`, `dataCompliance`, `aiDisclaimer`, `aiOptOutUrl`, `jobUrl`, `applyUrl`, `scrapedAt`.

### Pricing

- Job: $0.0008 per event ($0.80 per 1,000).
- Job with description: $0.0015 per event ($1.50 per 1,000).

You only pay for jobs that are returned.

### Tips

- Use the exact company slug from the board link, not the display name.
- Turn off the description option and the pay and questions option for a lighter, faster run.
- Combine department and location filters to build precise lead lists.

### FAQ

**Why is a company reported as not found?** The slug may be wrong or the company may not use Greenhouse. Copy the slug from its careers page link.

**Why do some jobs lack a field?** Greenhouse only returns what the company filled in. For example, workplace type and employment type appear only when the company sets them in job metadata, and pay appears only when a pay range is published. Missing fields are left out of the record.

**Is salary always present?** No. Only jobs with a published pay range have it.

### Limits

Only Greenhouse company boards are supported. Links for other platforms are ignored. Closed or unpublished jobs and missing salary fields are not supplied. Requests can be rate-limited or refused, and a small test is not proof of sustained-volume performance. Board terms and attribution requirements may apply, so check them before collecting or republishing data. Use collected data lawfully.

# Actor input Schema

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

Company board slugs or Greenhouse career-board URLs. Only this platform is accepted.

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

Keep only jobs where at least one of these words appears in the job title, department, team or full job description. Leave empty for all jobs.

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

Keep only jobs whose location contains at least one of these texts (for example London, Remote, Germany).

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

Keep only jobs whose department or team contains one of these texts (for example Engineering, Sales).

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

Keep only jobs marked remote or with remote in the location.

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

Adds the job description (plain text and HTML) to every result. Billed at the higher job-with-description rate when on.

## `includeDetails` (type: `boolean`):

Makes one extra request per job to get pay ranges and the application form. Turn off for a faster run that skips them.

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

Maximum number of jobs returned for each company.

## `concurrency` (type: `integer`):

How many companies are fetched at the same time.

## Actor input object example

```json
{
  "companies": [
    "stripe",
    "https://boards.greenhouse.io/airbnb",
    "discord"
  ],
  "keywords": [],
  "locations": [],
  "departments": [],
  "remoteOnly": false,
  "includeDescription": true,
  "includeDetails": false,
  "maxJobsPerCompany": 50,
  "concurrency": 5
}
```

# Actor output Schema

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

Download the run dataset as JSON; dataset export formats are also available.

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

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

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

```

## MCP server setup

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