# Greenhouse Jobs Scraper & New Job Alerts (`mikirag3/greenhouse-jobs-monitor`) Actor

Scrape every open job from any Greenhouse job board in seconds, with full descriptions, departments and locations. Schedule it to get only new or closed postings. No proxy, no login.

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

## Pricing

from $1.00 / 1,000 job results

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

### What does Greenhouse Jobs Scraper do?

**Greenhouse Jobs Scraper** extracts every open job from company job boards hosted on **Greenhouse** (`boards.greenhouse.io`, `job-boards.greenhouse.io`, including the EU region): title, department, office locations, publication and update dates, links and the full description. Type a board name like `stripe` or paste a board URL, click **Start**, and download the jobs as JSON, CSV, Excel or HTML.

Turn on **monitoring mode** and schedule it daily or hourly: each run returns **only the jobs posted since the last run**, and optionally the jobs that were **closed**. It works as a ready-made **Greenhouse new job alert** for Slack, email, Google Sheets or a webhook.

- ✅ **Fast**: a whole board in 1–2 seconds, even with descriptions. Stripe's 700+ jobs take about one second.
- ✅ **Board name or URL**: `stripe`, `https://boards.greenhouse.io/stripe`, `https://job-boards.greenhouse.io/stripe` or EU boards.
- ✅ **New and closed jobs** in monitoring mode, so unchanged jobs are never charged twice.
- ✅ **Full details**: description as clean text, department, every office location, first published and last updated dates.
- ✅ **Official public API**: uses Greenhouse's documented Job Board API. No proxy, no browser, no login.
- ✅ **Many companies per run**: watch dozens of boards in one scheduled task.

### Who uses it?

- **Job seekers and job alert services**: get a message the morning a target company opens a role.
- **Recruiters and staffing agencies**: watch client and competitor hiring across dozens of tech companies, most of which use Greenhouse.
- **Sales and RevOps teams**: hiring is a buying signal. Five new data engineering roles at a scale-up is a lead.
- **Investors and analysts**: track hiring velocity and team growth at startups and public companies.
- **Job boards and aggregators**: structured listings straight from the source, deduplicated by job ID.

### How to scrape Greenhouse jobs

1. Click **Try for free**.
2. In **Greenhouse job boards**, add one board per line, for example:
   - `stripe`
   - `https://boards.greenhouse.io/figma`
   - `https://job-boards.greenhouse.io/discord`
3. Optionally add filters: job title keywords, words to exclude, locations, departments, remote only, posted within the last N days.
4. Click **Start**.

**Finding the board name:** open any job on the company's careers page. If the address contains `greenhouse.io/<name>` or `gh_jid=`, the company uses Greenhouse. The board name is usually the company name in lowercase (`stripe`, `airbnb`, `databricks`).

### Greenhouse new job alerts (monitoring mode)

1. Turn on **Only new jobs since the last run**.
2. Give the watch list a **Monitor name**, for example `fintech-competitors`.
3. Save the input as a **task** and add a **schedule**, for example every day at 7:00.
4. Connect the task to **Slack**, **email**, **Google Sheets**, **Make**, **Zapier**, **n8n** or a **webhook** through Apify integrations.

The first run returns all current jobs (or none, if you turn off **Return existing jobs on the first run**) and remembers them. Every later run returns only new postings. Turn on **Also report closed jobs** to get a `removed` record when a posting disappears. Jobs that were not delivered (for example because the run hit your cost limit) are not marked as seen, so they come in the next run.

### Input example

```json
{
  "companies": ["stripe", "figma", "https://job-boards.greenhouse.io/discord"],
  "keywords": ["engineer", "data"],
  "excludeKeywords": ["intern"],
  "locations": ["New York", "Remote"],
  "includeDescription": true,
  "onlyNewJobs": true,
  "monitorName": "tech-watchlist",
  "reportRemovedJobs": true
}
```

### Output example

```json
{
  "type": "job",
  "ats": "greenhouse",
  "companySlug": "figma",
  "companyName": "Figma",
  "jobId": "5426468004",
  "title": "Account Executive, Enterprise",
  "department": "Sales",
  "location": "San Francisco, CA • New York, NY • United States",
  "allLocations": ["San Francisco, CA • New York, NY • United States", "US"],
  "isRemote": false,
  "postedAt": "2025-01-28T23:57:29+00:00",
  "updatedAt": "2026-07-22T09:37:08+00:00",
  "url": "https://boards.greenhouse.io/figma/jobs/5426468004?gh_jid=5426468004",
  "applyUrl": "https://boards.greenhouse.io/figma/jobs/5426468004?gh_jid=5426468004",
  "description": "Figma is growing our team of passionate creatives and builders on a mission to make design accessible to all...",
  "isNew": true,
  "firstSeenAt": "2026-10-12T07:00:00+00:00",
  "scrapedAt": "2026-10-12T07:00:00+00:00"
}
```

Closed jobs (monitoring mode with **Also report closed jobs**):

```json
{ "type": "removed", "ats": "greenhouse", "companyName": "Stripe", "jobId": "8172510", "title": "Abuse Investigator", "location": "Seattle", "url": "https://stripe.com/jobs/search?gh_jid=8172510", "firstSeenAt": "2026-09-01T00:00:00+00:00", "removedDetectedAt": "2026-10-12T07:00:00+00:00" }
```

A run summary (boards checked, not found, errors, jobs returned) is saved in the key-value store under `OUTPUT`.

### Data fields

| Field | Description |
|---|---|
| `type` | `job` for an open position, `removed` for a closed one (monitoring mode) |
| `companySlug`, `companyName` | Greenhouse board name and company display name |
| `jobId`, `title` | Greenhouse job ID and job title |
| `department` | Department as published on the board |
| `location`, `allLocations` | Main location and every office listed |
| `isRemote` | Remote flag, based on location and office labels |
| `postedAt`, `updatedAt` | First published and last updated dates (ISO 8601, UTC) |
| `url`, `applyUrl` | Job page and application page |
| `description` | Full job description as plain text |
| `isNew`, `firstSeenAt` | Monitoring mode: whether the job is new, and when the Actor first saw it |

Salary and employment type are `null` on most Greenhouse boards, because the public Job Board API does not publish them as structured fields. Values are never guessed from description text.

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

Pay-per-event pricing, you only pay for results:

- **Job board checked**: $0.001 per board per run.
- **Job result**: $0.001 per job, i.e. **$1 per 1,000 jobs**.

Example: a first full snapshot of Stripe, Figma and Discord (about 930 jobs) costs about $0.93. After that, a daily monitoring run on the same three boards costs $0.003 plus $0.001 per new job. Unchanged jobs are free. You can cap any run with Apify's **maximum cost per run**; the Actor stops cleanly and keeps undelivered jobs for the next run.

### FAQ

**Do I need a Greenhouse account or API key?** No. The Actor reads the public Job Board API that powers each company's careers page. It does not log in or apply to jobs. Review the company's terms and your intended use of the data.

**A board was not found.** The board name may differ from the company name, or the company may not use Greenhouse. Open a job on their careers page and look for `greenhouse.io/<name>` in the address.

**Need Lever, Ashby, Workday, Personio, Recruitee, Teamtailor or BambooHR too?** Use our [Jobs Scraper for 8 ATS platforms](https://apify.com/mikirag3/ats-jobs-monitor), which returns all of them in the same format, or the [Workday Jobs Scraper](https://apify.com/mikirag3/workday-jobs-monitor).

**Found a problem or need a feature?** Open an issue in the **Issues** tab.

# Actor input Schema

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

Greenhouse job boards, one per line: a board name like 'stripe', or a URL such as https://boards.greenhouse.io/stripe, https://job-boards.greenhouse.io/stripe or https://job-boards.eu.greenhouse.io/acme. To find the board name, open any job on the company's careers page: the address contains greenhouse.io/<board-name> or gh_jid=.

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

Keep only jobs whose title contains at least one of these words. Case-insensitive. Leave empty for all jobs.

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

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

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

Keep only jobs located in one of these places, e.g. 'London', 'Germany', 'Remote'.

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

Keep only jobs in matching departments or teams, e.g. Engineering or Sales. Jobs with no published department or team will not match this filter.

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

Keep only jobs marked as remote by the company (or with 'remote' in the location).

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

Keep jobs first published within the last N days. Leave empty for no limit.

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

Monitoring mode. The Actor remembers which jobs it has already seen and returns only new postings. Perfect for a daily or hourly schedule.

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

Keeps separate memories for different watch lists. Use a different name for each schedule that tracks a different list of companies.

## `reportRemovedJobs` (type: `boolean`):

In monitoring mode, also return a 'removed' record for every job that disappeared from a career page since the last run.

## `emitExistingOnFirstRun` (type: `boolean`):

In monitoring mode, the first run for a company returns all of its current jobs. Turn off to only start a baseline and get truly new jobs from the next run onwards.

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

Include the full job description as plain text. Greenhouse returns descriptions in the same request, so this does not slow the run down.

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

Return at most this many matching open jobs per company, newest first when dates are available. This limits output, not the number of requests needed to read a board. Closed-job records are additional. Leave empty for no limit.

## Actor input object example

```json
{
  "companies": [
    "stripe",
    "figma",
    "discord"
  ],
  "remoteOnly": false,
  "onlyNewJobs": false,
  "monitorName": "default",
  "reportRemovedJobs": false,
  "emitExistingOnFirstRun": true,
  "includeDescription": true
}
```

# Actor output Schema

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

Open (and, in monitoring mode, closed) jobs returned by this run.

## `summary` (type: `string`):

Companies checked, not found, errors and number of jobs returned.

# 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",
        "figma",
        "discord"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mikirag3/greenhouse-jobs-monitor").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",
        "figma",
        "discord",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("mikirag3/greenhouse-jobs-monitor").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",
    "figma",
    "discord"
  ]
}' |
apify call mikirag3/greenhouse-jobs-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mikirag3/greenhouse-jobs-monitor"
        }
    }
}
```

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/S2OMTRGIYDOspffWx/builds/DxdhjBEJgdX92sqHY/openapi.json
