Greenhouse & Lever ATS Job Postings Scraper
Pricing
from $1.00 / 1,000 job posting extracteds
Greenhouse & Lever ATS Job Postings 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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
15 hours ago
Last modified
Categories
Share
Greenhouse & Lever Job Postings Scraper
Pulls open positions from any company's public Greenhouse or Lever 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.
Try it free, no setup
Run it with the defaults. The first 10 postings come back with the full ai
block filled in, so you can see exactly what the AI step produces before
deciding whether it is worth anything to you. Postings past the tenth are
still returned in full — only the ai block is left empty, with aiError
saying why.
To enrich every posting in a run, put your own talariaToken in the input.
There is no signup wall on the demo and no card required to see the output.
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,
aiincluded, 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) and Lever (api.lever.co) 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.
Input
| Option | Type | Default | What it does |
|---|---|---|---|
startUrls | array | Lever's public demo board | Company job-board API URLs — Greenhouse (boards-api.greenhouse.io/v1/boards/<company>/jobs) or Lever (api.lever.co/v0/postings/<company>?mode=json). |
maxItems | integer | 100 | Hard cap on items returned. Never exceeded. Maximum 1000. |
enrich | boolean | true | Turns the paid AI step on or off. |
enrichFields | array | all fields | Restricts enrichment to named fields: salary_min, salary_max, salary_currency, salary_period, seniority, experience_years_min, skills, remote_status. |
talariaToken | string (secret) | none | Bearer token for the enrichment service. Required when enrich is on. |
talariaBaseUrl | string | https://talaria.skusol.com | Point the AI step at your own endpoint instead. |
requestIntervalSecs | integer | 1 | Minimum seconds between two requests to the target API. |
maxRetries | integer | 3 | Retries per page before it is skipped. |
respectRobotsTxt | boolean | true | Stops the crawl if robots.txt disallows it. |
Finding a company's board URL
Most companies that use Greenhouse or Lever link their career page straight
at boards.greenhouse.io/<company> or jobs.lever.co/<company> — the
<company> slug there is the same one this actor's startUrls need. If a
career page is custom-branded, view its page source and search for
greenhouse.io or lever.co; the slug is in the embedded widget's URL.
Use cases
- Compensation benchmarking.
salary_min,salary_maxandsalary_currencyturn free-text pay ranges into numbers you can compare across companies, roles, and regions — without maintaining currency detection yourself. - 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.
- Skill-demand tracking. Aggregate
skillsacross 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.
| Event | Charged when |
|---|---|
apify-actor-start | Once, when a run starts. |
item-scraped | Once 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-item | Once 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 or Lever's standard hosted job board. Companies on other ATS platforms (Workday, SmartRecruiters, Ashby, custom systems) aren't covered by this actor.
- 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 postings. Lever's API doesn't include a
company display name in the posting data itself, so
companyis 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. There is no change detection or deduplication across runs; a posting scraped twice appears twice. - AI fields are inferred.
aivalues come from a language model reading the posting. A field the posting does not state comes backnullorunknownrather than a guess, but the values are not verified against any other source. - robots.txt. With
respectRobotsTxton, a disallow ends the crawl instead of working around it.
Development
make actor-setup # once, needs the networkmake build # compileall and pytestmake 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.