Greenhouse Jobs Scraper & API
Pricing
from $1.00 / 1,000 job results
Greenhouse Jobs Scraper & API
Search 5,300+ Greenhouse job boards at once, or scrape any board by URL, token or company name. Live jobs with structured pay-transparency salary ranges, ISO countries, workplace, seniority, function, new/closed detection and hiring profiles. $1 per 1,000 jobs.
Pricing
from $1.00 / 1,000 job results
Rating
0.0
(0)
Developer
Dennis
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Security
Limited permissionsShare
Get every open job from any Greenhouse job board, with real salary ranges. Pass a board URL, a board token or just a company name, and get clean, normalized job records plus an optional hiring profile per company.
Greenhouse is the applicant tracking system behind the careers pages of thousands of tech companies, including Airbnb, Stripe, Figma, Discord, GitLab, Databricks, Coinbase, Anthropic and Reddit. This Actor reads the official, keyless Greenhouse Job Board API live at run time: no browser, no login, no proxy, no API key, and no stale database. If a job is in your dataset, it is on the employer's board right now.
No company list? Leave companies empty and the Actor searches 5,300+ known Greenhouse boards at once for your keywords, countries, functions and salary filters, newest jobs first.
Why this Actor
- Search all of Greenhouse, live. Don't know which companies to watch? Leave
companiesempty. The Actor scans its directory of 5,300+ live Greenhouse boards (190,000+ open jobs when the directory was built) and returns the newest matching jobs. Every result is read from the employer's board during your run, so there are no ghost jobs from a stale database. - Structured salaries, not guesses. Greenhouse employers publish pay-transparency ranges in a separate, structured block. This Actor requests that block and turns it into clean
payRangesper zone (for example "CA, NY, CT, NJ" or "US Zone 2"), with currency and period. In a live test on 44 boards (9,437 postings, November 2026), 48% of all postings had a structured salary range, and another 12% had one in the description text. Every salary says where it came from (salarySource), and on-target earnings are flagged (salaryIsOte). - A readable salary line for every job.
salaryDisplaygives youUSD 160,000 - 200,000 per year, ready for a spreadsheet, a job board or an AI agent. - Honest data cleaning. Duplicate zones are merged, OTE ranges are kept apart from base pay, obvious employer typos are flagged (
isSuspect), and a range typed in thousands ("45.6 - 57") is corrected when the description confirms it. Bonus, commission, equity and deal-size amounts in the description are never reported as salary. - Countries that work. Greenhouse locations are free text ("SF • NYC • Remote", "Dublin", "US-Chicago", "Toronto, ON, CA"). The Actor resolves them to ISO country codes:
countrywhen a posting is in one country,countriesfor every country it covers. In the same live test, 99% of postings got at least one country. The country filter uses these codes, soCAmeans Canada, not California. - One record per job, if you want. Large boards post the same job in several locations as separate postings (about 1 in 9 postings in our test). Turn on
collapseMultiLocationto get one record per job with the other locations inalsoPostedIn. That gives you fewer duplicates and a lower cost. - New and closed roles. A snapshot per board marks
isNewjobs and reports closed roles in the company profile. WithonlyNew, jobs that were skipped because of your per-company cap or your max-charge limit are delivered on the next run, not lost. - Company hiring profiles: open roles by function, seniority, department and location, salary disclosure rate and median salary range, leadership openings, a 0–100 hiring-momentum score and readable signals.
What you get per job
Title, company, board token, Greenhouse job id, requisition id, internal job id, department(s), offices, location, country / countries, workplace type (remote / hybrid / onsite), employment type, seniority, job function, first-published date, last-updated date, days open, application deadline, posting language, job URL and apply URL, the salary fields (salaryMin, salaryMax, salaryCurrency, salaryPeriod, salarySource, salaryIsOte, salaryDisplay), the full payRanges list, and optionally the full description as plain text or HTML.
Three ways to run
outputMode | Dataset | Charged |
|---|---|---|
jobs_and_profiles | One profile per employer plus filtered job records | company-profile + job-result |
jobs_only | Job records only | job-result |
profiles_only | One profile per employer, no job records | company-profile only |
profiles_only is the cheapest way to watch many employers. The Actor still reads each full board, so new/closed roles, momentum and salary statistics stay accurate, but it stores no job records.
Search mode: no company list
Leave companies empty to search every board in the Actor's directory: 5,300+ Greenhouse boards found in the open Common Crawl web index and verified live against the Greenhouse API, each with at least one open job when the directory was built. Example: remote data engineering jobs in the US paying at least $180,000.
{"companies": [],"keywords": ["data engineer", "analytics engineer"],"countries": ["US"],"workplaceTypes": ["remote"],"minSalary": 180000,"salaryCurrency": "USD","outputMode": "jobs_only","collapseMultiLocation": true,"maxSearchResults": 100}
How it differs from company mode:
- Every board is read live as a light list (no descriptions). Only jobs that can still match are then fetched in full and checked against all filters, newest first, until
maxSearchResultsis reached. keywordsmatch the job title (company mode also searches the description). Salary filters use the structured pay-transparency range.- ISO country codes skip boards that had no jobs in those countries, which makes country searches faster.
maxJobsPerCompanystops one large employer from filling your results.onlyNewworks per saved search: a scheduled run returns only jobs that the same search (same filters) has not delivered before.- Search mode returns job records only; company profiles need a company list. A
SEARCH_SUMMARYrecord in the key-value store shows how many boards were scanned and how many jobs matched.
The directory covers the Greenhouse employers that are visible on the public web, not every Greenhouse customer. A company that is missing can always be passed in companies.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
companies | array of strings | Discord's board URL | Leave empty for search mode. Board URLs (https://job-boards.greenhouse.io/discord; boards.greenhouse.io, job links and embed links work too), board tokens (discord), company websites (figma.com) or company names (Figma). |
outputMode | enum | jobs_and_profiles | jobs_and_profiles, jobs_only (no profile charge) or profiles_only (hiring signals without job records). |
keywords | array of strings | [] | A job matches when its title or description contains any of these words. |
excludeKeywords | array of strings | [] | Skip jobs whose title contains any of these words, e.g. intern, contract. |
departments | array of strings | [] | Substring match on the employer's own Greenhouse department names. |
countries | array of strings | [] | ISO-2 codes or country names, matched against the parsed countries of each job. |
workplaceTypes | enum array | [] | Only remote, hybrid or onsite jobs. Unknown workplace types are excluded when this filter is active. |
functions | enum array | [] | engineering, data_ai, product, design, sales, marketing, customer_success, operations, finance, people_hr, legal_compliance, other. |
seniorities | enum array | [] | intern, junior, mid, senior, staff_principal, lead, manager, director, vp, executive. |
languages | array of strings | [] | Posting languages as ISO 639-1 codes from Greenhouse, e.g. en, de, nl. |
onlyWithSalary | boolean | false | Only jobs with a published salary (structured or from the description). |
minSalary | integer | 0 | Minimum top of the range, as an annual amount (hourly × 2080, monthly × 12). Jobs without a salary are excluded when set. |
salaryCurrency | string | "" | ISO code such as USD or EUR, used with minSalary / onlyWithSalary so you compare like with like. |
postedWithinDays | integer | 0 | Only jobs first published in the last N days. 0 = no limit. |
onlyNew | boolean | false | Only jobs that were not on the board in the previous run (plus new jobs a previous run could not deliver). The first run is the baseline and returns everything. |
collapseMultiLocation | boolean | false | One record per job: other locations of the same job go into alsoPostedIn, all countries into countries. |
includeDescription | boolean | false | Add the full description (up to 20,000 characters) at no extra cost. |
descriptionFormat | enum | text | text (clean plain text, best for search and LLMs) or html (the original markup, for job boards that render it). |
maxJobsPerCompany | integer | 200 | Maximum job records delivered per board after filtering. |
maxBoards | integer | 50 | Safety cap on the number of companies processed in one run. |
maxSearchResults | integer | 100 | Search mode only: total job records across all boards, newest first. |
An empty companies list switches to search mode; profiles_only needs a company list and fails fast with a clear message otherwise. Numeric fields also accept numbers sent as strings ("150000"), which helps when the Actor is called by an AI agent.
How company names are resolved
- Greenhouse URL (board, job, embed or API link): exact, no guessing (
detectionMethod: "ats_url"). - Company website: the Actor looks for a Greenhouse link on
/careers,/jobsand the home page (careers_page). - Board token or company name: the Actor checks the token as given, then name variants such as
hugging-faceandhuggingface, against Greenhouse's board endpoint (slug_guess). The profile then shows the board name and URL so you can confirm it is the intended company.
Companies that use another ATS (Lever, Ashby, Workday, …) have no Greenhouse board and come back as a free not_found profile.
Example output
{"recordType": "job","jobKey": "greenhouse:instacart:8250324","company": "Instacart","jobId": "8250324","title": "Account Manager","department": "Ad Sales","location": "United States - Remote","country": "US","countries": ["US"],"workplaceType": "remote","employmentType": "full_time","seniority": "mid","jobFunction": "customer_success","publishedAt": "2026-10-02T23:10:53.000Z","daysOpen": 31,"isNew": null,"url": "https://instacart.careers/job/?gh_jid=8250324","salaryMin": 75000,"salaryMax": 111000,"salaryCurrency": "USD","salaryPeriod": "year","salarySource": "structured","salaryIsOte": false,"salaryDisplay": "USD 75,000 - 111,000 per year","boardToken": "instacart","requisitionId": "MH167","internalJobId": "3569489","language": "en","offices": ["Remote - United States"],"alsoPostedIn": [],"payRanges": [{ "label": "WA", "min": 86000, "max": 106500, "currency": "USD", "period": "year", "isOte": false, "isSuspect": false },{ "label": "All other states", "min": 75000, "max": 93000, "currency": "USD", "period": "year", "isOte": false, "isSuspect": false },{ "label": "CA, NY, CT, NJ", "min": 90000, "max": 111000, "currency": "USD", "period": "year", "isOte": false, "isSuspect": false },{ "label": "OTE Range", "min": 117500, "max": 148000, "currency": "USD", "period": "year", "isOte": true, "isSuspect": false }]}
(Shortened: the real record also has companySlug, ats, team, updatedAt, firstSeenAt, applyUrl, description, applicationDeadline, departments and every pay zone.) The summary salary spans all base zones; the OTE range stays in payRanges with isOte: true.
The company_profile record adds openJobs, jobsPostedLast7Days, jobsPostedLast30Days, newJobsSinceLastRun, closedJobsSinceLastRun, closedJobTitles, netChangeSinceLastRun, salaryDisclosedShare, medianSalaryMin, medianSalaryMax, medianSalaryCurrency, hiringMomentum, hiringMomentumScore, topFunction, jobsByFunction, jobsBySeniority, topDepartments, topLocations, openJobsHistory and signals.
Use cases
- Compensation research: Greenhouse employers in US states with pay-transparency laws publish salary ranges per zone. Collect them per role, level and location, with the currency and period already normalized.
- Job boards and newsletters: build a live Greenhouse feed, one record per job, filtered on remote, country and minimum salary, and use
onlyNewon a schedule to publish only fresh roles. - Recruiting and sourcing: pull every open role from a list of target employers into one schema.
- Sales and account intelligence: hiring is a buying signal. Track whether a target account is growing engineering, sales or security teams, and which roles closed.
- AI agents and RAG pipelines: feed clean records with stable ids, a readable
salaryDisplayand plain-text descriptions into an agent or vector store. The Actor is available as an MCP tool.
How it works
- Resolve each input to a Greenhouse board token (URL, careers page or token/name check).
- Download the whole board in one request:
GET https://boards-api.greenhouse.io/v1/boards/{token}/jobs?content=true&pay_transparency=true. - Normalize every posting with the shared ATS engine (workplace, seniority, function, dedupe keys) and add the Greenhouse fields: pay ranges, countries, requisition id, offices, departments, deadline and language.
- Compare with the named snapshot store to mark new and closed roles.
- Depending on
outputMode, push the company profile and/or the filtered job records, charging one event per delivered record, and save the snapshot after delivery.
In search mode step 2 is replaced by a light read of every directory board (GET .../jobs, gzip, no descriptions), followed by GET .../jobs/{id}?pay_transparency=true for the jobs that can still match, newest first.
The run has an internal deadline below the platform timeout, so a long company list ends cleanly and reports skipped boards instead of timing out. Once your max-charge limit is reached, the Actor stops reading further boards.
Pricing
Pay per event, no rental:
| Event | Price | Charged when |
|---|---|---|
apify-actor-start | $0.00005 | Actor start (Apify default). |
job-result | $0.001 | One job record is stored in the dataset. Descriptions are included at no extra cost. |
company-profile | $0.01 | One resolved board gets a company hiring profile. |
board-search | $0.01 | Once per search-mode run (empty companies): covers reading every board in the directory. |
1,000 jobs cost about $1.00 plus the start event. jobs_only avoids the profile charge, profiles_only avoids all job charges, and collapseMultiLocation avoids paying for duplicate postings. A search-mode run costs $0.01 plus $0.001 per delivered job, so 100 search results cost about $0.11. Not-found boards and error profiles are free. Every run respects your max-charge limit.
A full search over all 5,300+ boards takes about 1.5 minutes; a search narrowed to one country (ISO code) is much faster, for example about 30 seconds for the Netherlands.
Legal and data sources
- The source is Greenhouse's official, documented Job Board API, which employers enable to publish their vacancies. No login, no paywall, no CAPTCHA or anti-bot circumvention, no proxy.
- Job postings are company data that employers publish to attract candidates. The Actor does not build personal profiles and does not extract recruiter names or e-mail addresses. Greenhouse's internal custom fields (such as recruiting team or cost center) are not exported; only workplace, time type and country metadata are used for normalization.
- The Actor is not affiliated with Greenhouse Software or with any employer. Employer terms may apply to your use of the data; you are responsible for your own compliance and for how you store or republish the records.
- A board that returns an error is reported as a per-board profile and does not block the rest of the run.
When should an AI agent use this?
Use this Actor when a user asks questions like:
- "Which engineering roles is Figma hiring for right now, and what do they pay?"
- "List remote jobs at GitLab, Discord and Reddit paying at least $150,000."
- "Which Greenhouse jobs at these companies are open in Canada?"
- "Is Databricks still growing its sales team? Compare this week with last week."
- "What share of Coinbase's open roles has a published salary range?"
- "Build a feed of new Greenhouse job postings for these ten companies."
- "Find remote staff engineer jobs in the US paying over $200k at any company that uses Greenhouse." (search mode: leave
companiesempty)
The input is a short list of board URLs, tokens or company names. The output is one flat JSON record per job or profile, with stable ids, links and a readable salary line, so an agent can filter, summarize or store it without extra parsing.
FAQ
Do I need a Greenhouse API key? No. The Job Board API is public and keyless. The private Harvest API, which does need a key, is not used.
Where do I find the board token?
It is the last part of the board URL: https://job-boards.greenhouse.io/airbnb → airbnb. Some companies host their careers page on their own domain. Pass that domain and the Actor looks for the Greenhouse link, or pass the token directly.
Where does the salary come from?
Preferably from Greenhouse's structured pay-transparency block (salarySource: "structured"), with exact amounts per zone entered by the employer. Otherwise from a sentence in the description that is about pay ("description"). Bonus, commission, equity and deal-size amounts are skipped. If neither exists, the salary fields are null. The Actor never invents a range.
What does salaryIsOte mean?
Sales roles often publish only on-target earnings (base plus commission). Those ranges are returned, but with salaryIsOte: true and "(on-target earnings)" in salaryDisplay, so you never mistake them for a base salary.
Why is a salary marked hourly? Greenhouse sends no period with a pay range. The Actor reads the range label and description (for example "Hourly Rate") and checks the result against the amount, so a $24 rate is never treated as an annual salary.
Why do country and countries differ?
country is set when a posting is in a single country. A posting such as "London OR Dublin" has country: null and countries: ["GB", "IE"]. The country filter checks countries.
Are EU-hosted boards supported?
Not yet. Boards on job-boards.eu.greenhouse.io have no public Job Board API host. Those inputs return a free not_found profile with an explanation.
Can it search every Greenhouse employer at once?
Almost. Greenhouse has no public global index, so the Actor ships its own directory of 5,300+ live boards, built from the open Common Crawl web index and verified against the Greenhouse API. Leave companies empty to search them all. Employers that are not visible on the public web can be missing; pass them in companies.
How does onlyNew work?
The Actor stores a snapshot per board in a named key-value store. The first run is the baseline. Later runs return jobs that were not in the previous snapshot. New jobs that a run could not deliver (per-company cap, max charge) are kept and delivered next time. Schedule the Actor, for example daily, to get a meaningful signal.
Are closed jobs returned as records?
Closed jobs are summarized in the company profile (closedJobsSinceLastRun and closedJobTitles), not emitted as job records.
Why is workplaceType often unknown?
Many employers do not fill Greenhouse's workplace field. The Actor uses that field when present, otherwise words like "Remote" or "Hybrid" in the location or office names, and leaves the value unknown rather than guessing.
Keywords
Greenhouse jobs API, Greenhouse job search, search all Greenhouse jobs, Greenhouse scraper, scrape Greenhouse jobs, Greenhouse job board, boards.greenhouse.io scraper, job-boards.greenhouse.io, Greenhouse careers page, Greenhouse salary data, pay transparency salary ranges, salary range scraper, ATS job scraper, job board API, hiring signals, new job alerts, tech job data, recruiting data.
Related Actors
- Workday Jobs Scraper & API: the same normalized schema for Workday career sites, used by large enterprises.
- Career Sites ATS Job Feed & Company Hiring Signals: the multi-ATS version (Greenhouse, Lever, Ashby, Workday, Workable, Recruitee, SmartRecruiters, Personio) with automatic ATS detection. Use this Greenhouse Actor when you want structured pay ranges, country resolution and the extra Greenhouse fields.
Changelog
- 0.1 (2026-11-03): initial version. Search mode: leave
companiesempty to search a bundled directory of 5,300+ live Greenhouse boards (built from the Common Crawl web index, verified against the Greenhouse API), newest matching jobs first, withmaxSearchResultsandonlyNewper saved search. Board resolution by Greenhouse URL (board, job, embed, API), careers page or token/name check. One-request board download with pay transparency: deduplicated pay ranges with period inference, OTE and suspect-range flags, thousands-typo correction,salaryDisplay,salaryIsOte. Description salary only from pay sentences. Country resolution (country/countries) from location parts, offices, state/province codes and major cities. Optional one-record-per-job (collapseMultiLocation), plain-text or HTML descriptions. New/closed snapshots that keep undelivered new jobs for the next run, and a company hiring profile with salary statistics.jobs_and_profiles/jobs_only/profiles_onlymodes. Keyword, excluded-keyword, department, country, workplace, function, seniority, language, salary, posted-within and only-new filters.maxBoardssafety cap, run deadline, stop on max charge, PPE pricing.
Changelog policy
This Actor follows semantic versioning for its input and output contract. New optional fields are additive; removing or renaming a field is a breaking change and gets a new minor version with a release note.