# 🌱 Greenhouse Jobs API (`scraper-engine/greenhouse-jobs-api`) Actor

🌱 Greenhouse Jobs API (greenhouse-jobs-api) fetches live job listings from Greenhouse effortlessly. 🚀 Perfect for recruiters, job boards & developers building accurate, up-to-date career search experiences. 📈 Automate discovery with clean, reliable data.

- **URL**: https://apify.com/scraper-engine/greenhouse-jobs-api.md
- **Developed by:** [Scraper Engine](https://apify.com/scraper-engine) (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 $4.99 / 1,000 results

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 API Scraper

Pull **every public job posting** from any company that hosts its careers page on **Greenhouse** — straight from the official Greenhouse Boards API. Just paste one or more board URLs and get a clean, structured dataset with **94 fields per job**, including geocoded locations and published salary ranges.

> ⚡ No login. No browser. Direct from `boards-api.greenhouse.io`.

***

### 💡 Why Choose This Actor?

- **🎯 Source-direct** — reads the official Greenhouse Boards API, so data is fresh and complete (no stale aggregation).
- **🔗 Bulk input** — drop in as many board URLs as you like; tokens are auto-extracted from any Greenhouse URL format.
- **🌍 Geocoding built in** — messy office addresses are resolved to city / region / country / timezone / lat-lng via OpenStreetMap, and cached for fast repeat runs.
- **💰 Salary enrichment** — pulls published pay-transparency ranges per job.
- **🛡️ Bulletproof proxy fallback** — starts direct, then automatically climbs to datacenter and residential proxies only if Greenhouse pushes back.
- **📊 94-field schema** — the same comprehensive shape used by premium ATS feeds.

***

### ✨ Key Features

| Feature | Description |
|---------|-------------|
| 🔍 Title / Location / Org / Domain filters | Include & exclude lists with `:*` prefix matching |
| 📝 Description search | Full-text search across title + description |
| 💵 Salary ranges | Per-job pay-transparency data |
| 🌍 Derived location fields | Cities, regions, countries, timezones, lat/lng |
| 🧾 Text or HTML descriptions | Your choice |
| 🛡️ Proxy ladder | direct → datacenter → residential (sticky) |
| 📤 Live saving | Records stream to the dataset as they finish |

***

### 📥 Input

| Field | Type | Description |
|-------|------|-------------|
| `urls` ✅ | array | Greenhouse board URLs or plain tokens (bulk). **Required.** |
| `limit` | integer | Max jobs per run (200–5000). |
| `includeCompanyDetails` | boolean | Include company-data columns (LinkedIn/Crunchbase/logo). |
| `titleSearch` / `titleExclusionSearch` | array | Keep / drop by title. |
| `locationSearch` / `locationExclusionSearch` | array | Keep / drop by location. |
| `organizationSearch` / `organizationExclusionSearch` | array | Keep / drop by company. |
| `domainFilter` / `domainExclusionFilter` | array | Keep / drop by company domain (exact). |
| `descriptionSearch` / `descriptionExclusionSearch` | array | Search/exclude in title + description. |
| `descriptionType` | string | `text` or `html`. |
| `hasSalary` | boolean | Keep only jobs with a published salary. |
| `fetchSalaryData` | boolean | Fetch pay ranges even when `hasSalary` is off. |
| `geocodeLocations` | boolean | Fill the `*_derived` location fields. |
| `maxRetries` / `concurrency` | integer | Tuning knobs. |
| `proxyConfiguration` | object | Proxy settings (defaults to **no proxy**). |

#### Example input

```json
{
  "urls": [
    { "url": "https://job-boards.greenhouse.io/datadog" },
    { "url": "https://job-boards.greenhouse.io/stripe" }
  ],
  "limit": 200,
  "titleSearch": ["Engineer:*"],
  "fetchSalaryData": true,
  "geocodeLocations": true,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

***

### 📤 Output

Each record follows the full **94-field schema**. The dataset ships with **5 per-section views** in the Console: **📋 Overview**, **🌍 Location**, **💰 Salary**, **🏢 Company**, **📝 Description**.

#### Example record (truncated)

```json
{
  "id": 4567890,
  "title": "Senior Software Engineer",
  "organization": "Datadog",
  "url": "https://job-boards.greenhouse.io/datadog/jobs/4567890",
  "source": "greenhouse",
  "source_domain": "job-boards.greenhouse.io",
  "date_posted": "2026-06-11T10:22:02",
  "locations_alt": ["New York, NY"],
  "cities_derived": ["New York"],
  "regions_derived": ["New York"],
  "countries_derived": ["United States"],
  "timezones_derived": ["America/New_York"],
  "lats_derived": [40.7127281],
  "lngs_derived": [-74.0060152],
  "ai_salary_currency": "USD",
  "ai_salary_min_value": 150000.0,
  "ai_salary_max_value": 220000.0,
  "ai_salary_unit_text": "YEAR",
  "description_text": "About the role …"
}
```

> ℹ️ The `ai_*`, `org_linkedin_*`, `linkedin_org_*`, and `org_crunchbase_*` columns are vendor-side AI/LinkedIn enrichments with no public Greenhouse source. They are present in the schema for parity and emitted as `null` (salary `ai_salary_*` fields are filled from the published pay ranges).

***

### 🚀 How to Use (Apify Console)

1. Log in at [console.apify.com](https://console.apify.com) → **Actors**.
2. Open **Greenhouse Jobs API Scraper**.
3. Paste your Greenhouse board URLs into **🔗 Greenhouse Board URLs**.
4. (Optional) Set filters, salary, geocoding, and proxy.
5. Click **Start**.
6. Watch the real-time log as boards are fetched, salaries pulled, and locations geocoded.
7. Open the **Output** tab → switch between the per-section views.
8. Export to JSON / CSV / XLSX.

***

### 🤖 Use via API

```bash
curl -X POST "https://api.apify.com/v2/acts/<ACTOR_ID>/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"urls":[{"url":"https://job-boards.greenhouse.io/datadog"}],"limit":200}'
```

***

### 🎯 Best Use Cases

- 📈 Job-market & hiring-trend analysis
- 🧭 Sourcing & recruiting pipelines
- 🏢 Competitive hiring intelligence
- 💼 Building job boards / aggregators

***

### 💳 Pricing

This actor uses the **Pay-Per-Event** model:

| Event | Bills for |
|-------|-----------|
| `job-item` | Each job posting saved to the dataset |

You only pay for the jobs you actually receive. Runs that hit your charge limit stop cleanly.

***

### ❓ FAQ

**Which URLs are accepted?** Any Greenhouse board URL — `job-boards.greenhouse.io/<token>`, `boards.greenhouse.io/<token>`, `boards-api.greenhouse.io/v1/boards/<token>`, embed links, or a plain token like `datadog`.

**Why are the LinkedIn/Crunchbase columns null?** They require third-party enrichment data that a direct Greenhouse scrape doesn't have. They're kept for schema parity.

**Do I need a proxy?** No. The actor runs direct by default and only escalates to datacenter/residential proxies if Greenhouse blocks a request.

**How does geocoding work?** Locations are resolved via OpenStreetMap/Nominatim (1 req/s), cached across runs so repeat scrapes are fast.

***

### 🛟 Support & Feedback

Found a bug or want a new field? Open an issue on the Actor's **Issues** tab.

***

### ⚖️ Legal

Data is collected only from **publicly available** Greenhouse job boards. You are responsible for compliance with applicable laws (GDPR, CCPA, target ToS).

# Actor input Schema

## `urls` (type: `array`):

List one or more Greenhouse job-board URLs (e.g. https://job-boards.greenhouse.io/datadog or https://boards.greenhouse.io/stripe). Plain board tokens (e.g. `datadog`) are also accepted. Bulk input supported.

## `limit` (type: `integer`):

Maximum number of jobs to return per run. Minimum 200, maximum 5,000. 💡 Set memory to 1GB+ for runs above 2,000 jobs.

## `includeCompanyDetails` (type: `boolean`):

Include the company-data columns (LinkedIn / Crunchbase / logo). These are vendor-side AI enrichments with no public Greenhouse source — when enabled the columns are present but emitted as null.

## `titleSearch` (type: `array`):

Job titles to keep. Use `:*` for prefix matching (e.g. 'Soft:\*' matches 'Software', 'Softball'). Leave empty to keep all titles.

## `titleExclusionSearch` (type: `array`):

Job titles to drop. Use `:*` for prefix matching.

## `locationSearch` (type: `array`):

Locations to keep (phrase match against the job's location text). E.g. 'Barcelona', 'United Kingdom'. Use `:*` for prefix matching.

## `locationExclusionSearch` (type: `array`):

Locations to drop. Use `:*` for prefix matching.

## `descriptionSearch` (type: `array`):

⚠️ Intensive. Terms searched in title + description. Be specific and combine with a Title Search. Use `:*` for prefix matching.

## `descriptionExclusionSearch` (type: `array`):

⚠️ Intensive. Terms excluded from title + description. Use `:*` for prefix matching.

## `organizationSearch` (type: `array`):

Organization names to keep. Use `:*` for prefix matching.

## `organizationExclusionSearch` (type: `array`):

Organization names to drop. Use `:*` for prefix matching.

## `domainFilter` (type: `array`):

Company domains to keep — exact match (e.g. 'n26.com').

## `domainExclusionFilter` (type: `array`):

Company domains to drop — exact match.

## `descriptionType` (type: `string`):

Format of the job description in the output.

## `aiEmploymentTypeFilter` (type: `array`):

Filter by employment type. ℹ️ Vendor AI enrichment — a direct Greenhouse scrape has no AI source, so this filter is accepted but not applied.

## `aiWorkArrangementFilter` (type: `array`):

Filter by work arrangement. Remote OK = remote with an office available. Remote Solely = remote, no office. ℹ️ Vendor AI enrichment — accepted but not applied on a direct scrape.

## `hasSalary` (type: `boolean`):

Keep only jobs that publish a pay range (forces a per-job detail fetch).

## `aiExperienceLevelFilter` (type: `array`):

Filter by years of experience. ℹ️ Vendor AI enrichment — accepted but not applied on a direct scrape.

## `aiVisaSponsorshipFilter` (type: `boolean`):

Keep only jobs offering visa sponsorship. ℹ️ Vendor AI enrichment — accepted but not applied on a direct scrape.

## `aiTaxonomiesFilter` (type: `array`):

Filter by AI taxonomies. ℹ️ Vendor AI enrichment — accepted but not applied on a direct scrape.

## `aiTaxonomiesPrimaryFilter` (type: `array`):

Filter by primary AI taxonomy. ℹ️ Vendor AI enrichment — accepted but not applied on a direct scrape.

## `aiTaxonomiesExclusionFilter` (type: `array`):

Exclude jobs by AI taxonomies. ⚠️ Very broad — may drop relevant jobs. ℹ️ Vendor AI enrichment — accepted but not applied on a direct scrape.

## `removeAgency` (type: `boolean`):

Filter out recruitment agencies. ℹ️ Vendor AI enrichment — accepted but not applied on a direct scrape.

## `liIndustryFilter` (type: `array`):

Filter by LinkedIn industries. ℹ️ Vendor LinkedIn enrichment — accepted but not applied on a direct scrape.

## `liOrganizationEmployeesLte` (type: `integer`):

Keep only companies with at most this many LinkedIn employees. ℹ️ Vendor LinkedIn enrichment — accepted but not applied on a direct scrape.

## `liOrganizationEmployeesGte` (type: `integer`):

Keep only companies with at least this many LinkedIn employees. ℹ️ Vendor LinkedIn enrichment — accepted but not applied on a direct scrape.

## `includeLinkedIn` (type: `boolean`):

Deprecated alias of 'Include Company Data Fields'. Set to false to drop the company-data columns.

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

Deprecated. Legacy toggle for remote-only jobs; superseded by AI Work Arrangement. ℹ️ Accepted but not applied on a direct scrape.

## `aiHasSalary` (type: `boolean`):

Deprecated alias of 'Only Jobs With Salary'. When true, only jobs with a published pay range are kept.

## `fetchSalaryData` (type: `boolean`):

Fetch published pay ranges even when 'Only Jobs With Salary' is off (1 extra request per job; fills salary\_raw + ai\_salary\_\* where the employer publishes a range).

## `geocodeLocations` (type: `boolean`):

Resolve job locations via OpenStreetMap/Nominatim to fill the \*\_derived fields (cities / regions / countries / locations / timezones / lat / lng). Rate-limited to 1 request/second; results are cached for fast repeat runs.

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

Proxy settings. The actor starts with NO proxy (direct). If Greenhouse blocks the request, it automatically falls back to a datacenter proxy, then to a residential proxy (and sticks with residential for the rest of the run).

## Actor input object example

```json
{
  "urls": [
    "https://job-boards.greenhouse.io/datadog",
    "https://job-boards.greenhouse.io/stripe",
    "https://job-boards.greenhouse.io/robinhood"
  ],
  "limit": 20,
  "includeCompanyDetails": true,
  "titleSearch": [],
  "titleExclusionSearch": [],
  "locationSearch": [],
  "locationExclusionSearch": [],
  "descriptionSearch": [],
  "descriptionExclusionSearch": [],
  "organizationSearch": [],
  "organizationExclusionSearch": [],
  "domainFilter": [],
  "domainExclusionFilter": [],
  "descriptionType": "text",
  "aiEmploymentTypeFilter": [],
  "aiWorkArrangementFilter": [],
  "hasSalary": false,
  "aiExperienceLevelFilter": [],
  "aiVisaSponsorshipFilter": false,
  "aiTaxonomiesFilter": [],
  "aiTaxonomiesPrimaryFilter": [],
  "aiTaxonomiesExclusionFilter": [],
  "removeAgency": false,
  "liIndustryFilter": [],
  "includeLinkedIn": true,
  "remoteOnly": false,
  "aiHasSalary": false,
  "fetchSalaryData": true,
  "geocodeLocations": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "urls": [
        "https://job-boards.greenhouse.io/datadog",
        "https://job-boards.greenhouse.io/stripe",
        "https://job-boards.greenhouse.io/robinhood"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraper-engine/greenhouse-jobs-api").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 = {
    "urls": [
        "https://job-boards.greenhouse.io/datadog",
        "https://job-boards.greenhouse.io/stripe",
        "https://job-boards.greenhouse.io/robinhood",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scraper-engine/greenhouse-jobs-api").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 '{
  "urls": [
    "https://job-boards.greenhouse.io/datadog",
    "https://job-boards.greenhouse.io/stripe",
    "https://job-boards.greenhouse.io/robinhood"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scraper-engine/greenhouse-jobs-api --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/4p1b1wRIreXrf2vj6/builds/FQQOnrMGOJjmbwa2F/openapi.json
