Greenhouse Jobs Scraper & API - 4,600 Boards Built In
Pricing
$1.50 / 1,000 job postings
Greenhouse Jobs Scraper & API - 4,600 Boards Built In
Open job postings from Greenhouse ATS boards, read live from the official Job Board API. Name the companies, or use the built-in directory of 4,600 verified board slugs and see which companies are hiring without supplying one. One row per posting, pay per row.
Pricing
$1.50 / 1,000 job postings
Rating
0.0
(0)
Developer
Bruce McGinley
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Greenhouse Jobs Directory
Open job postings from any company that hires through Greenhouse, read live from Greenhouse's official Job Board API. Name the companies you want, or leave the list empty and read from the built-in directory: 4,636 boards verified live on 2026-09-08, so you can pull a broad slice of the Greenhouse corpus without supplying a single slug.
One dataset item per open posting. One charge per item. No proxies, no browser, no guessing: every row comes from boards-api.greenhouse.io, the endpoint Greenhouse publishes for exactly this purpose.
How it works
- Boards. If
companySlugshas entries, those are the boards. Each may be a board token (stripe) or a board URL (https://boards.greenhouse.io/stripe,https://job-boards.greenhouse.io/stripe/jobs/123). Anything on another host is refused, not fetched. If the list is empty, the Actor takes boards from its directory, optionally filtered bydirectoryFilter, up tomaxCompanies. - Quote. Before the first request the log states the most the run can cost: boards ×
maxJobsPerCompany× the per-row price. Real runs cost less, since most boards have far fewer than 200 open postings. - Read. One request per board to
/v1/boards/{token}/jobs?content=true, at most four requests a second across the whole run, four boards at a time, with a descriptive User-Agent. Redirects are not followed. A 404 means the board is gone and is logged, not charged. 429 and 5xx are retried twice with backoff, and aRetry-Afterheader is honoured up to 30 seconds; any other failure is logged and not charged. A board is not even requested once the run's charge limit has no room for its first row. - Filter.
firstPublishedAfterandupdatedAfterkeep only new or changed postings, so a daily run on the same boards charges only for what moved. Filtering happens before charging. - Rows. Each kept posting is charged and pushed as one item. When
includeCompanyMetais on, the board's own description is added to every row of that board (one extra request per board with postings).
The run's status message states the totals: jobs, boards, postings outside the filters, boards read in part when a charge limit cut the run, boards gone, boards that could not be read.
Directory
The directory is built by scripts/harvest.mjs in two stages:
- Harvest. The Common Crawl CDX index is read for every URL it has seen on
boards.greenhouse.ioandjob-boards.greenhouse.ioacross the four newest crawls: CC-MAIN-2026-21, CC-MAIN-2026-25, CC-MAIN-2026-30, CC-MAIN-2026-34. The first path segment of each URL is a board token. No token is guessed, none is copied from another dataset. - Validate. Each token is read once against
/v1/boards/{token}at four requests a second. A 200 keeps it, with the company name Greenhouse returns; a 404 drops it.
src/directory.json carries the crawl ids, the harvest date, the validation date and the counts, so you can see exactly how old the list is. On 2026-09-08, 6,142 tokens were seen and 4,636 were live.
Two limits, stated plainly. The directory is incomplete: Common Crawl only indexes boards that some page linked to, so companies that embed Greenhouse on their own site and never link the hosted board are missing. And between rebuilds it goes stale by months: boards close and open every week, which is why the Actor never trusts the list and reads every board live. Give your own tokens for anything the directory lacks. The directory is rebuilt from newer crawls, and every rebuild revalidates every token; validatedAt in directory.json is the date that counts.
Pricing
Pay per event. The one event is job, charged once per posting row at $0.002 on the free tier. There is no start fee. Boards that turn out empty, gone, filtered out or unreadable cost nothing beyond the Apify platform usage of the run itself.
Worked cases. The first figure of each is the ceiling the log quotes before a run starts; the last is what to expect.
- Three named boards, default
maxJobsPerCompanyof 200: at most 600 rows, so at most $1.20. A typical three-company read returns well under that. - The default directory run,
maxCompanies500: at most 100,000 rows, so at most $200.00. In practice a run with the default input on 2026-09-08, the first 500 boards of the directory in token order, returned 12,958 rows, so $25.92. - A daily delta on the same 500 boards with
updatedAfterset to yesterday: only the postings that changed, usually a few hundred rows.
Raise the run's maximum total charge in Apify if you want the whole directory in one run; the Actor stops cleanly at the limit and says how many boards were left.
Input
| Field | Type | Default | Meaning |
|---|---|---|---|
companySlugs | string[] | [] | Board tokens or board URLs. Empty means use the directory. |
directoryFilter | string | "" | Case-insensitive match on token or company name, directory mode only. |
maxCompanies | integer | 500 | Boards read this run. |
maxJobsPerCompany | integer | 200 | Rows kept per board. |
firstPublishedAfter | ISO date | "" | Keep postings first published after this. |
updatedAfter | ISO date | "" | Keep postings updated after this. |
includeContent | boolean | false | Add the posting's description HTML to each row. |
includeCompanyMeta | boolean | true | Add the board's description to each row. |
Input example, three companies with descriptions:
{"companySlugs": ["stripe", "https://boards.greenhouse.io/figma", "duolingo"],"includeContent": true}
Directory mode, boards whose token or name contains "pay", daily delta:
{"directoryFilter": "pay","maxCompanies": 200,"updatedAfter": "2026-09-07T00:00:00Z"}
Output
One item per posting. Field names follow the Job Board API's own, so any row can be checked against its absoluteUrl.
{"jobId": 4001,"boardSlug": "acme","boardName": "Acme Inc","title": "Data Engineer","absoluteUrl": "https://job-boards.greenhouse.io/acme/jobs/4001","location": "Remote - US","departments": ["Engineering"],"offices": ["Boston"],"firstPublished": "2026-08-20T09:00:00-04:00","updatedAt": "2026-09-05T10:00:00-04:00","language": "en","applicationDeadline": null,"requisitionId": "R-77","internalJobId": 900,"metadata": [{ "id": 1, "name": "Team", "value": "Data", "value_type": "single_select" }],"content": null,"boardContent": "<p>About Acme</p>","aiOptOutRequestUrl": null,"source": "boards-api.greenhouse.io","fetchedAt": "2026-09-08T12:00:00.000Z"}
Field notes. boardName is the company_name Greenhouse returns on the posting itself. content is the description HTML when includeContent is on, otherwise null. boardContent is the board's description when includeCompanyMeta is on. metadata is the board's custom fields as Greenhouse returns them. language, applicationDeadline, requisitionId, internalJobId and aiOptOutRequestUrl are passed through from the API unchanged, the last so you can honour it. No applicant data is on this API, and nothing about people is extracted from postings.
Use cases
- Hiring signals. Which companies opened engineering roles this week, by department and office.
- Job aggregation. A daily delta feed of new and changed postings for a job board or newsletter.
- Market research. Titles, locations and departments across a sector, filtered from the directory by name.
- Recruiting tools. Watch a list of target companies and alert on matching titles.
FAQ
Is this allowed? The Job Board API is Greenhouse's public, keyless, documented interface for reading boards, and the Actor reads it the way its documentation describes: one request per board, under five a second, identified by User-Agent. It does not touch the hosted board pages, does not use a proxy, and does not read anything but the API host.
Why does a board return nothing? Either it has no open postings, or it was gone (404) when read; the log names each. Boards that Greenhouse serves under a custom domain but not at boards.greenhouse.io still work if you give their token.
Why is my company not in the directory? The directory only holds boards that Common Crawl saw linked from somewhere. Give the token in companySlugs and it is read like any other.
Can I read every board in the directory at once? Set maxCompanies to the directory size and raise the run's maximum total charge. The log quotes the ceiling first; the Actor stops at the limit rather than overrunning it. That is the directory, which is smaller than Greenhouse itself: see the limits above.
Where do I report a problem? The Issues tab of this Actor.