Greenhouse Jobs Lookup: jobs scraper by company from $4/1k avatar

Greenhouse Jobs Lookup: jobs scraper by company from $4/1k

Pricing

from $2.00 / 1,000 successful lookups

Go to Apify Store
Greenhouse Jobs Lookup: jobs scraper by company from $4/1k

Greenhouse Jobs Lookup: jobs scraper by company from $4/1k

Greenhouse jobs scraper: live postings by company. Look up any company's live Greenhouse job board and get every open role: title, location, department, apply link. Filter by title, location, remote, or posted date. Charged once per company checked, however many roles it has open.

Pricing

from $2.00 / 1,000 successful lookups

Rating

0.0

(0)

Developer

Adrian Voss

Adrian Voss

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Greenhouse Jobs Lookup: Greenhouse Jobs Scraper — Live Postings by Company

Paste a list of companies and get every open role from each one's Greenhouse job board — title, location, department, and apply link — as one row per posting, or one row per company. No API key and no HTML scraping: this reads Greenhouse's own public job board API directly. Optional filters narrow results by title, location, or posting date, and a delta mode returns only the postings that are new since your last run.

Who it's for

Sourcers and recruiters use this to pull every open Greenhouse role for a target account list in one pass instead of opening each careers page. Sales and RevOps teams watch a competitor's Greenhouse board on a schedule to catch expansion signals — a company opening five sales roles in a new region is a warmer lead than a cold one. Investors and market researchers score hiring momentum across a portfolio or a sector by reading job counts over time rather than company by company. What makes it worth automating rather than checking by hand: Greenhouse's own API returns the whole board in one response, so a company with 600 open roles costs the same single lookup as one with two.

Why this one

  • Direct from Greenhouse's own API. No HTML scraping to break when a careers page gets redesigned — this calls boards-api.greenhouse.io the same way Greenhouse's own careers pages do.
  • You pay per company, not per job. A board with 578 open roles and a board with 2 both cost one item-lookup charge. A company with no board, or zero open roles, is a free miss.
  • Real filters, not a wall of raw fields. Title keyword include/exclude, location, remote-only, and posted-after-date all combine, so you can ask for exactly the roles you want instead of filtering 578 rows by hand afterward.
  • A delta mode for watching hiring over time. Turn on onlyNewSinceLastRun, put the actor on a schedule, and every run after the first returns only postings you haven't seen — a quiet week still gets a row, so you can tell "nothing new" from "the run broke."
  • Flexible input. A bare Greenhouse token or the full boards.greenhouse.io / job-boards.greenhouse.io careers URL both work — no need to go find the raw API slug first.

What you get

One row per open job posting by default — toggle "One row per job posting" off to get one row per company instead, with the job list nested in jobs. The 17 columns below are fixed, whether or not you've turned on filters or delta mode.

FieldType / formatDescription
querytextThe company value you passed in, unchanged.
foundbooleantrue if the company has a Greenhouse board with at least one open role. Gates billing.
statustextOK, NOT_FOUND (no board or no open roles), or BAD_FORMAT (not a token or URL).
boardTokentextThe board token, extracted from whatever you pasted.
jobCountnumberRoles matched, after filters and delta filtering.
totalJobCountnumberRoles on the board before filtering — shows what a filter dropped.
newJobsnumberRoles new since your last run. Empty unless onlyNewSinceLastRun is on.
firstRunbooleantrue on the baseline run for a watchlist. Empty unless delta mode is on.
jobsarrayAll matching jobs, each with the fields below. Expanded into separate rows in one-row-per-job mode.
titletextJob title.
locationtextOffice or region as Greenhouse lists it — e.g. "San Francisco", "Remote".
departmentsarrayDepartment name(s), fetched from the board's separate department listing.
remotebooleantrue if location or title reads as remote — matches "remote", "anywhere", "work from home", "wfh", "distributed".
postedAtdate (ISO)When Greenhouse first published the posting, falling back to updated_at.
updatedAtdate (ISO)When the posting was last edited.
applyUrllinkDirect apply link for the role.
scrapedAtdate (ISO)When this actor fetched the row.

A company with no board, or a board with zero open roles, still returns one row with found: false and a status/message explaining why — never charged.

How delta mode works

Turn on onlyNewSinceLastRun and put the actor on a schedule, and it stops being a full re-dump and starts being a hiring alert. Here's what actually happens across runs:

  • First run: returns everything matching your filters and remembers every posting id it showed you. firstRun is true on this row.
  • Every run after: returns only postings it hasn't shown you before, and counts them in newJobs. A quiet week still returns a row per company — jobCount: 0, newJobs: 0 — so you can tell "nothing changed" from "the schedule silently stopped running." Every company checked is still billed once, whether or not anything is new.
  • Filters are part of the watchlist's identity. Two schedules watching the same company with different titleKeywords keep separate seen-lists automatically. Edit a filter and that watchlist re-baselines on its next run — you'll see everything matching once more, then deltas resume from there.
  • Where it lives: a named key-value store, greenhouse-jobs-lookup-state, inside your own Apify account. Nobody else can read it, storage cost is negligible, and deleting the store resets every watchlist to a fresh baseline.

Price

$4 per 1,000 companies, plus a $0.00005 start fee. Misses (found:false) are never charged.

That works out to $0.004 per company whose board is found, on the FREE pricing tier (drops to $0.002 on GOLD) — you're never billed for a company with no Greenhouse board or a BAD_FORMAT input, no matter how many companies are in the list. However many roles a found company has open, it's one charge: a board with 578 postings costs the same as one with 2.

1,000 companies through this actor: ~$4 if every one has a findable board — in practice less, since a company with no Greenhouse presence costs nothing. Run the same 1,000 rows through a credit-based enrichment platform and expect $80–$400. This actor does one job — Greenhouse postings — and isn't trying to be a general enrichment waterfall.

How to use

  1. In the Apify Console. Open the actor page and click Start — the companies field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
  2. Via the API. Call it directly with a POST request — no Console needed once you have an API token:
    curl "https://api.apify.com/v2/acts/accountable_eel~greenhouse-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"companies":["stripe"]}'
  3. On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.

Paste one company per line — a bare Greenhouse token like stripe, or the full careers URL (https://boards.greenhouse.io/stripe or https://job-boards.greenhouse.io/stripe). The token is extracted automatically either way, so you don't need to go look up the raw API slug.

Common ways teams use this:

  • Source candidates by pulling every open role matching a title keyword across a list of target companies in one pass.
  • Watch a competitor's hiring with a fixed company list on a weekly schedule and delta mode on, so each run shows only what's new.
  • Score hiring momentum across a target account list by reading jobCount per company in one-row-per-company mode.
  • Find roles in a specific market by combining locations with titleKeywords instead of exporting everything and filtering by hand.
  • Feed an ATS-aware outbound sequence by joining applyUrl and postedAt onto an existing account list in Clay or n8n.

For a standing watchlist, turn on onlyNewSinceLastRun in the 🔁 Watch for new jobs section and put the actor on a schedule — see How delta mode works below for exactly what changes across runs.

Input

{
"companies": [
"stripe"
]
}

One company per line — paste the Greenhouse token or the full careers page URL. Accepted formats: stripe, https://boards.greenhouse.io/stripe, https://job-boards.greenhouse.io/stripe.

To narrow what comes back, open the 🎯 Job filters section. All of these are optional, and they combine with AND across fields, OR within a field:

InputWhat it does
titleKeywordsKeep only roles whose title contains at least one of these — ["engineer","designer"]. Case-insensitive, partial words count.
excludeTitleKeywordsDrop roles whose title contains one of these — ["intern","contract"]. Applied after titleKeywords.
locationsKeep only roles whose location contains one of these — ["Berlin","United Kingdom"].
remoteOnlyKeep only roles that read as remote.
postedAfterKeep only roles first published on or after this date — "2026-06-01".

Leave every filter empty and you get every open role. jobCount (matched) and totalJobCount (before filtering) both come back on every row, so a filtered result is never ambiguous — and a company whose roles all get filtered out still returns a found: true row with jobCount: 0, charged like any other found company, because it answered the question you asked.

Sample output

queryfoundstatusboardTokenjobCounttotalJobCountnewJobsfirstRunjobstitlelocationdepartmentsremotepostedAtupdatedAtapplyUrlscrapedAt
stripetrueOKstripe573573<all matching jobs (full list)>Account Executive, AI SalesSan Francisco, CA["1175 Enterprise - Account Executives (NA)"]false2026-02-03T15:19:01-05:002026-08-25T17:40:40-04:00https://stripe.com/jobs/search?gh_jid=75327332026-08-31T06:40:11.844Z

That table lists every available column. In "one row per job posting" mode — the default — a real row reads like this:

{
"query": "stripe",
"found": true,
"status": "OK",
"boardToken": "stripe",
"jobCount": 589,
"totalJobCount": 589,
"title": "Account Executive, AI Sales",
"location": "San Francisco, CA",
"departments": ["1175 Enterprise - Account Executives (NA)"],
"remote": false,
"postedAt": "2026-02-03T15:19:01-05:00",
"updatedAt": "2026-08-25T17:40:40-04:00",
"applyUrl": "https://stripe.com/jobs/search?gh_jid=7532733",
"scrapedAt": "2026-08-26T06:00:44.199Z"
}

A company with no Greenhouse board comes back as a miss and is never charged:

{
"query": "not-a-real-company",
"found": false,
"status": "NOT_FOUND",
"message": "No Greenhouse board found for this token",
"scrapedAt": "2026-08-26T06:00:44.199Z"
}

Miss rows are still written to the dataset so you can see exactly which companies failed, rather than diffing your input list against the output.

Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

curl "https://api.apify.com/v2/acts/accountable_eel~greenhouse-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-X POST \
-H "Content-Type: application/json" \
-d '{"companies":["stripe"]}'

n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~greenhouse-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"companies":["stripe"]} (swap in an expression from an earlier node for a real value).

Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~greenhouse-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"companies":["{{company}}"]}, mapping the row's company into the companies array.

MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Greenhouse Jobs Scraper | Apify" — the agent will find and run this actor.

Tips

  • Combine filters to build a watchlist query, not just a keyword search.
    titleKeywords: ["engineer"]
    plus locations: ["Berlin"] plus remoteOnly: false gets you Berlin-based engineering roles only, in one pass, instead of filtering a full dump afterward.
  • Put delta mode on a weekly schedule for competitor tracking. onlyNewSinceLastRun plus a fixed company list turns this into a hiring-alert feed — you only see what changed since last time, and a quiet week still confirms the schedule is running.
  • Use postedAfter for "what opened this month", not updatedAt. Greenhouse bumps updatedAt on any edit, including typo fixes — postedAt only moves when a role first goes live.
  • Switch to one-row-per-company mode for a headcount signal. Read jobCount per company without pulling every posting into your table.
  • Don't combine delta mode with "Only keep rows containing." That filter runs on the finished row and can drop the newJobs: 0 heartbeat row — the one row that tells you the schedule is still alive on a quiet week.

vs. alternatives

What it costsWhat you getTrade-off
This actor (greenhouse-jobs-lookup)$0.004 per company whose board is found (less on paid tiers), $0.00005 actor start, nothing for a company with no Greenhouse boardEvery open posting for a company's Greenhouse board — title, location, department, apply URL — filtered by role keyword, location or posting date, with onlyNewSinceLastRun for deltasGreenhouse only. If your list is mixed-ATS, use ats-jobs-unified-lookup. Office data isn't returned — Greenhouse's own endpoint costs 78× the payload to include it.
TheirStack$0.005–$0.03 per companyA job-postings dataset with history, normalised across many ATS platforms and job boardsBroader coverage than one platform, and it keeps history. This reads Greenhouse's own API live, at the bottom of that price range.
Greenhouse's own APIFreeThe same JSONIt is the same JSON. This handles the board-token guessing, the second request departments actually live behind, filtering, deltas, and the retries — and hands you a flat table.
Clay$0.08–$0.40 per enriched row in credits, on top of a seatA whole enrichment workspace — waterfalls across dozens of providers, plus the table and the sequencing around itIf you want one place that does everything and you're not counting rows, that's Clay. This is one column, priced per column, callable from Clay via its HTTP step.

(TheirStack and Clay prices above are their published August 2026 list prices — check each vendor's own page before relying on the comparison.)

FAQ

Why does found say false, or a row come back empty? Either the input didn't look like a Greenhouse token or URL (status: BAD_FORMAT), the company doesn't have a Greenhouse board, or it currently has zero open roles (status: NOT_FOUND either way). Check the message column for the specific reason.

Was I charged for that row? Only if found is true. A company with no board, or no current openings, is free — check status to confirm which case it was.

I got charged for a company that returned jobCount: 0 — why? Its board exists and has open roles; they just didn't match your filters, or weren't new since your last delta run. totalJobCount shows what was on the board before filtering. That's a real answer to the question you asked, so it bills like any other found company. A company with no board, or nothing open, is found: false and free.

How does delta state work, and can I reset it? It lives in a named key-value store, greenhouse-jobs-lookup-state, inside your own Apify account — nobody else can see it, and it holds only job IDs per company. Delete that store to reset every watchlist. Changing your filters also starts a fresh watchlist automatically, since the filter values are part of what identifies a seen-list.

Why is there no office field, and where do departments come from? Greenhouse's job-listing endpoint omits both unless you request its heavyweight response, which inlines every job's full HTML description — a large payload multiplier on a board with hundreds of roles. So departments is filled from one extra request to the board's separate department listing; if that request fails, every role still comes back, just with an empty departments cell. Offices aren't reported at all, because the only endpoints carrying them cost far more than the field is worth — better no column than a permanently blank one. location carries the place information, and remoteOnly matches on both location and title.

Does this hit rate limits on large company lists? It calls Greenhouse's public board API once per company (twice with the departments hop), with its own timeouts and retries. That API is unauthenticated and public — the same one Greenhouse's own careers pages call — so no proxy is needed. Large lists just take proportionally longer.

Is this GDPR-safe to run against EU companies? Everything returned is already published publicly on each company's own careers page — titles, locations, departments, apply links. No personal data about applicants or employees is collected. You remain responsible for how you use the output downstream.

Can an agent run this without a human clicking Start? Yes — it's registered with the Apify MCP server, so a Claude or Cursor agent with that MCP connected can find "Greenhouse Jobs Lookup" and pull rows back on its own; see Use it from Clay, n8n, Make, or an AI agent.

  • ATS Jobs Unified Lookup — check a company across Greenhouse, Lever, Ashby, and other ATS platforms in one call when you don't know which one they use.
  • Lever Jobs Lookup — the same lookup, filters, and delta mode for companies on Lever.
  • Ashby Jobs Lookup — the same lookup, filters, and delta mode for companies on Ashby.