Greenhouse Jobs Scraper & Monitor: Job Board Export avatar

Greenhouse Jobs Scraper & Monitor: Job Board Export

Pricing

from $0.98 / 1,000 greenhouse job results

Go to Apify Store
Greenhouse Jobs Scraper & Monitor: Job Board Export

Greenhouse Jobs Scraper & Monitor: Job Board Export

Export live jobs from known public Greenhouse boards. Get job details or compare snapshots for new, updated and verified removed posts, with coverage reports.

Pricing

from $0.98 / 1,000 greenhouse job results

Rating

0.0

(0)

Developer

Cliqto Media

Cliqto Media

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 days ago

Last modified

Categories

Security

Limited permissions

Share

Export live jobs from public Greenhouse job boards (boards.greenhouse.io and job-boards.greenhouse.io, US and EU) to track hiring at companies you follow, feed your own job board, or get alerts about new, updated and removed jobs. Add a board token or board URL, or exact job IDs. The Actor uses the public Greenhouse Job Board API: no login, browser or proxy.

Start with boards: ["proton"]; the Input form has this small example filled in. Pricing is $0.0014 per start + $1.40 per 1,000 saved job rows on the Free plan (down to $0.98 on Gold and above) at the default 512 MB memory. Check RUN_SUMMARY when a board is empty, a filter removes jobs, or a source request fails.

Greenhouse jobs: public board input, current job rows and explicit snapshot changes

Table of contents

What it does

The Actor has three modes:

  • Snapshot: all current jobs of one or more known Greenhouse boards, with optional filters by title, description, location, department, office and date.
  • Details: exact jobs by board and job ID, with public application questions and published pay ranges when you need them.
  • Monitor: compare a board with a snapshot from an earlier run and get only new, updated and verified removed jobs.

Every job has a stable ID (board:jobId), title, location, departments, offices, dates and links. The job description is optional. A separate RUN_SUMMARY report shows, for each board or job, whether it was read in full, empty, not found or failed.

Good fit

  • Export the open jobs of companies that use Greenhouse.
  • Feed your own job board or job alert with current roles and stable IDs.
  • Hiring research: which teams, offices and locations a company is hiring for.
  • Change tracking: new and removed jobs between two runs, with proof that both runs read the full board.

Not a fit: finding all companies that use Greenhouse, a global job search, private or internal jobs, closed-job history, submitting applications, contact enrichment, or other ATS platforms. A removed job means "seen missing", not an employer-confirmed closing date.

πŸ‘‰ Try it now: open the input form

How it works

  1. You give board tokens, board URLs or exact jobs. Each one is checked and normalized; duplicates are read once.
  2. The Actor reads each board from the public Greenhouse Job Board API (US or EU) in one request, plus one detail request per job only when you ask for questions or pay. It does not use a browser, login or proxy.
  3. Your filters and row caps are applied. In monitor mode the full board is compared with your earlier snapshot.
  4. It saves one Dataset row per job (or per change), a RUN_SUMMARY report and, in snapshot and monitor modes, a SNAPSHOT for your next monitor run.

πŸ‘‰ Try it now: open the input form

Quick start

Input form: box 1 mode, box 2 board tokens or URLs with the proton example, box 3 include job description, box 4 maximum jobs per board and total, box 5 Start

  1. Open the Input tab. Keep Mode on Current snapshot (box 1 in the picture).

  2. Keep the filled board proton, or paste your board token or URL such as https://job-boards.greenhouse.io/figma (box 2). Click + Add for more companies in one run.

  3. Optional: turn on Include job description for the full text (box 3).

  4. Keep the caps at 100 for a first test (box 4).

  5. Click Start (box 5).

  6. Open the Output tab. Each row is one job; check title and location (box 6) and the job link absoluteUrl. Open Storage β†’ Key-value store β†’ RUN_SUMMARY for each board's status and counts.

    Output table: one row per Greenhouse job with stable ID, change, title and location (box 6), board, updated date and job URL

Expected result: one row per current Proton job. The board had 20 jobs when checked on 28 October 2026; live jobs change. An API call without boards reads the figma board, so always send your own boards.

πŸ‘‰ Try it now: open the input form

Use cases

Your taskSettingsUseful fields
Export the jobs of a companymode: snapshot, boardsstableId, title, location, absoluteUrl
Job board or job feedincludeContent: truecontentText, departments, firstPublishedAt
Engineering roles in Europe onlytitleKeywords, locationstitle, location, offices
Application questions or salary of a jobmode: details, jobs, detail optionsquestions, payRanges
Alert on new and removed jobsmode: monitor, baselineStoreIdchangeStatus, changedFields, observedRemovedAt

πŸ‘‰ Try it now: open the input form

Input

Input fields

All fields are top-level. Array items are strings. Null values, empty target arrays, empty filter arrays and unknown fields are rejected; remove an optional filter to turn it off.

FieldType / allowed valuesDefault when omittedForm example / notes
modesnapshot, details, monitorsnapshotsnapshot
boards1–100 board tokens or board URLs["figma"] in snapshot and monitor["proton"]; not used in details mode
jobs1–500 exact jobs, token/jobId or job URLnone; required in details modefor example proton/4555348101
baselineStoreIdstore ID, 5–80 letters, digits, _ or -nonemonitor only; the store is read, never changed
monitorOutputchanges_only or allchanges_onlyall also returns unchanged jobs
includeContentbooleanfalsejob description as HTML and plain text
includeQuestionsbooleanfalsepublic application questions, no answers
includePayTransparencybooleanfalsepay ranges the employer publishes
titleKeywordsup to 20 strings, ≀200 characters eachno filtertitle contains any keyword
contentKeywordssameno filterdescription contains any keyword; needs includeContent: true
locationssameno filterlocation.name contains any value
departmentssameno filterdepartment name contains any value
officessameno filteroffice name contains any value
firstPublishedAfterISO date or timeno filterfirst published on or after
updatedAfterISO date or timeno filterupdated on or after
maxJobsPerBoard1–5,0005,000100; row cap per board
maxJobsTotal1–10,00010,000100; row cap per run, monitor changes included

baselineStoreId was called baselineKeyValueStoreId before version 0.6. The old name still works in API input; if you send both, they must have the same value.

Interacting settings

  • Board URLs. Accepted hosts: boards.greenhouse.io, job-boards.greenhouse.io, boards.eu.greenhouse.io and job-boards.eu.greenhouse.io, HTTPS only. A board URL is /{token}, a job URL is /{token}/jobs/{id}; legacy /embed/job_app?for={token} works for boards. Company career pages on other domains are rejected.
  • Filters. Case-insensitive text matches, not regular expressions. Values inside one filter use OR; different filters use AND. A date-only value means midnight UTC. Jobs without a date never pass a date filter.
  • Description filter. contentKeywords needs includeContent: true; without it there is no text to match.
  • Questions and pay. Each needs one extra request per job; both options share it. On large boards this makes runs slower.
  • Caps. The full board is always read and checked first; caps limit saved rows, not the source response. A capped board is reported as partial.
  • Monitor. Keep boards, content and detail options the same between the earlier and the new run; otherwise the snapshots are not comparable.

Input examples

Several boards, engineering roles with descriptions:

{"mode":"snapshot","boards":["figma","https://job-boards.eu.greenhouse.io/proton"],"includeContent":true,"titleKeywords":["engineer"],"maxJobsPerBoard":100,"maxJobsTotal":200}

One job with questions and pay:

{"mode":"details","jobs":["proton/4555348101"],"includeContent":true,"includeQuestions":true,"includePayTransparency":true}

This job was live when checked; use a current job ID.

Monitoring, first run (creates the baseline, every job has changeStatus: baseline):

{"mode":"monitor","boards":["proton"]}

Next run: pass RUN_SUMMARY.currentSnapshotStoreId from the first run:

{"mode":"monitor","boards":["proton"],"baselineStoreId":"<store ID from the first run>"}

Each run writes its own new snapshot store and never changes the earlier one, so several runs can compare against the same baseline. A schedule does not pass the store ID for you: your caller keeps the latest currentSnapshotStoreId and sends it next time. Keep (name) a store you need longer than your Apify data retention.

πŸ‘‰ Try it now: open the input form

Output

Output fields

Each Dataset row is one current job or one verified removed job. All fields are always present; null means not available, not requested or not used in this mode.

FieldTypeMeaning
schemaVersioninteger1
recordTypestringjob
stableIdstring{board}:{jobId}, lowercase board; use it to join runs
boardTokenstringboard token
boardRegionstringus, eu or unknown
jobIdstringGreenhouse job post ID
internalJobIdstring/nullemployer internal job ID
requisitionIdstring/nullemployer requisition ID
titlestringjob title, up to 2,000 characters
locationobject/null{name} as published; not geocoded
departmentsarraydepartment objects (id, name, parent_id, child_ids); may be empty
officesarrayoffice objects, may include location; may be empty
metadataarray/nullemployer custom fields (id, name, value, value_type)
languagestring/nulllanguage of the job post
absoluteUrlstringjob and apply page on the employer site
greenhouseUrlstringjob page on Greenhouse
firstPublishedAtstring/nullfirst published, UTC ISO
updatedAtstring/nulllast updated at the source, UTC ISO
contentHtmlstring/nulldescription HTML, with includeContent
contentTextstring/nulldescription as plain text, with includeContent
questionsobject/nullpublic questions, location, compliance and demographic questions, with includeQuestions
payRangesarray/nullpublished pay ranges with the employer's keys (min, max, currency, title), with includePayTransparency
retrievedAtstringwhen the Actor read the job, UTC ISO
changeStatusstring/nullmonitor: baseline, new, updated, unchanged, removed
matchTransitionstring/nullmonitor: entered, left, none (job started or stopped matching your filters)
changedFieldsarraymonitor: names of changed fields; empty if none
previousHashstring/nullmonitor: content hash in the earlier snapshot
currentHashstring/nullcontent hash now; null for removed jobs
observedRemovedAtstring/nullmonitor: when the job was seen missing
sourceEvidenceobjectAPI host and request kind used for this row

A removed row keeps the job's last known fields and previousHash, with currentHash: null. A job that stops matching your filters is matchTransition: left, not a removal.

Output entities and surfaces

SurfaceWhat it holds
Dataset, view Jobs and verified changescurrent jobs and verified removals
RUN_SUMMARY (Key-value store)status and counts per board or job, limits, baseline status, saved and charged rows, runComplete, runFailed, limitedByUserLimits, currentSnapshotStoreId
SNAPSHOT (Key-value store)all jobs of each board before filters, with hashes; the baseline for your next monitor run; not written in details mode

Per board or job, RUN_SUMMARY.inputs[].state is one of: COMPLETE (read in full), EMPTY (board has no jobs), NOT_FOUND, PARTIAL (cap or detail failure), DRIFTED (unexpected source format), FAILED or UNPROCESSED. A SUCCEEDED run alone does not mean every board was read in full: a run stopped only by your maxJobsPerBoard, maxJobsTotal or maximum total charge ends SUCCEEDED with runComplete: false and limitedByUserLimits: true. A run ends FAILED (runFailed: true) when a board is FAILED, DRIFTED, UNPROCESSED, PARTIAL because of a source error, or the dataset write fails. After 8 Greenhouse timeouts, network or server errors in a row, the run stops calling the source and marks the boards it did not read UNPROCESSED with errorCode: SOURCE_UNAVAILABLE; run it again later.

Output example

A trimmed row from the Proton example:

{"schemaVersion":1,"recordType":"job","stableId":"proton:4555348101","boardToken":"proton","boardRegion":"eu","jobId":"4555348101","title":"Head of Growth","location":{"name":"London, Paris, Geneva"},"absoluteUrl":"https://job-boards.eu.greenhouse.io/proton/jobs/4555348101","changeStatus":null,"changedFields":[],"contentHtml":null}

Use case β†’ fields

Use caseFields to use
Job feedstableId, title, location.name, departments[].name, absoluteUrl, contentText
Hiring researchboardToken, departments, offices, firstPublishedAt
Salary researchpayRanges, title, location
Change alertschangeStatus, changedFields, matchTransition, observedRemovedAt

πŸ‘‰ Try it now: open the input form

Pricing

Pricing unit

Pay per event. Apify charges the standard apify-actor-start event automatically: $0.0014 per GB of run memory, at least one event. At the default 512 MB (and up to 1 GB) that is $0.0014 per run; at 2 GB it is $0.0028. Then one job-result event per saved job row or verified change:

PlanPer saved rowPer 1,000 rows
Free$0.0014$1.40
Bronze$0.00126$1.26
Silver$0.00112$1.12
Gold, Platinum, Diamond$0.00098$0.98

Descriptions, questions, pay, RUN_SUMMARY and SNAPSHOT have no separate fee. Skipped and filtered jobs, unchanged jobs in changes-only monitoring and summary records are not charged. Invalid input pays only the start.

Cost examples

Run at 512 MB, Free planActor event charge
Empty, fully filtered or unchanged run, 0 rows$0.0014
10 rows$0.0154
The Proton example, 20 rows$0.0294
1,000 rows$1.4014
10,000 rows (maximum per run)$14.0014

There is no separate platform-usage fee for buyers on this pricing. To cap a run's cost, set Apify's maximum total charge (maxTotalChargeUsd in the API); allow at least the start amount plus one row ($0.0028 at 512 MB). The run stops cleanly at the cap, ends SUCCEEDED and reports the result as incomplete (limitedByUserLimits: true). maxJobsPerBoard and maxJobsTotal cap rows, not dollars.

πŸ‘‰ Try it now: open the input form

Limits

  • Up to 100 boards or 500 exact jobs per run; up to 5,000 saved rows per board and 10,000 per run.
  • Four boards are read at a time and at most eight detail requests at once. A request is tried up to three times for network errors, 408, 429 and 5xx; redirects are not followed. Board responses are capped at 64 MiB and detail responses at 2 MiB.
  • The Actor works for at most 900 seconds. With a shorter run timeout it keeps 15 seconds to save results. Memory 256–2,048 MB, default 512 MB.
  • A board counts as complete only when its job count matches the source and the format is as expected. Removals are reported only when both snapshots of that board are complete and comparable.
  • Only public jobs of boards you supply. Descriptions, pay and questions are only what the employer publishes; nothing is guessed.

πŸ‘‰ Try it now: open the input form

API, export and integrations

  • API: start cliqtomedia/greenhouse-jobs-monitor-scraper with the same input JSON through the Apify API or an Apify client, then read the default Dataset and the RUN_SUMMARY record of the default Key-value store.
  • Export: download the Dataset as JSON, CSV or Excel. For CSV pick flat fields such as stableId, title, location.name, boardToken, absoluteUrl, changeStatus; keep JSON for questions and metadata.
  • Scheduling: snapshot mode works on any schedule. For monitor mode, your caller must pass the latest currentSnapshotStoreId as baselineStoreId on each run.

Source documentation: Greenhouse Job Board API.

Use with AI agents (MCP)

  • MCP server with only this Actor: https://mcp.apify.com?tools=cliqtomedia/greenhouse-jobs-monitor-scraper.
  • Smallest useful input: {"mode": "snapshot", "boards": ["proton"]}.
  • Key output fields: stableId (stable job ID), title, location.name, absoluteUrl (job page), changeStatus (monitor); RUN_SUMMARY.inputs[].state tells why a board gave no rows.
  • The Proton board returns about 20 rows in about 3 seconds for $0.0294 at 512 MB on the Free plan. Supply known board tokens; the Actor does not search Greenhouse.

πŸ‘‰ Try it now: open the input form

Troubleshooting

  • URL rejected: use one of the four Greenhouse board hosts and a board or job path. A company careers page on its own domain does not work; find the board token in its Greenhouse links.
  • No rows: open RUN_SUMMARY. EMPTY is a board with no jobs; a complete board with zero matches means your filters removed everything; NOT_FOUND means the token or job does not exist.
  • Fewer rows than expected: check caps, PARTIAL boards, limitedByUserLimits and filters.
  • Monitor run has no rows: with changes_only, unchanged jobs are only counted in RUN_SUMMARY. Use monitorOutput: all to see them.
  • Baseline error: the store ID must come from an earlier run with the same boards and options. A missing, damaged or different baseline stops the comparison; no new baseline is created silently.
  • Timeout or rate limit: retry later with fewer boards or without questions and pay. Do not retry invalid URLs or 404s.

πŸ‘‰ Try it now: open the input form

FAQ

Do I need a Greenhouse account?

No. Only public job boards are read through the public Greenhouse Job Board API.

Can I get every job on Greenhouse?

No. You supply the boards. There is no company discovery or global search.

Does a repeat run return only new jobs?

Only in monitor mode with baselineStoreId. Snapshot mode returns all current jobs every time.

Is an empty run free?

No. It has the $0.0014 start charge at 512 MB and no row charges.

Do pay ranges and questions always exist?

No. They appear only when the employer publishes them. The Actor never estimates salary and never reads applicant data.

Is a removed job closed?

It was seen missing from a complete board compared with a complete earlier snapshot. The employer's closing date or reason is not known.

πŸ‘‰ Try it now: open the input form

πŸ‘‰ Try it now: open the input form

Support

Open an issue in this Actor's Apify Issues tab. Include the run ID, mode, input without private data and the relevant RUN_SUMMARY entry. Never share tokens, cookies or applicant answers.

Greenhouse is a trademark of its owner. This Actor is not affiliated with or endorsed by Greenhouse Software, Inc. You are responsible for how you use and keep public job content.

πŸ‘‰ Try it now: open the input form