Greenhouse, Lever, Ashby & Workday Jobs Scraper with Salaries
Pricing
$0.00125 / job posting
Greenhouse, Lever, Ashby & Workday Jobs Scraper with Salaries
Open jobs from Greenhouse, Lever, Ashby, Workday and 4 more ATS — by company domain, or search ~11,000 company boards by keyword. Posted salaries, filters, and a daily only-new feed.
Pricing
$0.00125 / job posting
Rating
0.0
(0)
Developer
ScrapeBench
Maintained by CommunityActor stats
0
Bookmarked
9
Total users
3
Monthly active users
4 hours ago
Last modified
Categories
Features
Share
Pain points
- Several job-board Actors are published one per applicant-tracking system, so a mixed list of employers means running two or three of them and reconciling different output shapes.
- Most want the ATS board slug rather than the company, which you have to look up per employer before you can start.
- Career pages increasingly render the job list in JavaScript, so a generic page crawler comes back empty or partial.
- Boards get large — a single Workday tenant tested held 2,000 open roles — so a per-company cap and a visible total matter more than they sound.
- Large employers run Workday, whose tenant, pod and site name cannot be read off a domain, so a Workday board is normally addressed by a careers URL you have to hunt down per employer.
What we solve
- One input — a company domain, a careers URL, or an explicit board like 'greenhouse:stripe' — resolves to the right ATS automatically, including Workday tenants from a bare domain (nvidia.com, salesforce.com, disney.com).
- No company list at all: 'Search every company' runs your filters across ~11,000 Greenhouse, Ashby and Lever boards, read live at run time.
- One output schema across eight systems, so Greenhouse, Workday and Recruitee rows sort and filter together.
- The posted pay range as numbers — min, max, currency, interval — plus the board's own wording, from Greenhouse, Ashby, Lever and Recruitee wherever the employer published it (Breezy: its own pay text).
- Filters applied before billing — title words, excluded words, department, location, employment type, remote, has a salary, or words anywhere in the job text: you pay only for the jobs you asked for.
- 'Only jobs new since my last run' remembers what it delivered, so a scheduled run is a true new-openings feed and never bills the same posting twice.
- Hundreds of companies in a single run, with each company's outcome written to the run log.
- A company we cannot resolve returns a free, unbilled row naming the exact input that would work — never a silent zero.
Summary
Two ways in. Submit company domains — nvidia.com, stripe.com — and this Actor works out which applicant-tracking system runs each career page, Workday tenants included, and returns their open jobs. Or skip the list: turn on 'Search every company' and your filters run across ~11,000 Greenhouse, Ashby and Lever boards read live, e.g. every remote machine-learning role with a posted salary. Eight systems — Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee and Breezy — land in one schema: title, department, team, location, remote flag, employment type, posting date, requisition ID, the apply link and, where the employer posts one, the salary range. Filters (title words, excluded words, department, location, employment type, remote, has a salary, or words anywhere in the job text) run before anything is billed. Schedule it with 'Only jobs new since my last run' and each run returns only postings you have not had before — Workday included, which states no posting date. Every row says how the board was matched (detected_by) and cites the job URL the board itself served. Built for recruiters, sales teams treating a new posting as a hiring signal, compensation analysts reading posted pay bands, job seekers, and job boards that would otherwise run one Actor per ATS.
Who it's for
- Recruiters and sourcers tracking open roles across a target list of employers
- Sales and RevOps teams using new job postings as a hiring/expansion signal
- Job-board and aggregator operators ingesting employer boards at scale
- Talent-market and compensation analysts measuring hiring by department and location
How to use
Set the input, run the actor, and collect results from the run's dataset (export to JSON/CSV/Excel, or pull via the Apify API). Example input:
{"companies": ["greenhouse:figma","ashby:openai","stripe.com"],"titleKeywords": ["engineer"],"maxResults": 100}
See Inputs below for every available field.
What you get
One row per record:
| Field | Description |
|---|---|
company | The value you submitted — domain, careers URL or explicit board |
company_name | Employer name as the board states it (Greenhouse and SmartRecruiters publish it; Ashby, Lever and Workday do not, so it is null there) |
ats | greenhouse, lever, ashby, smartrecruiters or workday |
ats_slug | The board identifier on that ATS |
detected_by | How the board was matched: explicit, careers_page, or slug_match |
job_id | The board's own job identifier — stable across runs, so it de-duplicates |
title | Posted job title |
department / team | Department and team or job function, where the board publishes them |
location / locations | Primary location plus any additional locations on the same posting |
remote | The board's own remote flag where it publishes one (Ashby, SmartRecruiters); otherwise read from the board's own location wording, e.g. 'Remote - US' or 'Hybrid - London'. Null when the board says nothing either way |
employment_type | Full time, contract, intern and so on, where published |
posted_at | Publish timestamp — Greenhouse, Lever, Ashby and SmartRecruiters |
posted_text | The board's own wording when it gives no date, e.g. Workday's 'Posted Today' |
updated_at | Last-modified timestamp, where published |
apply_url | Where a candidate applies |
requisition_id | The employer's internal requisition reference, where published |
salary_min / salary_max | The posted pay range (Greenhouse, Ashby, Lever), where the employer published one; null otherwise — never estimated |
salary_currency / salary_interval | Currency (USD…) and the vendor's own interval wording, e.g. Ashby '1 YEAR' or Lever 'per-year-salary' |
salary_text | The board's own pay wording, verbatim, e.g. '$250K - $445K' or 'Annual Base Salary Range' |
description | Full job text — only when 'Include the full job description' is on |
source_url | The job page as the board serves it |
Sample:
{"source_url": "https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b","company": "ashby:openai","company_name": null,"ats": "ashby","ats_slug": "openai","detected_by": "explicit","job_id": "240d459b-696d-43eb-8497-fab3e56ecd9b","title": "Research Engineer","department": "Research","team": "Research","location": "San Francisco","locations": [],"remote": null,"employment_type": "FullTime","posted_at": "2025-04-05T00:03:20.653+00:00","posted_text": null,"updated_at": null,"apply_url": "https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b/application","requisition_id": null,"salary_min": 250000,"salary_max": 445000,"salary_currency": "USD","salary_interval": "1 YEAR","salary_text": "$250K - $445K","description": null}
Inputs
| Field | Required | Type | Default | Description |
|---|---|---|---|---|
company | no | string | "stripe.com" | A company domain (acme.com), a careers URL, or an explicit board such as 'greenhouse:stripe', 'lever:gopuff' or 'workday:nvidia'. The Actor works out which applicant-tracking system the company uses (Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Breezy). Kept forever alongside 'companies' — saved tasks and API callers send it. |
companies | no | array | ["stripe.com", "notion.so", "greenhouse:figma"] | Look up many companies in ONE run instead of starting a run per company. Takes the same values as 'Company'. Combined with 'Company' if you fill both, and duplicates are removed. Billing is unchanged: you are charged per job returned, not per company submitted. |
searchAllCompanies | no | boolean | false | Ignore 'Companies' and search a directory of ~9,400 Greenhouse and Ashby boards (plus ~1,900 Lever boards if you add Lever below) with your filters — e.g. title 'data analyst' + location 'Canada'. Boards are read live at run time, in random order, and the run stops at 'Maximum jobs for the whole run'. Title words are matched on titles only in this mode. |
atsPlatforms | no | array | [] | Which directories to search: greenhouse, ashby, lever. Default greenhouse + ashby. Lever is opt-in because its boards publish no light list, so searching all of them is much slower. |
maxTotalResults | no | integer | 500 | Run-wide spend cap for 'Search every company': the search stops once this many matching jobs are found (each still billed per job). Not used when you list companies — there 'Maximum jobs per company' applies. |
maxResults | no | integer | 1000 | Cap on jobs returned PER COMPANY, not per run — so a batch cannot silently return only the first rows overall and read as 'these companies aren't hiring'. When a board holds more, the run log states the board's own total next to what was returned. |
postedAfter | no | string | — | Keep only jobs published on or after this date (YYYY-MM-DD) — this is what turns the Actor into a weekly new-openings feed. Jobs whose board states no publish date (Workday says 'Posted Today' rather than a date) are KEPT, because dropping them would hide every Workday job and read as 'not hiring'. |
titleKeywords | no | array | [] | Keep only jobs whose title contains ANY of these words (case-insensitive), e.g. 'engineer', 'account executive'. Applied before billing — you pay only for matching jobs. Leave empty for every job. |
keywordsInDescription | no | boolean | false | Widen 'Job title contains' to the full job text, e.g. find every job mentioning 'Snowflake' or 'visa sponsorship'. Works on Greenhouse, Ashby, Lever, Workable and Recruitee (their boards carry the text); Workday, SmartRecruiters and Breezy still match on title, and so does 'Search every company'. Does not add the description to your rows unless 'Include the full job description' is on. |
excludeKeywords | no | array | [] | Drop jobs whose title contains ANY of these words, e.g. 'intern', 'senior', 'manager'. Applied before billing. |
departments | no | array | [] | Keep only jobs whose department or team contains ANY of these words, e.g. 'Engineering', 'Sales'. Boards that publish no department (Workday) match nothing here. Applied before billing. |
employmentTypes | no | array | [] | Keep only jobs whose employment type contains ANY of these, e.g. 'full time', 'contract', 'intern' — spelling variants such as 'FullTime' and 'Full-time' match alike. Applied before billing. |
onlyNew | no | boolean | false | Return only jobs this Actor has not delivered to you before under the same 'State name' — schedule it daily for a new-openings feed, Workday included (which states no posting date). The first run returns every matching job and sets the baseline. Remembered per job ID, so you are never billed twice for the same posting. |
stateKey | no | string | "default" | Names the memory 'Only jobs new since my last run' uses. Keep one name per feed (e.g. 'sales-hiring-signals'); use a new name to start a fresh baseline. Letters, digits and hyphens. |
locationKeywords | no | array | [] | Keep only jobs whose location (primary or any additional one) contains ANY of these words, e.g. 'London', 'Remote', 'United States'. Matches the board's own wording. Applied before billing. |
remoteOnly | no | boolean | false | Keep only jobs the board marks remote — its own remote flag, or its own location wording such as 'Remote - US'. Jobs whose board says nothing either way are left out. Applied before billing. |
salaryOnly | no | boolean | false | Keep only jobs whose board publishes pay: a range on Greenhouse, Ashby, Lever and Recruitee, or Breezy's pay text, where the employer entered one (SmartRecruiters, Workday and Workable never publish pay). Applied before billing. |
includeDescription | no | boolean | false | Off by default: descriptions are the bulk of the payload (one large board is ~16 KB per job) and most buyers filter on title, team and location first. Turn it on when you need the text. |
proxyConfiguration | no | object | {"useApifyProxy": false} | Optional. These are public vendor APIs and the plain path is the fastest one, so a proxy is genuinely not needed for the boards themselves. Enable it only if a company's own careers page blocks the detection step. |
Pricing (Pay Per Event)
You pay per result (job-posting) — no charge for empty runs. Example: 1000 job postings at $0.00125/result ≈ $1.25.
You are charged per job returned after your filters, not per company submitted — 1,000 jobs cost the same whether they come from one company or fifty. Marker rows explaining an unresolved company are free. Compute and proxy are included; you pay only the listed event.
Use cases
- Hiring-signal alerts — schedule a daily run over your account list with 'Only jobs new since my last run' on, and get only the roles opened since yesterday, Workday employers included.
- Market-wide job search — 'Search every company' for 'data engineer' in 'Canada' with a posted salary, no employer list needed.
- Sourcing a target list — submit 200 employer domains and get every open engineering role across all of them in one dataset.
- Aggregator ingestion — pull whole boards by ATS and reconcile them on the stable per-board job ID rather than on titles.
- Market research — count openings by department and location across a peer group to see where a sector is hiring.
- Pay benchmarking — pull every engineering role with a posted salary across 50 peer companies and compare the bands by level and city before setting an offer.
- Job-seeker feeds — a daily remote-only, salary-only list of new roles at the companies you want to work for, with the apply link on every row.
Why this actor
- Takes a company domain, so you do not have to look up an ATS board slug per employer first.
- Includes Workday from a bare domain — the system behind many of the largest employers (NVIDIA, Salesforce, Disney, Intel; one tenant tested held 2,000 open roles).
- Refuses to guess: a board is only used when you named it, when the company's own site links it, or when the vendor states a company name or website that matches — disney.com's Greenhouse slug belongs to someone else and is rejected — so you are never handed another company's jobs.
- Every row carries the board's own job URL, job ID and how the board was matched (
detected_by), so a result is auditable and de-duplicates cleanly across runs. - Salary is never estimated: a range appears only where the employer posted one, and the board's own wording rides along in
salary_text. - $1.25 per 1,000 jobs, charged per job returned after your filters rather than per company submitted.
Limitations & updates
Covers the eight applicant-tracking systems listed; a company on any other system (or hosting its own board, like Walmart) will not resolve, and returns a free marker row saying so. Automatic detection from a domain worked for 11 of 14 companies tested on 2026-09-06 — the misses were career pages rendered entirely in JavaScript, which expose no ATS link to read; those still work if you pass the board or careers URL directly. Workday resolves from a bare domain only when its tenant is named after the company and something on it names the company; otherwise pass 'workday:
FAQ
Which applicant-tracking systems are supported?
Eight: Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee and Breezy HR. Each is read from that vendor's own public job-board endpoint, so there is no login, no API key and no browser rendering involved. 'Search every company' covers Greenhouse, Ashby and (opt-in) Lever.
How does it know which ATS a company uses?
Tried in this order. If you name the board — 'greenhouse:stripe', 'workday:nvidia', or a careers URL — that wins. Otherwise it looks for an ATS link on the company's own careers page, which proves the board belongs to them. Failing that it derives a likely board name from the domain and accepts it only if the vendor states a company name or website that matches (Workable states the employer's own website; a Workable account with no open jobs is passed over, because large employers keep dormant ones). Last, it looks for a Workday tenant named after the company and accepts it only if one of its careers sites or the hiring organisation on a live job names the company: on 2026-10-31 that resolved nvidia.com, salesforce.com, disney.com and intel.com; boeing.com's tenant names neither, so it needs 'workday:boeing'. Every row records which path applied, in detected_by.
Can I search without a list of companies?
Yes — turn on 'Search every company'. Your filters run across ~11,000 boards: 5,974 Greenhouse and 3,418 Ashby by default, plus 1,926 Lever if you add Lever under 'Platforms to search'. Boards are read live at run time in random order, and the run stops at 'Maximum jobs for the whole run' (default 500). On 2026-10-31 'machine learning' + remote only returned 60 jobs from 31 employers after reading 1,684 boards in under 3 minutes. Title words match titles only in this mode. If the run's time limit or a vendor's rate limit stops it before every board was read, you get a free 'truncated' row saying how many were searched. The directory lists boards known to be live on 2026-10-31; a board created since is not in it, so name it in 'Companies' instead.
How does 'Only jobs new since my last run' work?
The Actor remembers the ID of every job it delivered to you under a 'State name' (default 'default') and skips those next time — before the per-company cap, so 'maximum 100' means 100 new jobs. The first run returns every match and sets the baseline. It works on Workday too, which states no posting date, and you are never billed twice for the same posting. Use a different state name per feed; a new name starts a fresh baseline.
What happens when a company cannot be resolved?
You get one free, unbilled row explaining why and naming the input that would work, for example 'lever:acme'. It is never a silent empty result, because 'we could not find the board' and 'this company is not hiring' are different answers and only one of them is our fault. On a 14-company test on 2026-09-06, 11 resolved from the domain alone and the three that did not were companies whose careers page is entirely JavaScript.
Why is posted_at empty on some rows?
Workday publishes a relative phrase — 'Posted Today' — rather than a date. Rather than invent a timestamp, those rows leave posted_at null and keep the board's own wording in posted_text. The other systems publish a real timestamp. For the same reason, the 'Posted on or after' filter keeps undated rows instead of dropping them, which would hide every Workday job; for a Workday feed use 'Only jobs new since my last run' instead.
Do I pay per company or per job?
Per job returned. Submitting 50 companies that collectively have 1,000 open roles costs the same as one company with 1,000 roles. Companies that resolve to nothing, and boards with no open jobs, are free.
How many jobs can one company return?
Whole boards, and they get large — on 2026-09-06 the boards in the example input held 617, 132 and 765 open roles, and one Workday tenant tested held 2,000. Use 'Maximum jobs per company' to cap it; the cap applies per company, not per run, and the run log always states the board's own total next to what was returned so a cap can never read as completeness.
Why is remote sometimes null instead of false?
Because the board did not say. Ashby, SmartRecruiters, Workable, Recruitee and Breezy publish a real remote flag; Greenhouse and Workday publish none, so for those the value is read from the board's own wording — 'Remote - US' gives true, 'Hybrid - London' gives false. A posting that just says 'Dublin' says nothing about remote work, and this Actor returns null there rather than asserting false. Filtering for remote roles gives the same answer either way; the difference only shows when you filter for non-remote, and there null is the honest value.
Does it return salaries?
Yes, wherever the employer posted a range: Greenhouse, Ashby and Lever all publish one when asked. On 2026-10-31, 93 of 140 Figma jobs (Greenhouse), 645 of 810 OpenAI jobs and 165 of 172 Ramp jobs (Ashby) carried a range; Stripe and Vercel posted none on the board, and Lever boards rarely do (2 of 779 at Gopuff). Recruitee publishes a structured range where the employer entered one, and Breezy a pay text (kept verbatim in salary_text, never parsed into numbers). SmartRecruiters, Workday and Workable publish no pay field. You get salary_min, salary_max, salary_currency, the vendor's interval and its own wording in salary_text. Greenhouse states no interval field — its range title ('Annual Base Salary Range', 'Internship') says it, so an hourly intern range shows as e.g. 46 with that title. Turn on 'Only jobs with a posted salary' to pay only for jobs that have one.
Can I filter before paying?
Yes. 'Job title contains', 'Job title must NOT contain', 'Department or team contains', 'Location contains' and 'Employment type' match any of the words you give (case-insensitive) against the board's own wording; 'Also match title words in the job description' widens the title match to the job text (Greenhouse, Ashby, Lever, Workable, Recruitee); 'Remote jobs only' keeps jobs the board marks remote; 'Only jobs with a posted salary' keeps jobs with a posted range or pay text. Filters run before billing, and the cap 'Maximum jobs per company' counts matching jobs, so 100 engineers means 100 engineers rather than the engineers among the first 100. A company with no matching job returns one free marker row.
What is not in the output?
Skills, requirements and seniority as separate columns, and any salary the employer did not post. Everything returned comes from the board; nothing here is estimated or inferred by a model.
Is a proxy needed?
No. These are public vendor endpoints and the direct path is the fastest one, so the proxy input is off by default. Turn it on only if a particular company's own careers page blocks the detection step.
Which actor to choose
Other Actors in the portfolio that pair with this one:
- Business Email, Phone & Contact Details Scraper — You have the employers and now need contact details for outreach rather than their open roles.
- US Business Entity Search & Leads Scraper (Secretary of State) — You want newly formed companies to build the target list this Actor then checks for hiring.
Guides & use cases
Written up on scrapebench.dev — the bench that runs and verifies this actor against the live source every night:
- How-to: How to run Greenhouse, Lever, Ashby & Workday Jobs Scraper with Salaries
- Use case: Benchmark Software Engineer Pay From Posted Salary Ranges
- Use case: Every Open Job at a Company, From Its Career Page
- Use case: New Job Postings This Week Across a Company List
- Use case: Open Roles From a Workday Careers Site
More actors, coverage and nightly verification results: scrapebench.dev
Works with AI assistants (MCP)
Callable as an MCP tool, so Claude, Cursor, VS Code Copilot and other MCP clients can run it directly. Grab the config from the MCP tab on this page — Apify hosts the server and keeps that snippet current, and OAuth signs you in on first connect, so no API token goes in your config file.
Then just ask:
"List the open engineering jobs at Figma (greenhouse:figma) and OpenAI (ashby:openai) that post a salary, with the pay range and location."
Run 2026-10-31 with titleKeywords ['engineer'] and salaryOnly: 31 Figma and 318 OpenAI jobs matched. A domain such as stripe.com resolves on its own; for a JavaScript-only careers page name the board ('lever:gopuff') or paste its careers URL. Runs started this way bill exactly like any other run.
Data & lawful use
This actor collects publicly available information that Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Breezy HR or the employers whose career pages it reads publishes for public lookup — licence records, business listings and the contact details professionals list there. Some of it identifies individuals (sole proprietors, licence holders, agents), so treat any names, phone numbers and emails in your results as personal data.
When you run this actor, you decide what is collected and what it is used for, so you are the controller of that data and we act only as your processor (Apify Standard Actor Contract). You need a lawful basis for your use, must honour opt-out and deletion requests, and must follow the marketing rules that apply to you (CAN-SPAM, TCPA, GDPR, CCPA and similar). Don't use the output for unsolicited bulk messaging, for screening covered by the FCRA, or for anything the source's own terms forbid.
Your results are stored in your own Apify account. We don't keep a copy of your results and don't sell or share them.
Disclaimer
This is an independent tool. It is not affiliated with, endorsed by or sponsored by Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Breezy HR or the employers whose career pages it reads. Names and marks are used only to describe the data source. Records are provided as published by the source and may be out of date or incomplete. For anything consequential (hiring, a permit, a legal decision), confirm the record with the issuing agency. You are responsible for making sure your use complies with applicable law and the source's terms.
Need help?
Open an issue on this actor's Issues tab and we'll respond there. Bug reports, missing fields and feature requests are all welcome. Guides and examples: scrapebench.dev.
If you are a person named in this data and want your record removed from our copy, email apify-help@scrapebench.dev; the source agency remains the official record.
Your run may be used to improve our services. If something looks off, or you want this actor to fit your use better, please share your run data with us: Apify Console → Settings → Security → Share run data with developers. It lets us see exactly what went wrong and keep improving the actor.
If this actor saved you time, a short review on its Store page helps other buyers find it.