Greenhouse, Lever, Ashby & Workday Jobs Scraper avatar

Greenhouse, Lever, Ashby & Workday Jobs Scraper

Pricing

from $1.00 / 1,000 job posting extracteds

Go to Apify Store
Greenhouse, Lever, Ashby & Workday Jobs Scraper

Greenhouse, Lever, Ashby & Workday Jobs Scraper

Scrape open roles from any company's Greenhouse or Lever job board through their public ATS API - no browser, no CSS selectors to break. Each posting returns as JSON with salary min/max, currency, seniority, years of experience, skills and remote status parsed by AI. First 10 items enriched free.

Pricing

from $1.00 / 1,000 job posting extracteds

Rating

0.0

(0)

Developer

Kusol Sukhakul

Kusol Sukhakul

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Greenhouse, Lever, Ashby & Workday Job Postings Scraper

Pulls open positions from any company's public Greenhouse, Lever, Ashby or Workday job board API and returns each one as structured JSON, with salary, seniority, skills and remote status normalized by an AI step you can filter and aggregate.

Quick start

Put the companies you want in companies, or paste their careers-page addresses into startUrls exactly as they appear in your browser:

{
"companies": ["stripe", "palantir"],
"startUrls": [{ "url": "https://jobs.lever.co/leverdemo" }],
"maxItems": 50
}

boards.greenhouse.io/<company>, job-boards.greenhouse.io/<company> and jobs.lever.co/<company>, jobs.ashbyhq.com/<company> and Workday career sites (<company>.wd5.myworkdayjobs.com/<site>) all work, and so does a single job's page. Workday sites need their full URL: companies cannot guess the wd<N> host or site name. A bare company name is tried on Greenhouse, Lever and Ashby; the ones it does not use are skipped and not charged.

No setup, no API key

Run it with the defaults. Every posting comes back with the full ai block filled in; there is no key to request and nothing to configure. You pay per posting returned and per posting the AI step enriched successfully, at the prices on this listing, and nothing for an AI step that fails. To see the output before a large run, set maxItems to 10 — about $0.03 at the current prices.

enrich: false returns the postings without the AI step, and without its charge.

Sample output

One item, exactly as it lands in the dataset:

{
"url": "https://boards-api.greenhouse.io/v1/boards/discord/jobs/8659978002?content=true",
"source": "company_ats",
"scrapedAt": "2026-09-05T14:02:23+00:00",
"ats": "greenhouse",
"title": "Senior Full-Stack Software Engineer, Ads",
"company": "Discord",
"location": "San Francisco Bay Area",
"description": "Discord has a highly engaged community of millions of daily active users... The US base salary range for this full-time position is $196,000 to $220,500 + equity + benefits. …",
"jobId": "8659978002",
"postingUrl": "https://job-boards.greenhouse.io/discord/jobs/8659978002",
"postedAt": "2026-07-31T12:23:32-04:00",
"ai": {
"salary_min": 196000,
"salary_max": 220500,
"salary_currency": "USD",
"salary_period": null,
"seniority": "senior",
"experience_years_min": 4,
"skills": ["TypeScript", "React", "Python", "React Native", "iOS", "Android"],
"remote_status": "onsite"
}
}

Everything outside ai is read from the posting. Everything inside ai is inferred from the posting text by the AI step. When enrichment is turned off, fails, or times out, ai is null, an aiError field says why, and the posting is returned anyway.

Note: the whole object above, ai included, is verbatim from a live run against Discord's real, public Greenhouse board on 2026-09-05, with the description truncated for length — nothing here is fabricated or schema-shaped filler.

How this is different from a browser-automation job scraper

This actor never renders or scrapes a career page's HTML. Greenhouse (boards-api.greenhouse.io), Lever (api.lever.co), Ashby (api.ashbyhq.com) and Workday (/wday/cxs/ on each career site) are the same JSON APIs those companies' own career pages call to display their listings — public, undocumented-nowhere-near-obscure, no login, no anti-bot measures, and no robots.txt restriction on the endpoints this actor uses. That means: no rendering overhead, no brittle CSS selectors that break on a redesign, and results as clean as the company's own listing page shows.

Pay only for what changed

Turn on incremental and schedule the Actor daily or weekly. The first run returns everything; each later run returns only postings that are new or whose content changed since the last run with the same stateName, marked changeType: "NEW" or "UPDATED". Unchanged postings are skipped: not returned, not charged, not sent to the AI step.

{ "incremental": true, "stateName": "weekly-eng" }
  • Use a different stateName for each separate search or schedule.
  • The memory lives in a key-value store in your own Apify account and forgets postings not seen for 30 days.
  • A posting whose AI step failed is not remembered, so the next run tries it again.
  • Closed postings are not reported; a posting that disappears is simply not returned.

Input

OptionTypeDefaultWhat it does
startUrlsarrayLever's public demo boardCareers-page URLs (boards.greenhouse.io/<company>, job-boards.greenhouse.io/<company>, jobs.lever.co/<company>, jobs.ashbyhq.com/<company>, <company>.wd5.myworkdayjobs.com/<site>), single job pages, or the API URLs (boards-api.greenhouse.io/v1/boards/<company>/jobs, api.lever.co/v0/postings/<company>?mode=json, api.ashbyhq.com/posting-api/job-board/<company>).
companiesarraynoneCompany slugs such as stripe. Each is tried on Greenhouse, Lever and Ashby.
maxItemsinteger100Hard cap on items returned. Never exceeded. Maximum 1000.
enrichbooleantrueTurns the paid AI step on or off.
enrichFieldsarrayall fieldsRestricts enrichment to named fields: salary_min, salary_max, salary_currency, salary_period, seniority, experience_years_min, skills, remote_status.
incrementalbooleanfalseReturn only postings that are new or changed since the last run with the same stateName. Unchanged ones are not charged.
stateNamestringdefaultSeparate incremental memories, e.g. one per schedule.
talariaTokenstring (secret)noneNot needed on Apify. Only for running the Actor outside Apify, or against your own talariaBaseUrl.
talariaBaseUrlstringhttps://talaria.skusol.comPoint the AI step at your own endpoint instead.
requestIntervalSecsinteger1Minimum seconds between two requests to the target API.
maxRetriesinteger3Retries per page before it is skipped.
respectRobotsTxtbooleantrueStops the crawl if robots.txt disallows it.

Finding a company's board URL

Most companies on these ATSs link their career page straight at boards.greenhouse.io/<company>, jobs.lever.co/<company> or jobs.ashbyhq.com/<company> — paste that address as it is, or put the <company> part in companies. If a career page is custom-branded, view its page source and search for greenhouse.io, lever.co or ashbyhq.com; the slug is in the embedded widget's URL.

Use cases

  1. Compensation benchmarking. salary_min, salary_max and salary_currency turn free-text pay ranges into numbers you can compare across companies, roles, and regions — without maintaining currency detection yourself.
  2. Hiring-signal lead generation. A company opening several roles on a team is a buying signal for sales, recruiting, and market research. Run this against a watchlist of companies on a schedule to catch new postings.
  3. Skill-demand tracking. Aggregate skills across postings from companies in a sector to see which tools and technologies are actually in demand, not which a survey says employers want.

Pricing

Prices are set on the Apify Store listing; this table says what triggers each event.

EventCharged when
apify-actor-startOnce, when a run starts.
item-scrapedOnce per job posting after it has been written to the dataset. A posting that fails to parse is never pushed and never charged.
ai-enriched-itemOnce per posting whose AI fields came back valid. Enrichment that fails, times out or is turned off is not charged.

Two rules the actor holds to: nothing is charged before the thing it pays for exists, and when a run reaches its maximum cost the run ends cleanly with everything produced so far.

Limitations

  • Coverage. Only companies using Greenhouse, Lever, Ashby or Workday's standard hosted job board. Companies on other ATS platforms (SmartRecruiters, iCIMS, custom systems) aren't covered by this actor.
  • Workday lists at most 2,000 jobs per career site. That is Workday's own cap on its listing API; very large employers may have more openings than it returns.
  • No board directory. You supply each company's board URL yourself — this actor doesn't maintain or guess a list of which companies use which ATS.
  • Company name on Lever, Ashby and Workday postings. None of these APIs includes a company display name in the posting data itself, so company is derived from the board's URL slug (e.g. acme-corp → Acme Corp), which can differ slightly from the company's official name.
  • Freshness. Each item is a snapshot at scrapedAt. Without incremental, a posting scraped on two runs appears, and is charged, on both; with it, only new or changed postings come back.
  • AI fields are inferred. ai values come from a language model reading the posting. A field the posting does not state comes back null or unknown rather than a guess, but the values are not verified against any other source.
  • robots.txt. With respectRobotsTxt on, a disallow ends the crawl instead of working around it.

Development

make actor-setup # once, needs the network
make build # compileall and pytest
make actor-run # local run in pay-per-event test mode

The test suite runs offline. It uses fake pages, a fake enrichment service, and the Apify SDK's local pay-per-event mode, and asserts on charge counts and ordering.