Workday, Greenhouse, Lever, Ashby and ATS Jobs Scraper avatar

Workday, Greenhouse, Lever, Ashby and ATS Jobs Scraper

Pricing

$1.50 / 1,000 listed jobs

Go to Apify Store
Workday, Greenhouse, Lever, Ashby and ATS Jobs Scraper

Workday, Greenhouse, Lever, Ashby and ATS Jobs Scraper

Workday jobs scraper plus Greenhouse, Lever, Ashby, Rippling, BambooHR, Jobvite and iCIMS careers page scraper. Give it companies, get one clean job feed row per opening.

Pricing

$1.50 / 1,000 listed jobs

Rating

0.0

(0)

Developer

Gerald Dobin

Gerald Dobin

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Give this Actor a list of companies and it returns every open job those companies are advertising, as clean rows in one schema. It reads each company's applicant tracking system through that system's own public job board endpoint, so the data is the same data the company publishes on its careers page: no rendering, no guessing, no stale copies. Fourteen systems are covered today: Workday, Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Personio, Teamtailor, Recruitee, Rippling, Jobvite, Breezy HR, BambooHR and iCIMS. You can point it at a board link such as https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite or https://jobs.lever.co/palantir, at a company's own careers page such as https://vercel.com/careers (the Actor loads it once and finds the board behind it), or at a short system:slug pair such as greenhouse:stripe. Titles, departments, locations, employment type, posting dates, salary ranges where the company publishes them, and the full job description in both HTML and plain text all come back in the same field names no matter which system the job came from.

Who it is for

Job aggregators and job boards that need clean feeds. Point the Actor at a few thousand employers, schedule it daily, and load the rows straight into your index. Every row carries a stable jobId, so you can upsert on it and spot the jobs that disappeared since yesterday without diffing free text.

Recruiters and sourcers tracking target companies. Keep a watch list of the twenty companies your candidates care about and see the moment a role opens, with the apply link and the pay range already in the row instead of buried three clicks into a careers site.

Sales teams using hiring signals as intent data. A company that just posted four data engineering roles is buying a data stack. Filter on job title keywords, push the results into your CRM, and let your reps work accounts that are visibly investing rather than accounts that merely match a firmographic filter.

What you get

One dataset row per unique job. Here is a real row from a test run against Ramp's Ashby board, with the two long description fields shortened for readability:

{
"ats": "ashby",
"companySlug": "ramp",
"companyName": null,
"jobId": "ashby:ramp:34413f8d-26bf-4bbc-8ade-eb309a0e2245",
"nativeId": "34413f8d-26bf-4bbc-8ade-eb309a0e2245",
"title": "Security Engineer, Cloud",
"department": "Engineering",
"team": "Backend",
"location": "New York, NY (HQ)",
"city": "New York City",
"country": "United States",
"remote": false,
"workplaceType": "hybrid",
"employmentType": "Full-time",
"seniority": null,
"salaryMin": 211400,
"salaryMax": 290600,
"salaryCurrency": "USD",
"salaryPeriod": "year",
"descriptionHtml": "<div><p>Ramp is a financial operations platform ...</p></div>",
"descriptionText": "Ramp is a financial operations platform ...",
"postedAt": "2026-04-07T17:12:35.753Z",
"updatedAt": null,
"applyUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application",
"sourceUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245",
"scrapedAt": "2026-09-07T23:03:29.062Z"
}

Every field is present on every row. A field is null when the applicant tracking system does not publish it, never missing and never an empty string. Dates are ISO 8601 in UTC. workplaceType is one of remote, hybrid, onsite or null, and remote always agrees with it. Salary fields are plain numbers plus a currency and a period, parsed out of whatever shape the board used.

How to use it

Inputs

InputWhat it does
companiesOne line per company: a board link, a careers page link, or a system:slug pair. Required. Workday boards are addressed by two names, so its pair carries both: workday:nvidia.wd5/NVIDIAExternalCareerSite.
keywordsKeep only jobs whose title contains one of these words. Case does not matter.
locationsKeep only jobs whose location, city or country contains one of these words.
remoteOnlyKeep only jobs the company marks as remote.
postedAfterKeep only jobs posted on or after this date, written as YYYY-MM-DD.
includeDescriptionOn by default. Turn it off for a faster, cheaper run when you only need titles and links; the two description columns stay in the output as nulls.
maxJobsPerCompanyStop after this many jobs per company. 0 means no limit. Worth setting on Workday boards, which often carry thousands of openings: the Actor stops paging as soon as it has this many. See the note below on how this interacts with filters.
maxConcurrencyHow many companies to work on at once. Lower it if a board starts rate limiting.

How maxJobsPerCompany behaves when you also set a filter. You always get up to that many jobs that actually match. On the boards that publish the whole job in the listing, that costs nothing extra. On the boards that need a second request per job, some filters can only be judged once that second request has happened: a Workday listing carries no posting date at all, and an iCIMS job card may carry no location. When a filter of that kind is set, the Actor keeps reading further down the board until it has enough matching jobs, rather than taking the first few and then discarding most of them. That costs more requests than an unfiltered run of the same size, and it stops at 2000 jobs examined per company, so a filter that matches almost nothing on a very large board returns what it found by then rather than reading the whole board. Filtering on job title keywords never costs extra on any board, because every listing carries the title.

A monitoring pattern that works. Schedule the Actor once a day against the same company list, write every run into the same named dataset, and deduplicate on jobId on your side. A jobId you have not seen before is a new opening. A jobId that stops appearing is a closed one. Because the id is built from the ATS, the board slug and the system's own job id, it stays the same across runs and across changes to the job title or location.

Calling it from the API

curl -X POST "https://api.apify.com/v2/acts/YOUR_USERNAME~ats-jobs-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"companies": ["greenhouse:stripe", "workday:ww.wd1/careers", "https://vercel.com/careers"],
"keywords": ["engineer"],
"includeDescription": false
}'

Add &format=csv to that URL for a spreadsheet instead of JSON. Results also stay in the run's dataset, so you can page through them later with the standard dataset endpoints.

MCP. Apify exposes its Actors over the Model Context Protocol, so an assistant such as Claude can call this scraper as a tool and answer questions like "which of these fifteen companies is hiring platform engineers in Berlin right now" without you writing any glue code.

Coverage and limits

Covered. Workday, Greenhouse (including EU boards and embedded job boards), Lever, Ashby, Workable, SmartRecruiters, Personio, Teamtailor, Recruitee, Rippling, Jobvite, Breezy HR, BambooHR and iCIMS. Between them these cover most startups and mid-market employers, a good share of large European ones, and with Workday and iCIMS a large part of the enterprise market too.

Workday takes two names, not one. A Workday board lives at a tenant host and publishes one or more career sites on it, so both halves are needed. Paste the board URL in any shape it comes in, including the ones with /en-US/ or a /job/... path, and the Actor works out the pair. If you prefer the short form, write it as workday:tenant.wdN/SiteName, for example workday:nvidia.wd5/NVIDIAExternalCareerSite. Workday boards are often very large, so set maxJobsPerCompany when you only want a sample: the Actor stops paging as soon as it has enough instead of walking the whole board.

Not covered. SuccessFactors, Taleo, Oracle Recruiting and JazzHR are not supported. Those systems either have no public job board endpoint or gate it behind per-tenant credentials.

A company must expose a public board. If an employer has switched its board to private, or publishes jobs only inside a rendered careers page with no underlying system, there is nothing to read and the Actor says so.

Descriptions. Greenhouse, Lever, Ashby, Teamtailor and Recruitee return the job body in the same call as the listing. Workday, SmartRecruiters, Workable, Rippling, BambooHR, Jobvite, iCIMS and Breezy need one extra request per job, so those companies take longer and cost more compute; turn includeDescription off when you do not need the body. Personio returns descriptions only when the employer fills them in on the board.

Dates. postedAt and updatedAt are only filled in when the board publishes a date the Actor can read exactly, in ISO 8601 or that system's documented format. A date it cannot read becomes null rather than a guess. Workday is the clearest case: its board list dates a job only as "Posted Today" or "Posted 5 Days Ago", which become real dates, while "Posted 30+ Days Ago" is a floor rather than a date and becomes null instead of pretending to be exactly thirty days old. postedAfter is checked when the run starts, so a value the Actor cannot parse stops the run with a message instead of quietly disabling your filter.

Salary. Ashby, Lever, Recruitee and Breezy publish structured pay ranges and the Actor passes them through. BambooHR and Jobvite publish pay as a display string or a schema.org block, and the Actor reads it when the numbers and the currency are unambiguous; a range it cannot read confidently is left null rather than reported wrongly. Greenhouse, SmartRecruiters and Workday usually do not publish a structured range, so salaryMin and salaryMax are null there even when a range appears inside the description text.

Companies that fail. A company that resolves to no known system produces a single row with error: "ATS not detected". A slug that no longer exists produces a row with error: "board not found". If a board answers with something that is not the shape it documents, you get error: "unexpected response from <system>" rather than a silent empty result, so a changed endpoint cannot look like a company that stopped hiring. These rows are free.

Addresses the Actor will not fetch. Only plain public http and https URLs on the default port are accepted. Links to an IP address, to localhost or a .internal name, or to any host that resolves onto a private, loopback, link local or cloud metadata address are refused, and that check is applied again on every redirect. Job descriptions are stripped down to ordinary formatting tags before they reach you, so no scripts, styles, embeds or javascript: links come through.

Run size. Up to 5000 companies and 200000 jobs in one run. Split larger lists across runs.

Pricing

Pay per unique job delivered. You are charged once for each job row the Actor writes into the dataset, and nothing else. There is no monthly subscription and no minimum.

  • Duplicate jobs inside a run are removed before they reach the dataset and are never charged.
  • Error rows are never charged.
  • Jobs removed by your keywords, locations, remoteOnly or postedAfter filters never reach the dataset, so they are never charged. On the systems that need a second request per job, those filters are applied before that request, so a narrow filter is a cheap run.

A run that finds nothing costs nothing. If you set a maximum spend on the run, the Actor stops fetching once it hits that ceiling and finishes cleanly with whatever it has already delivered, rather than failing.

Support

Something wrong with a row, or a company whose board the Actor cannot see? Open an issue on the Actor's Issues tab with the exact companies entry you used and the run id. Requests for another applicant tracking system are welcome; say which one and name a company that uses it, so the endpoint can be checked against a real board.

Runs are stateless and store nothing beyond the dataset and the key value store record for the run itself. The Actor reads only public job board endpoints and sends no credentials anywhere.