Greenhouse Jobs Scraper API — Full Descriptions avatar

Greenhouse Jobs Scraper API — Full Descriptions

Pricing

$1.00 / 1,000 job fetcheds

Go to Apify Store
Greenhouse Jobs Scraper API — Full Descriptions

Greenhouse Jobs Scraper API — Full Descriptions

Track new Greenhouse job postings with full descriptions, from 872 verified boards built in — or just type a company name. Clean spreadsheet, no login. $1 per 1,000 jobs.

Pricing

$1.00 / 1,000 job fetcheds

Rating

0.0

(0)

Developer

WickFeed

WickFeed

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

0

Monthly active users

5 hours ago

Last modified

Share

Unofficial — not affiliated with, endorsed by, or connected to Greenhouse. "Greenhouse" is a trademark of Greenhouse Software, Inc., used here only to describe what this tool reads.

Data note: job postings are employer-published public data and may contain recruiter or contact details inside the description text; treat that as personal data and don't use it for spam or unsolicited outreach.

Version 0.2.6 · live since 2026-07-15 · 872 Greenhouse boards verified 2026-07-15 · $1 per 1,000 jobs, $0 to start.

Live status: https://api.apify.com/v2/key-value-stores/WickFeed~wickfeed-public-status/records/status.json — real self-test results for every wickfeed scraper (pass/fail plus 30-day success rate), updated hourly, no login needed. Opens as raw data (JSON).

Choosing among the WickFeed tools:

Paste a Greenhouse careers URL or a bundled company name, press Start, and get one row per open job — the description included as plain text (capped at 20,000 characters), and the source URL on every row for the complete posting. The 3-company demo costs at most $0.15. No Greenhouse login or API key is required — an Apify account is all you need to run the tool.

From first click to download, four steps:

  1. Click Try for free and sign in to your Apify account.
  2. Leave the demo boards exactly as prefilled and click Start.
  3. When the run finishes, open Dataset to see one row per job.
  4. Click Export to download the rows as CSV, Excel, or JSON.

What it does

Every open job at the Greenhouse companies you choose, as a fresh snapshot each run — one tidy row per job, the job description in the same row. Pick boards, press Start. It reads Greenhouse's own public Job Board API (the same JSON a careers page loads) and writes a normalized row for each posting.

Descriptions inline, in a single pass — at no extra cost. Greenhouse returns the whole board, every posting with its description, in one response. This actor asks for that (content=true) and fills descriptionText on every row in that same fetch — so you get the write-up (responsibilities, requirements, and the rest) as plain text, capped at 20,000 characters as a memory-safety guard; each row also carries the source url, the route to the complete posting when a description runs past that cap. Turning descriptions on doesn't change the price: a flat $1 per 1,000 jobs. Dated, deduplicated rows with the description already attached are the substance here — you're not re-fetching a title and a link one posting at a time.

Demo cost, in full: at most about $0.15. The form arrives prefilled with 3 demo boards (gitlab, databricks, figma). Press Start and the first run over those three boards costs a few cents — up to roughly $0.15 — every penny of which Apify's $5 monthly free credit absorbs, so your first runs are free. And you pay strictly for jobs delivered: an empty, dead, or misspelled board is never charged.

Each run returns a fresh, full snapshot of every open role, not a comparison against yesterday. To have only the new and changed jobs pulled out automatically, use the ATS Job Aggregator — the diff monitor for the family.

Run a few boards and you get rows like these (real postings, fetched 2026-07-15):

CompanyTitleLocationRemotePosted
StripeAccount Executive, AI Sales (Grower)San Francisco, CA2026-06-02
GitLabAI EngineerRemote, USyes2026-05-29
GitLabAccount Executive - ItalyRemote, Italyyes2026-04-17
DatabricksAccount ExecutiveBengaluru, India; Mumbai, India2023-12-12

"—" means unknown: Greenhouse's public feed has no remote flag, so the actor marks remote: yes only when the location text itself says remote, and leaves it blank otherwise.

Each row also carries a stable id, department, the public application url, the plain-text descriptionText, and a fetch timestamp.

You don't need to know a company's "board token." In the Companies box, put whatever you already have — one company per line:

  • A careers page address. Copy it straight from the browser: https://boards.greenhouse.io/gitlab (the job-boards.greenhouse.io/... form works too). This is the reliable path — the board id is right there in the address, so it always works.
  • A company name. Type GitLab. Typed names are matched against the bundled list of 872 verified Greenhouse companies — a starter directory, not every Greenhouse company. If yours isn't in it, paste the careers page address instead.
  • A bare board token. gitlab, exactly as before. Existing setups and saved runs keep working unchanged.
{ "sources": ["GitLab", "https://boards.greenhouse.io/databricks", "figma"] }

If an entry can't be read — a blank line, an address for a different hiring system (a Workable or Ashby link pasted here is caught and named), or a company name that isn't in the bundled list — that one line is skipped with a plain-English note in the run summary telling you exactly what to paste instead. It never silently runs empty, and the rest of your list still runs. The run only fails when nothing in the box could be used.

Quick start

  1. Add companies. Just press Start to use the three demo boards already filled in (gitlab, databricks, figma). Or paste careers-page addresses, type company names, or switch Company list to "Starter" (100 highest-volume boards) or "All verified" (all 872).
  2. (Optional) Narrow it. Add keywords (e.g. engineer, product) or locations (e.g. new york, remote) to keep only matching jobs.
  3. Press Start. By default each board delivers up to 50 jobs — the first 50 that match your filters (or just the first 50 it finds, if you set none) — so the first pass stays fast and inexpensive across however many boards you listed. Increase Max results per board once you've reviewed the output and want the complete set.

Calling the API? Sending an empty input {} runs the very same three demo boards you see in the form, each capped at 50 jobs (about $0.15 in total), so a first API call behaves exactly like pressing Start — never an empty run, and never a surprise-priced one.

Bundled company lists

Choose a preset and press Start — no token hunting:

  • Starter — 100 boards: the highest-volume Greenhouse boards (the ones with the most open jobs), for a rich sample run.
  • All verified — 872 boards: every Greenhouse board in the bundle, each confirmed to return live postings against Greenhouse's own API on 2026-07-15.

It's a starter corpus, not an exhaustive directory of every Greenhouse company. You can add your own boards by hand in the Companies box; the two lists merge and duplicates are removed.

Output schema

One row per job, the same fields every time:

FieldMeaning
idStable id greenhouse:<token>:<jobId> — deduplicate on this.
atsAlways greenhouse — the hiring system this row came from (kept so the schema matches the multi-ATS aggregator).
companyTokenThe Greenhouse board slug this row came from (e.g. gitlab).
companyGreenhouse's company_name when present, else the title-cased token.
titleJob title.
departmentFirst department when published, else null.
locationLocation string as Greenhouse provides it.
remotetrue only when the location text says remote; null when unknown (see note above).
urlPublic application URL (absolute_url).
postedAtPublish time (ISO-8601), or null.
updatedAtLast update time (ISO-8601), or null.
salaryRawAlways null — the public feed carries no pay field (see Limitations).
descriptionTextPlain text, capped at ~20,000 chars.
fetchedAtWhen this run fetched the row.
schemaVersionThe output-record schema version (a number, currently 1). See Output contract below.

Turn on Include raw HTML description to also get descriptionHtml.

Two real records from a run over the stripe board (fetched 2026-07-15) — every field present on every row, honest nulls where Greenhouse's public feed doesn't expose a value:

[
{
"id": "greenhouse:stripe:7954688",
"ats": "greenhouse",
"companyToken": "stripe",
"company": "Stripe",
"title": "Account Executive, AI Sales",
"department": "Account Executives (AI)",
"location": "San Francisco, CA",
"remote": null,
"url": "https://stripe.com/jobs/search?gh_jid=7954688",
"postedAt": "2026-06-02T12:58:57.000Z",
"updatedAt": "2026-07-13T18:37:36.000Z",
"salaryRaw": null,
"descriptionText": "Stripe builds the economic infrastructure for the internet. As an Account Executive on the AI Sales team you will …",
"fetchedAt": "2026-07-15T18:00:00.000Z",
"schemaVersion": 1
},
{
"id": "greenhouse:stripe:8042978",
"ats": "greenhouse",
"companyToken": "stripe",
"company": "Stripe",
"title": "Staff Software Engineer",
"department": "Engineering",
"location": "Remote - North America",
"remote": true,
"url": "https://stripe.com/jobs/search?gh_jid=8042978",
"postedAt": "2026-07-02T07:24:50.000Z",
"updatedAt": "2026-07-03T01:13:43.000Z",
"salaryRaw": null,
"descriptionText": "As a Staff Software Engineer you will design and build the systems that move money for millions of businesses …",
"fetchedAt": "2026-07-15T18:00:00.000Z",
"schemaVersion": 1
}
]

remote is true on the second row only because its location text says "Remote"; the first row's is null (unknown) — Greenhouse's public feed has no explicit remote flag. descriptionHtml is added only when Include raw HTML description is on.

Output contract (schema stability)

A shipped update on our end shouldn't break your spreadsheet or your pipeline, so here is the promise set down in writing:

  • We never rename or remove an existing field within a major version. The columns above — id, title, url, descriptionText, and the rest — keep both their names and their meaning, so you can build on every one of them safely.
  • A null is a placeholder, never a dropped field. Everywhere Greenhouse's public feed exposes no value (remote, salaryRaw, and sometimes department or postedAt), the field is still present and set to null — it is never dropped, so a column you read is always there to read.
  • New fields are added, never forced. We may add a field over time; adding one never disturbs the fields you already read, so your existing code keeps working untouched.
  • A breaking change is spelled out up front, not slipped in. If a field ever had to be renamed or removed, that would be a major version bump — spelled out in the Changelog (and the Issues tab) before it lands, so it never turns up unannounced on your next scheduled run.
  • schemaVersion is a breaking-contract version. Every row carries it (and it's in RUN_SUMMARY too). It is not the release number and not an exact-shape fingerprint: adding a new field does not bump it — it changes only when an existing field is renamed, removed, or retyped (a breaking change, which also bumps the major version). So while this number holds, every field you already read keeps its name, type, and meaning; new fields may have been added alongside. It is 1 today.
  • The field list is published for machines too. The actor ships a machine-readable output schema (a JSON Schema of every field above), so a pipeline or AI agent can discover the exact row shape without parsing this table.

Pricing

You pay only for jobs delivered: $1.00 per 1,000 jobs — that's $0.001 a job (the job-fetched event). Starting a run costs nothing, boards that are dead or return nothing are never charged, and you're billed for delivered rows only — not for run time, retries, or empty boards. Descriptions come inline in the same request, so turning them on doesn't change what you pay.

In plain numbers: at $0.001 a job, a run that returns 500 jobs costs about $0.50, and 2,000 jobs costs about $2.00. A board that's dead, misspelled, or has no open roles returns nothing and is never charged, so you only ever pay for jobs actually delivered.

Free to try. Apify's free plan ships with monthly usage credit that fully covers a first demo run, so you can review a complete sample — rows, descriptions, and all — before paying anything.

For comparison. Comparable single-system Greenhouse job actors on the store run about $1.15–$4 per 1,000 (multi-system feeds run higher still), and most add a per-run start fee on top; this one is a flat $1 per 1,000 with no start fee. A few listings do price lower per job and charge a fixed start fee instead — for example fetch_cat/greenhouse-jobs-scraper (about $0.03 per 1,000 plus a $0.005 start fee) and memo23/greenhouse-jobs-scraper (about $0.79 per 1,000 plus a $0.007 start fee), both checked 2026-07-16 — so on a big pull they can come in under this one, while on a very small run the fixed fee can tip it the other way. Prices move, so compare on the current listings. Store prices as listed 2026-07-15; competitor prices checked 2026-07-16.

If a charge ever looks wrong, open an issue on the Issues tab with your run ID, and we investigate the same day. If we over-billed you, we file a credit request with Apify to put that amount back on your account. (Apify pays seller compensation as account credit rather than cash, so account credit is what we can promise and what we will do — not a guarantee about how Apify itself handles it.)

Limitations (read this)

  • Public postings only. It reads what a company publishes on its Greenhouse board — not private ATS data, internal reqs, or candidate information.
  • No structured salary. Greenhouse's public feed has no salary field, so salaryRaw is always null. If a company writes pay into the job text, it appears inside descriptionText, not as a parsed number. If you need published salary ranges as a field, the Ashby Jobs Scraper below exposes them directly.
  • Remote is inferred, not declared. Greenhouse's public feed has no explicit remote flag, so remote is true only when the location text says remote, and null otherwise — it is a best-effort read, not a guarantee.
  • You supply the companies. No API lists every Greenhouse company, and this actor does not crawl. Use a bundled list, or read a token off a careers URL.
  • Unknown or misspelled tokens are reported as a per-board error, not silently swallowed. A token that isn't a real Greenhouse board returns HTTP 404, so the actor isolates that one board as an error — it's skipped, never charged, and the rest of the run finishes normally — and lists it in the per-board error output. Check there if a board you expected is missing (a typo'd slug shows up as a 404). A valid board that simply has no open jobs is different: it returns a clean empty result, not an error.
  • Whole board in one response. Greenhouse returns the entire board — every posting, with full descriptions — in a single response, so it isn't paginated. The actor handles the largest real boards (thousands of jobs, tens of MB) with a generous size guard; a pathologically huge board beyond that guard is isolated and reported, never silently truncated.
  • No server-side search. The keyword, location, remote and date filters run over the whole board after fetching, and Max results per board then caps the matching jobs delivered (so a match is never hidden past the cap).
  • Politeness. Requests are paced at about 1.3 per second with retries and backoff. Greenhouse rate-limits its API (HTTP 429); the actor stays under that limit and retries any 429 it does hit, so a throttled board still returns its jobs rather than being dropped. Very large runs take proportionally longer.
  • Endpoint drift. If Greenhouse changes its response shape, the reader may need an update; a bad board is isolated and reported, never fatal to the rest of the run.

What it does not do

  • It does not touch private or candidate data. It reads only jobs a company has published publicly on its Greenhouse board — never applicant data, internal reqs, or anything behind a login. It stays on the public boards-api.greenhouse.io endpoint and never touches the candidate portal.
  • It does not log in or use any key. Greenhouse's Job Board API is public: no account, no password, no API key.
  • It does not discover companies for you. No public index lists every Greenhouse company, and this actor does not crawl to find them — you supply the board tokens (or use a bundled list).
  • It does not invent salary. Greenhouse's public jobs feed has no structured pay field, so the salaryRaw column is always empty (see the salary limitation above).
  • It does not break on page redesigns. It reads the JSON feed, not the rendered HTML, so a careers-page restyle doesn't affect it.

FAQ

I got few or zero jobs back — is it broken?

Almost never a real fault — nearly always a filter or the per-board cap. Take the plain checks first, in order: clear your Keywords and Locations, turn Remote only off, and raise Max results per board (it defaults to 50 per board). Next, open the run's own Status and Logs and look for a mistyped board token or a board that returned nothing. If it still looks wrong after that, open the Issues tab with your run link and we'll look into it.

Advanced diagnostics: the complete per-board breakdown — fetched, matched, delivered, filtered, and every board error — is written to the run's key-value store as RUN_SUMMARY, and any rows that failed schema validation are collected in REJECTS; a typo'd token shows up there as a 404. When a board has more matching jobs than the cap, its row shows how many matched, so you can raise Max results per board to get the rest.

Does it scrape HTML?

No. It calls Greenhouse's public Job Board API and reads JSON directly — the same call a browser makes when it renders a careers page, and nothing more. No proxies, no headless browser, no rendered-page parsing.

Why is the salary column empty?

Because Greenhouse's public feed has no salary field. This actor never guesses or fabricates pay, so salaryRaw is always null. For published salary ranges as a real field, use the Ashby Jobs Scraper.

Do I get the job description?

Yes — the actor requests the board with descriptions included, so descriptionText is filled in on every row in a single pass, at no extra cost. It's plain text, capped at 20,000 characters as a memory-safety guard; if a posting's description runs longer than that, the row's source url links to the complete posting.

Is this allowed?

It reads the very same public JSON feed your browser loads when it opens a Greenhouse careers page — no login, no password, no API key, and no HTML scraping. It only ever touches jobs a company chose to publish publicly on its Greenhouse board, never candidate or private data. You decide how you use the results, and you are responsible for that use — for example, don't use it for spam or unsolicited outreach. This is a description of how the tool works, not legal advice.

Can I schedule daily runs?

Yes, with Apify's scheduler. Each run re-fetches from scratch, so a daily schedule delivers a fresh, complete snapshot of every open role every day — it is a full re-pull, not a comparison against yesterday. If you'd rather receive only the new and changed jobs, pulled out for you automatically (true alerts that charge only for what changed), the Jobs Scraper API is the diff monitor for that.

What happens to a dead or misspelled board?

A misspelled or non-Greenhouse token returns HTTP 404, so that one board is reported as an error in the per-board results (skipped, never charged) while the rest of the run finishes normally — check the per-board errors if a board you expected is missing. A real board that just has no open jobs comes back as a clean empty result instead. Either way, you're never charged for a board that delivered no jobs.

Use with AI agents (MCP)

AI agents can drive this actor as a tool — Claude Desktop, Cursor, n8n, LangGraph, CrewAI, or any other MCP-compatible client — through Apify's hosted MCP server at mcp.apify.com. An agent locates it with search-actors, inspects its full input with fetch-actor-details, and runs it with call-actor. Point your MCP client at Apify's server:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com"
}
}
}

That form uses OAuth sign-in; to pass a token instead, add a "headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }. Output is flat, stable JSON built for machine consumption, and agentic pay-per-event billing is enabled.

Integrations

Download the full results as CSV, Excel, or Google Sheets — no code required. Or wire it up: it works with n8n, Make, and Zapier through Apify's native integrations, so you can route the dataset into Slack, a webhook, a Google Sheet, or a pipeline of your own.

Changelog

  • 0.2.6 — 2026-07-16 — Added a public live-status link (real self-test results, no login).
  • 0.2.5 — 2026-07-16Filters now run over the whole board before the cap, plus honesty fixes. Max results per board used to cap the raw job list before your keyword, location, remote, and date filters ran, so a matching job sitting past the cap could be silently missed. Now the filters run over the whole board first and the cap limits the matching jobs delivered, so a match is never hidden past the cap. Runs with no filters behave exactly as before (still the first N jobs), the 64 MB large-board size guard is untouched, and every per-board cost ceiling is the same (at most the cap × $0.001 per board; the 3-board demo still tops out around $0.15). An unreadable Posted after date is now rejected with a plain-English message instead of quietly turning the date filter off. The actor also publishes a machine-readable output schema (JSON Schema) so a pipeline or agent can discover the row shape, and the schemaVersion wording is corrected to a breaking-contract version (adding a field does not bump it). No price, count, or cap value changed.
  • 0.2.4 — 2026-07-16Honest description limits, a lowercase-name fix, and a benefit-first page. The description claim is now qualified everywhere: descriptionText (and the optional descriptionHtml) is plain text capped at 20,000 characters as a memory-safety guard, and each row's source url is named as the route to the complete posting when a description runs past that cap. A company name typed in lowercase now resolves to the same board as its normal-case spelling — previously a lowercase one-word name could be taken as a raw board token and miss the bundled listing. The page now leads with the benefit and moves the "what it does not do" list down under Limitations; added a four-step click-to-file walkthrough, a WickFeed tool chooser, plain snapshot-vs-diff wording (pointing to the ATS Job Aggregator for new-and-changed alerts), and a novice-first troubleshooting answer. No price, count, cap value, or run behavior changed — the 20,000-character cap has always been in the code.
  • 0.2.3 — 2026-07-16Each page now speaks in its own voice. Rewrote the sections this README used to share word-for-word with the Ashby and Workable pages — pricing, the output contract, the FAQ, the AI-agents (MCP) and integrations sections, and the footer — in this scraper's own thorough voice. Every fact, price, and promise stays the same, and nothing about how a run behaves changed.
  • 0.2.2 — 2026-07-16Error messages now point you to the right scraper. Paste a careers link for a different hiring system and the message now names the product that reads it — our Ashby or Workable Jobs Scraper for those, or our all-in-one Jobs Scraper + Job Monitor that covers all five systems (Greenhouse, Lever, Ashby, Workable, Recruitee) in one run; paste your company's own website and it points you to that aggregator, which can take the company name and look for the board. The Companies box now also states the first-run cost ceiling (about $0.15 for the prefilled 3-board demo). No change to how a valid run behaves.
  • 0.2.1 — 2026-07-16Paste a link or type a name — no token hunting. The Companies box now accepts a pasted careers-page address (https://boards.greenhouse.io/gitlab, or the job-boards.greenhouse.io form) or a plain company name (matched against the 872 bundled verified companies), alongside the bare board tokens it always took — existing setups and saved runs are unchanged. A link for a different hiring system (Workable, Ashby, Lever, …), a company homepage, junk, or a name that isn't bundled is caught and reported in plain English with the exact thing to paste instead, never a silent empty run. Also: every output row now carries a schemaVersion field (currently 1) and this README documents the output contract (existing fields are never renamed or removed within a major version; null means honestly-absent, not missing) — additive, so existing pipelines are unaffected. And a bare {} API call now runs the same three demo boards the form prefills (≈ $0.15) instead of failing, so a first call can't surprise-bill.
  • 0.1.0 — Initial release. Reads Greenhouse's public Job Board API with content=true so full descriptions arrive inline in one pass; one normalized row per job, 872 verified-live boards bundled (plus a 100-board starter preset), keyword / location filters, per-board 404 isolation, 429-aware pacing (~1.3 requests/second) with retries and backoff, a large-board size guard, schema-validated output, and pay-per-event billing at $1 per 1,000 jobs ($0 to start a run).
  • Need 5 hiring systems in one feed? The Jobs Scraper API covers Greenhouse, Lever, Ashby, Workable and Recruitee in this same schema. Start with its starter-500 preset — 500 verified-live boards in one click — and turn on diff mode to track only new and changed jobs on a daily schedule (and pay $0 on a quiet day).
  • Want published salary ranges as a field? The Ashby Jobs Scraper uses this same clean schema and carries salary when the company publishes it.
  • Just want Workable companies? The Workable Jobs Scraper uses the same schema for Workable.
  • Not sure which companies use a given system? ATS Company Discovery finds live boards and their current open-job counts across five systems.

Need help? Open an Issue with your run link. If a run ever misbehaves or a charge looks off, open the Issues tab and paste your run link — we fix buyer-facing breakages the same day, so that's the fastest route to a fix.