Greenhouse Jobs Monitor & Scraper
Pricing
$2.00 / 1,000 results
Greenhouse Jobs Monitor & Scraper
Monitor Greenhouse jobs from any company careers board (Airbnb, Stripe, Discord and thousands more). Get flat rows with title, location, posting date, apply link, and published salary ranges as numbers: min, max, currency, period. Schedule monitor runs to get only new, changed, and removed jobs.
Pricing
$2.00 / 1,000 results
Rating
0.0
(0)
Developer
Redomic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
13 hours ago
Last modified
Categories
Security
Limited permissionsShare

Monitor Greenhouse jobs from any company careers board (for example airbnb, stripe, or discord) and get every open job as flat rows: title, location, posting date, apply link and, when the company publishes one, the salary range as numbers: salaryMin, salaryMax, salaryCurrency (ISO 4217) and salaryPeriod (year, month, hour). Schedule runs in monitor mode to get only new, changed, and removed jobs since the last run.
Real rows from airbnb, 31 Oct 2026 (default input, no extra options):
| title | location | workplaceType | salaryMin | salaryMax | salaryCurrency | salaryPeriod |
|---|---|---|---|---|---|---|
| AirCover Specialist, Claims Experience | Canada | Remote | 58,000 | 68,000 | CAD | year |
| Associate Principal, Procurement Innovation Supplier Programs | United States | Remote | 102,000 | 120,000 | USD | year |
| Business Development Manager | Berlin, Germany | Hybrid | 71,000 | 84,000 | EUR | year |
| Business Operations and Growth Lead | United States | Remote | 168,000 | 203,000 | USD | year |
| Business Process Improvement Manager | United States | Remote | 156,000 | 195,000 | USD | year |
What it does
Salary comes from Greenhouse itself. Companies that use Greenhouse's pay-transparency feature attach a pay range to each job; the Actor requests it (?pay_transparency=true on the public board API) and splits it into salaryMin, salaryMax, salaryCurrency and salaryPeriod. How often it is filled depends on the company. Counts from runs on 31 Oct 2026 with the input {"boards": ["<board>"], "maxItems": 1000}:
| board | jobs | with salary |
|---|---|---|
| discord | 41 | 38 |
| airbnb | 202 | 165 |
| databricks | 901 | 491 |
| figma | 140 | 93 |
| stripe | 746 | 0 (Stripe writes pay only in the description: use includeDescription, 24 found) |
When a job has several pay zones (Robinhood lists 3), all of them are in salaryRanges, and salaryMin/salaryMax span them. With includeDescription, a range written only in the text ("Salary: $156,800 - $235,200/yr") is read as well. A job without a published range has null salary fields.
In monitor mode the Actor stores each board's jobs in a named key-value store and returns only jobs that are new, changed (title, location, update time, requisition id or pay range) or removed since the previous run, with changeType. You pay for new and changed jobs only.
Every board you enter gets a status row, so a typo ("_status": "failed", reason board not found (404)) or an empty board is visible in the dataset. The empty case, from a battery run on 31 Oct 2026:
{"_status": "empty", "board": "prisma", "mode": "jobs", "rows": 0, "reason": "board has no open jobs", "total": 0}
A board that exists but has no open jobs (like prisma above) is a successful run with an empty status row, not a failure; a board that cannot be fetched (_status: "failed", for example a 404 typo) gets a failed status row, and the run fails only when no board could be fetched; with some boards fetched it succeeds as partial and you keep their jobs. Rows are capped per board by maxItems, and the run stops at the maximum cost you set. Placeholder requisition ids (ONE, MULTI, See Opening ID) are returned as null.
The data comes from the public boards-api.greenhouse.io JSON API: one request per board, no proxy, no browser. A run over a few boards takes seconds.
Input
| Field | Type | Default | Meaning |
|---|---|---|---|
boards | array of strings | ["airbnb"] | Greenhouse board slugs — the part after boards.greenhouse.io/, for example airbnb, stripe. Full board or job URLs are accepted; only the slug is kept |
mode | enum | jobs | jobs lists every open job; detail fetches full descriptions for specific jobIds; monitor reports only new, changed and removed jobs since the last run |
jobIds | array of integers | [] | For mode: detail: the Greenhouse job ids to fetch in full |
search | string | "" | Keep only jobs whose title, location or department (or description, when included) contains this text. Case-insensitive |
postedSinceDays | integer | null | Keep only jobs first published within the last N days (postedAt at or after the run time minus N days). For "new this week" set 7, for "new this month" set 30 — no monitor state needed. Empty for every open job. Works in jobs, detail and monitor modes |
locations | array of strings | [] | Keep only jobs whose location contains one of these values (case-insensitive, OR within the list). Empty for every location. AND-combined with the other filters |
workplaceTypes | array of strings | [] | Keep only jobs with one of these workplace types (Remote, Hybrid, Onsite; OR within the list). Remote also matches when the location says remote. Empty for every workplace type; jobs with no workplace type are excluded only when this filter is set |
employmentTypes | array of strings | [] | Keep only jobs with one of these employment types (Full-time, Part-time, Contract, Internship, Apprenticeship, Temporary; OR within the list). Empty for every type; jobs with no employment type are excluded only when this filter is set |
minSalary | number | null | Minimum yearly salary: keep only jobs whose salaryMax, converted to yearly (year x1, month x12, hour x2080), is at least this value. Jobs with no published salary are excluded |
salaryCurrency | string | "" | ISO 4217 code (for example CAD) that salary must be in when minSalary is set. Empty for any currency |
hasSalaryOnly | boolean | false | Keep only jobs with a published salary range. Off for every job, including those with null salary |
includeDescription | boolean | false | Add the full description (plain text and HTML), department and offices, and read pay ranges written only in the description. Same single request per board, just a bigger response |
maxItems | integer | 100 | Upper limit on job rows per board, 1 to 1000 (3 boards x 100 = at most 300 rows) |
Example:
{ "boards": ["airbnb"], "mode": "jobs", "maxItems": 20 }
Output
One row per job, then one status row per board, then a summary row as the last row. In Apify Console the "Jobs" table shows the columns most buyers use (title, location, salary, dates, links); the "Full details" view adds ids, language, descriptions and the per-zone salaryRanges. Example values come from the Greenhouse board API captured on 2026-10-31 (the default input's board, airbnb).
| Field | Example | Meaning |
|---|---|---|
id | 8306554 | Greenhouse's job id, stable across runs |
board | airbnb | The board (company) you searched |
title | AirCover Specialist, Claims Experience | Job title |
company | Airbnb | Employer |
location | Canada | The job's location as the board lists it |
workplaceType | Remote | Remote / Hybrid / Onsite, from the company's own field, or Remote when the location says so; null otherwise |
url | https://careers.airbnb.com/positions/8306554?gh_jid=8306554 | The job posting URL |
applyUrl | same as url | The apply link (on Greenhouse boards the posting is the application) |
postedAt | 2026-10-28T14:52:05Z | First-published date, UTC ISO-8601 |
updatedAt | 2026-10-28T14:52:05Z | Last-updated date, UTC ISO-8601 |
applicationDeadline | null | Application deadline, when the board sets one |
internalJobId | 3591434 | The company's internal job id |
requisitionId | null | The company's requisition reference; null when absent or a placeholder like ONE |
language | en | Posting language |
department | Community Support | Primary department (detail / includeDescription only) |
departments | ["Community Support"] | All departments (detail / includeDescription only) |
offices | ["Canada"] | Offices (detail / includeDescription only) |
employmentType | null | Full-time, Part-time, Contract, Internship, Apprenticeship or Temporary, only when the title (or the description, when included) states it; null otherwise |
salaryMin | 58000 | Lowest published pay (across all pay zones of the same currency and period) |
salaryMax | 68000 | Highest published pay |
salaryCurrency | CAD | ISO 4217 currency code |
salaryPeriod | year | year, month or hour |
salaryText | CAD 58,000 - 68,000 per year | The range as one readable string |
salarySource | payTransparency | payTransparency (the company's structured Greenhouse pay range) or description (read from the description text); null when no pay is published |
salaryRanges | [{"min": 58000, "max": 68000, "currency": "CAD", "period": "year", "label": "Canada Annual Pay Range"}] | Every published range, e.g. one per pay zone |
descriptionText | Airbnb was born in 2007 when two hosts welcomed... | Full description as plain text (detail / includeDescription only) |
descriptionHtml | <div class="content-intro"><p>... | Full description as HTML (detail / includeDescription only) |
changeType | new | Monitor mode only: new, changed or removed |
scrapedAt | 2026-10-31T00:00:00Z | When the row was fetched (UTC) |
The status row carries _status (ok, partial, empty, failed), board, mode, rows, reason and total (the board's own job count). The last row is a summary with _status: "summary" and totals: rows, boardsOk, boardsEmpty, boardsFailed, and — in monitor mode — checked, unchanged, new, changed, removed, firstRun, runStatus, charged plus the evidence ids newIds, changedIds, removedIds (the job ids of the event rows delivered in that run, so the summary can be reconciled against the dataset). Every monitor run pushes exactly one summary row; a quiet run that finds nothing new ends successfully with checked jobs examined, unchanged jobs untouched, new 0 and charged 0, and runStatus ok.
Pricing
result: $0.002 per job row delivered, no start fee. 1,000 jobs ≈ $2.00. In monitor mode you pay only for new and changed jobs; unchanged and removed jobs are free.
Monitor recipe
Track hiring signals for one company, and get a webhook whenever something changes:
- Create a task with
{ "boards": ["airbnb"], "mode": "monitor" }. - Schedule it hourly (or daily) in Apify Console.
- Add a webhook for "run succeeded" to push
new/changed/removedrows to Slack, Make or n8n — or export the dataset straight to Google Sheets. - Filter the dataset on
changeTypeto see what actually moved since the previous run. A changed pay range counts aschanged, so you can also watch salary bands move.
FAQ
- How do I find a board slug? Open a company's careers page; if it is a Greenhouse page the slug is the part right after
boards.greenhouse.io/(orjob-boards.greenhouse.io/), e.g.boards.greenhouse.io/airbnb→airbnb. You can paste the whole URL. - Can I search across every company at once? No — Greenhouse's public API is per-board, and there is no global endpoint. Run several boards in one
boardslist instead. - Does it include salary? Yes, whenever the company publishes it. Structured pay-transparency ranges come with every run at no extra cost; with
includeDescriptiona range written in the description text is read as well. Companies that publish no pay getnullsalary fields: nothing is estimated or invented. - Why is
salaryPeriodnull on some rows? The company gave a range but no period, and the amount alone cannot tell (e.g. PLN). The range is still returned. - What if a job closes? The job drops off the board. In
jobsmode it just disappears; inmonitormode it is reported asremoved.
What this does not do
It does not log in, break captchas or access anything behind Greenhouse's Harvest API; it reads only the public board endpoints. It does not guess missing fields (salary when no range is published, department when not published), and it does not search a keyword across all Greenhouse companies.
Other languages
Español
Dale un tablero de Greenhouse — el identificador de la página de empleo de una empresa, por ejemplo airbnb — y obtén cada vacante abierta como filas: puesto, empresa, ubicación, departamento, fecha de publicación, el enlace para postularse y, cuando la empresa lo publica, el rango salarial en números (mínimo, máximo, moneda ISO y periodo). Para usarlo, rellena boards (por ejemplo ["airbnb"]) y pulsa Start; pagas solo por cada empleo entregado.
Deutsch
Gib ein Greenhouse-Board an — den Slug der Karriereseite eines Unternehmens, zum Beispiel airbnb — und erhalte jede offene Stelle als Zeilen: Titel, Firma, Ort, Abteilung, Veröffentlichungsdatum, Bewerbungslink und, wenn das Unternehmen es veröffentlicht, die Gehaltsspanne als Zahlen (Minimum, Maximum, ISO-Währung, Zeitraum). Fülle dafür boards (zum Beispiel ["airbnb"]) aus und klicke auf Start; du zahlst nur pro gelieferter Stelle.
Français
Donnez-lui un board Greenhouse — le slug de la page carrière d'une entreprise, par exemple airbnb — et obtenez chaque offre ouverte sous forme de lignes : intitulé, entreprise, lieu, département, date de publication, lien de candidature et, quand l'entreprise la publie, la fourchette de salaire en chiffres (minimum, maximum, devise ISO, période). Remplissez boards (par exemple ["airbnb"]) puis cliquez sur Start ; vous ne payez que pour chaque offre livrée.
Português
Informe um board do Greenhouse — o slug da página de vagas de uma empresa, por exemplo airbnb — e receba cada vaga aberta como linhas: título, empresa, local, departamento, data de publicação, link de candidatura e, quando a empresa publica, a faixa salarial em números (mínimo, máximo, moeda ISO e período). Preencha boards (por exemplo ["airbnb"]) e clique em Start; você paga apenas por vaga entregue.
Sibling Actors: Ashby Jobs Scraper with Salaries and Lever Jobs Scraper with Salaries (same row shape for the other two big startup ATSs) and Google Jobs API Scraper.
Use it from AI agents (MCP) and Python
AI agents. Add this Actor as a tool in Claude, Cursor, VS Code or any MCP client through the Apify MCP server. The agent reads the input schema, so a plain request is enough.
{"mcpServers": {"greenhouse-jobs-monitor": {"url": "https://mcp.apify.com?tools=redomic/greenhouse-jobs-monitor","headers": {"Authorization": "Bearer <YOUR_APIFY_TOKEN>"}}}}
Python. pip install apify-client, then:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("redomic/greenhouse-jobs-monitor").call(run_input={"boards": ["airbnb"], "mode": "jobs"})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
More from us
- Ashby Jobs Scraper with Salaries: Ashby jobs scraper for any startup careers board (OpenAI, Ramp, Notion and thousands more), with salary ranges as numbers: min, max, currency, period, plus equity and bonus flags
- ATS Jobs Search: Greenhouse, Lever & Ashby Jobs API: Search 328,000+ open jobs from 11,000+ companies on Greenhouse, Lever and Ashby in one run
- Google Jobs Scraper - Job Postings API: Google Jobs and job postings scraper: get job title, company, location, posted date, salary, full description and every apply link for any search
- Google Trends API: Trending Now & Interest Over Time: Trending-now searches and new-trends alerts/monitoring per country with the news behind them, plus interest over time, interest by region, and related and rising queries for any keyword
- Lever Jobs Scraper with Salaries: Lever jobs scraper for any company's careers page (Palantir, Spotify, Zoox, Shield AI and thousands more): flat rows with title, team, location, workplace, commitment, apply link, salary as numbers and the full description merged