ATS Job Scraper: Greenhouse, Lever, Workday, Oracle +10 More avatar

ATS Job Scraper: Greenhouse, Lever, Workday, Oracle +10 More

Pricing

from $1.50 / 1,000 job results

Go to Apify Store
ATS Job Scraper: Greenhouse, Lever, Workday, Oracle +10 More

ATS Job Scraper: Greenhouse, Lever, Workday, Oracle +10 More

Open jobs from Greenhouse, Lever, Ashby, Workday, Oracle HCM, BambooHR, Workable, Recruitee, SmartRecruiters, Personio, Rippling, Teamtailor, Breezy & Gem boards as unified JSON: title, salary, location, remote, apply link. New/removed job alerts. No login. $1.50 per 1,000 jobs.

Pricing

from $1.50 / 1,000 job results

Rating

0.0

(0)

Developer

SteadyScrape

SteadyScrape

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 hours ago

Last modified

Share

ATS Job Feed & Scraper: Greenhouse, Lever, Ashby, Workday, Oracle, Workable, BambooHR & More

Get every open job posting from any company's Greenhouse, Lever, Ashby, Workday, Oracle Cloud HCM, BambooHR, Workable, Recruitee, SmartRecruiters, Personio, Rippling, Teamtailor, Breezy HR or Gem careers page as one clean, unified JSON feed. You give it a list of company job boards (URLs, slugs, or company names from the built-in list), and it returns one record per job with title, department, salary range, remote/hybrid/onsite, parsed city/region/country, employment type, posted date, job and apply links, and the full description. Schedule it daily with Only new jobs and you get a change feed of new (and removed) postings.

  • Official public job-board APIs. It reads the JSON endpoints each ATS publishes for career pages. No login, no cookies, no proxies, no browser.
  • 14 ATS platforms, 1 schema. Mix Greenhouse, Lever, Ashby, Workday, Oracle Cloud HCM, BambooHR, Workable, Recruitee, SmartRecruiters, Personio, Rippling, Teamtailor, Breezy HR and Gem boards in a single run and get identical fields for all of them.
  • Paste any board URL. The platform is auto-detected. A bare company slug like figma works too, and so does a company name or domain from the built-in company list (for example Bosch Group or stripe.com).
  • Job change detection. Output only jobs you haven't received before, plus optional "removed" records when a job is taken down.
  • Salary data. Structured where the ATS exposes it (Ashby compensation, Greenhouse pay transparency, Lever salaryRange, Recruitee, SmartRecruiters, Personio, Rippling and Breezy salary fields), otherwise parsed from the description text. salary.source tells you which.
  • Pay per result. $1.50 per 1,000 jobs. Removed-job records and the run summary are free.
  • Robust. Retries with backoff, one broken board never fails the run, and it saves its results before the run timeout instead of losing them. A per-company status report is saved to OUTPUT.

Note: This Actor fetches the boards you list. It does not search every company on the internet for a keyword. To find jobs at many companies, list their boards (you can pass hundreds in one run) and filter by keyword, location, department or date.

What can you use it for?

  • Job alerts. "Tell me when Stripe, Ramp or NVIDIA posts a new engineering role in Canada." Run on a schedule with Only new jobs and send results to email, Slack or a webhook.
  • Recruiter and sales leads from hiring signals. See which companies are hiring for which roles, where and at what pay. A company hiring its first data engineer or a new sales team is a buying signal for many B2B products.
  • Labor-market and salary research. Collect structured salary ranges, locations, remote share and departments across many employers.
  • Job boards and aggregators. Feed a niche job board (for example "remote AI jobs" or "climate tech jobs") with fresh postings every day, with apply links that go straight to the employer's ATS.
  • AI agents and LLM workflows. Agents can call this Actor through the Apify API or Apify MCP server to answer "what roles is company X hiring for?" with structured, current data.

Quick start

  1. Click Try for free (or Start).
  2. In Company job boards, paste the careers page URLs of the companies you want, for example:
    https://job-boards.greenhouse.io/stripe
    https://jobs.lever.co/spotify
    https://jobs.ashbyhq.com/ramp
    https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite
  3. Optionally add filters (title keywords, locations, remote only, posted within N days) and a Max jobs per company cap.
  4. Click Start. Jobs appear in the Output tab, where you can download them as JSON, CSV, Excel or HTML, or read them through the API.

Example input

{
"companies": [
"https://job-boards.greenhouse.io/stripe",
"https://jobs.lever.co/zoox",
"https://jobs.ashbyhq.com/ramp",
"https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
],
"keywords": ["engineer"],
"excludeKeywords": ["intern"],
"locations": ["US", "Canada"],
"postedWithinDays": 14,
"maxJobsPerCompany": 200,
"onlyNewSinceLastRun": true,
"emitRemovedJobs": true
}

Run it from the API

curl -X POST "https://api.apify.com/v2/acts/steady-scrape~ats-job-feed/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"companies": ["greenhouse:stripe", "ashby:ramp"], "keywords": ["engineer"], "maxJobsPerCompany": 50}'

How to find a company's job board (slug)

Open the company's careers page, click any job, and look at the address bar. The URL tells you the ATS and the slug. You can paste the board URL as is, or a job URL from it, or use the short platform:slug form.

ATSWhat the URL looks likeSlugShort form
Greenhousejob-boards.greenhouse.io/stripe or boards.greenhouse.io/stripe, or an embedded board boards.greenhouse.io/embed/job_board?for=discordstripegreenhouse:stripe
Leverjobs.lever.co/spotify (EU boards: jobs.eu.lever.co/<company>)spotifylever:spotify / lever-eu:<company>
Ashbyjobs.ashbyhq.com/ramprampashby:ramp
Workdaynvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSitetenant nvidia, data center wd5, site NVIDIAExternalCareerSiteworkday:nvidia.wd5/NVIDIAExternalCareerSite
Workday (alt. domain)wd3.myworkdaysite.com/recruiting/<tenant>/<site>paste the URL
BambooHRacme.bamboohr.com/careersacmebamboohr:acme
Workableapply.workable.com/huggingface/huggingfaceworkable:huggingface
Recruiteeacme.recruitee.comacmerecruitee:acme
SmartRecruitersjobs.smartrecruiters.com/Wise or careers.smartrecruiters.com/Wisecompany ID Wisesmartrecruiters:Wise
Personioacme.jobs.personio.de (or .com)acmepersonio:acme
Oracle Cloud HCMjpmc.fa.oraclecloud.com/hcmUI/CandidateExperience/en/sites/CX_1001/jobshost jpmc.fa.oraclecloud.com, site CX_1001 (or the site name in the URL)oraclehcm:jpmc.fa/CX_1001
Ripplingats.rippling.com/rippling/jobsripplingrippling:rippling
Teamtailorcareer.teamtailor.com/jobs (regional hosts like acme.na.teamtailor.com work too)careerteamtailor:career, or teamtailor:careers.acme.com for a custom domain
Breezy HRacme.breezy.hracmebreezy:acme
Gemjobs.gem.com/accelaccelgem:accel

Tips:

  • If a company's careers page is on its own domain (e.g. company.com/careers), click a job: the apply page usually reveals the ATS URL.
  • A bare slug (e.g. figma) is first looked up in the built-in company list, then tried on Greenhouse, Ashby and Lever. Workday always needs the full URL or the workday:tenant.wdN/site form, because the site name differs per company. For the other platforms, use the URL or the platform:slug form. Oracle Cloud HCM needs the full Candidate Experience URL (or oraclehcm:host/site), because each company has its own host and site. Teamtailor boards on a company's own domain need teamtailor:<that domain>.
  • The language part of Workday URLs (/en-US/) is optional and ignored.
  • If a slug is wrong, that board shows Board not found (404) in the run summary and the other boards still run.

Built-in company list

You can also enter a company name or domain (Bosch Group, ServiceNow, stripe.com, https://wise.com). The Actor looks it up in a small bundled table of about 580 company job boards: about 380 on the first 9 platforms (Greenhouse through Personio) and 40 each on Rippling, Teamtailor, Breezy HR, Gem and Oracle Cloud HCM. Every board in the table was checked live and had open jobs when the table was built (October 2026). Matching ignores case, punctuation, www., the domain ending and suffixes like Inc or GmbH.

  • The list is small on purpose. It is not a directory of every company. If a name is not in it, the run summary lists it under unresolvedInputs with a clear message, and you can paste the company's careers board URL instead.
  • Names that matched are listed under resolvedByLookup in the run summary, and those rows have resolvedVia: "lookup:<name>", so you can check what each name was mapped to.
  • An explicit URL or platform:slug always wins over the list.
  • Companies sometimes switch ATS. If a looked-up board stops working, paste the current careers URL.

The table was compiled from these open datasets (see Data sources and credits).

Pricing

This Actor uses pay-per-event pricing:

  • $1.50 per 1,000 jobs delivered ($0.0015 per job result).
  • A tiny Actor-start fee of $0.00005 per run (at up to 1 GB memory).
  • Free: removed-job records, error reports and the run summary.

You pay only for job records written to the dataset. Filters are applied before charging, so jobs you filter out cost nothing.

What you fetchCost
100 jobsabout $0.15
1,000 jobsabout $1.50
5,000 jobs (a full first pull of several large boards)about $7.50
Daily Only new jobs feed that finds 200 new jobs per dayabout $0.30 per day
Daily Only new jobs feed with no new jobs that dayabout $0.00005 (start fee only)

Platform usage (compute) is included in the price. You can also set a maximum total charge for a run in the run options. The Actor stops cleanly at that limit and does not deliver jobs it can't bill, so you never pay more than you set.

Only new jobs and removed jobs

Turn on Only new jobs since last run (onlyNewSinceLastRun) for scheduled runs:

  • The Actor remembers which job IDs it has already delivered for each board, in a named key-value store (stateStoreName, default ats-job-feed-state).
  • Each run outputs only jobs it has not delivered before, marked changeType: "new". You pay only for those.
  • First run: by default every current job is output once (firstRunEmitsAll: true). Set it to false to record a silent baseline and get only jobs posted after that.
  • Removed jobs: with emitRemovedJobs: true, jobs that disappeared from a board since the last run are output as free records with changeType: "removed", firstSeenAt and removedDetectedAt. This needs a complete listing of the board, so for Workday it only works when no cap or keyword pre-filter limited the listing. On SmartRecruiters, a job missing from the listing is re-checked directly before it is reported as removed, because its paged listing can skip a job while the board is changing.
  • Max jobs per company in this mode caps the new jobs per run. Jobs held back by the cap are delivered on later runs.
  • Use different stateStoreName values for independent feeds (for example one per customer or per alert).

Stops early instead of timing out

If a run is about to hit its timeout (for example you passed many large Workday, BambooHR or SmartRecruiters boards with a short timeout), the Actor stops starting new requests shortly before the deadline (about 20% of the timeout, at most 2 minutes), saves every job collected so far and writes the run summary. The run still succeeds, and the status message says how many boards were completed. The summary lists incompleteBoards and notStartedBoards. The Only new state is updated only for boards that finished, so nothing is lost or skipped next time. To get everything, raise the timeout or reduce the boards or maxJobsPerCompany.

Input

FieldDescription
companies (required)Board URLs, job URLs, platform:slug, or company names/domains from the built-in list. See how to find a board.
keywords / excludeKeywordsKeep jobs whose title contains any of / none of these words (case-insensitive).
locationsCity, region, country name or ISO country code ("US", "Toronto", "Germany").
remoteOnlyOnly remote jobs.
departmentsSubstring match on department or team.
postedWithinDaysOnly jobs posted in the last N days. Jobs with no date are kept.
includeDescriptionInclude the HTML and plain-text description (default on).
maxJobsPerCompanyCap per board (in Only new mode: cap on new jobs per board).
onlyNewSinceLastRunOutput only jobs not delivered in earlier runs.
firstRunEmitsAllWith Only new: on a board's first run, output everything (default) or just record a baseline.
emitRemovedJobsWith Only new: also output free changeType: "removed" records.
stateStoreNameName of the state store. Use different names for independent feeds.
maxConcurrency, maxRetriesPoliteness and robustness settings.

Output

One dataset item per job, with the same fields on every platform. Example:

{
"jobId": "ashby:ramp:34413f8d-26bf-4bbc-8ade-eb309a0e2245",
"sourceJobId": "34413f8d-26bf-4bbc-8ade-eb309a0e2245",
"platform": "ashby",
"boardSlug": "ramp",
"boardUrl": "https://jobs.ashbyhq.com/ramp",
"company": "Ramp",
"title": "Security Engineer, Cloud",
"department": "Engineering",
"team": "Backend",
"locations": [
{"raw": "New York, NY (HQ)", "city": "New York City", "region": "New York", "country": "United States", "countryCode": "US", "isRemote": false},
{"raw": "Remote (Canada)", "city": null, "region": null, "country": "Canada", "countryCode": "CA", "isRemote": true}
],
"locationText": "New York, NY (HQ)",
"isRemote": true,
"workplaceType": "HYBRID",
"employmentType": "FULL_TIME",
"employmentTypeRaw": "FullTime",
"salary": {"min": 211400, "max": 290600, "currency": "USD", "interval": "YEAR", "source": "structured", "raw": "$211.4K - $290.6K"},
"postedAt": "2026-04-07T17:12:35.753000Z",
"updatedAt": null,
"jobUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245",
"applyUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application",
"requisitionId": null,
"descriptionHtml": "<h1><strong>About Ramp</strong></h1>...",
"descriptionText": "About Ramp\n\nRamp is building ...",
"changeType": "new",
"scrapedAt": "2026-10-25T21:10:02Z"
}

Output fields

FieldTypeDescription
jobIdstringStable unique ID: platform:board:sourceJobId. Use it to deduplicate.
sourceJobIdstringThe job's ID in the ATS.
platformstringgreenhouse, lever, ashby, workday, bamboohr, workable, recruitee, smartrecruiters, personio, oraclehcm, rippling, teamtailor, breezy or gem.
boardSlugstringBoard identifier (e.g. stripe, nvidia.wd5/NVIDIAExternalCareerSite, jpmc.fa/CX_1001).
boardUrlstringPublic careers board URL.
companystringCompany name as reported by the ATS (or the slug).
titlestringJob title.
department / teamstringDepartment and team, where the ATS provides them.
locationsarrayParsed locations: raw, city, region, country, countryCode (ISO 3166-1 alpha-2), isRemote.
locationTextstringPrimary location as written in the ATS.
isRemotebooleanTrue if the job is remote or any of its locations is remote.
workplaceTypestringREMOTE, HYBRID, ONSITE or null.
employmentTypestringFULL_TIME, PART_TIME, CONTRACT, INTERN, TEMPORARY, OTHER or null.
employmentTypeRawstringEmployment type exactly as the ATS reports it.
salaryobjectmin, max, currency, interval (YEAR, MONTH, WEEK, DAY, HOUR), source (structured or text), raw. Null if no pay is published.
postedAt / updatedAtstringISO 8601 UTC timestamps, where available.
jobUrl / applyUrlstringJob page and application page.
requisitionIdstringEmployer's requisition number, where available.
descriptionHtml / descriptionTextstringFull description as HTML and plain text (if includeDescription is on).
changeTypestringnew or removed in Only new mode, otherwise null.
firstSeenAt / removedDetectedAtstringOnly on removed records.
scrapedAtstringWhen the record was fetched (ISO 8601 UTC).

The run summary is saved to the key-value store record OUTPUT: totals plus per-board status, counts, duration and errors (e.g. Board not found (404)), plus unresolvedInputs (entries that were not a board URL, slug or known company) and resolvedByLookup (company names matched in the built-in list).

What each platform provides

FieldGreenhouseLeverAshbyWorkday
Salarypay-transparency ranges, else textsalaryRange, else textcompensation API, else texttext only
Department / team✓✓ (team; dept if set)✓–
Employment typeonly via custom metadata✓✓✓
Workplace typefrom location text✓✓from location text
Posted datefirst publishedcreatedpublishedstart date / "Posted N days ago"
Updated date✓–––
FieldBambooHRWorkableRecruiteeSmartRecruitersPersonio
Salarycompensation text on the job pagetext only✓ salary fieldscompensation fields (needs descriptions on), else textsalary fields where published, else text
Department / teamdepartment✓ (team = function)departmentdepartment or function✓ (team = category)
Employment type✓✓✓✓✓
Workplace type✓ (onsite / remote / hybrid)remote flag only✓remote / hybrid flagsfrom location text
Posted date✓publishedpublishedreleasedcreated
Updated date––✓––
FieldOracle Cloud HCMRipplingTeamtailorBreezy HRGem
Salarytext onlypay range fields (needs descriptions on), else texttext only✓ salary field (structured on the job page)text only
Department / teambusiness unit or job family / job function✓✓ (team = role)department✓
Employment type✓ (schedule)✓ (needs descriptions on)–✓✓
Workplace type✓ where the employer sets it✓✓ (remote status)remote flag✓
Posted date✓created (needs descriptions on)publishedpublishedfirst published
Updated date––––✓

Requests per board: Greenhouse, Lever, Ashby, Workable, Recruitee, Personio, Teamtailor and Gem return a whole board in one or a few requests. BambooHR always needs one request per job (the posted date and pay are only on the job page). SmartRecruiters, Oracle Cloud HCM, Rippling and Breezy HR need one request per job only when descriptions are on; Workday always does. Oracle lists 200 jobs per request and returns at most the newest 10,000 jobs per site. maxJobsPerCompany limits these per-job requests.

Performance

Tested on the Apify platform on Oct 25, 2026 at 256 MB, with the first four platforms:

  • 670 jobs from 8 boards (2 per platform, capped at 100 jobs per company) in 47 s.
  • A second run in Only new mode took 6 s. It delivered the 205 jobs that the cap had held back and nothing it had already delivered.
  • The default memory of 256 MB is enough. Peak memory was about 147 MB.

Greenhouse, Lever, Ashby, Workable, Recruitee, Personio, Teamtailor and Gem return a whole board in a few requests, so they are fast. Workday, BambooHR and (with descriptions on) Oracle, Rippling, Breezy and SmartRecruiters need one request per job for details, so large boards on them take longer.

How it compares

Verified on Apify Store, Oct 25, 2026. Prices shown are the Free-tier price per job.

ActorPlatformsPrice per 1,000 jobsChange detection
This ActorGreenhouse, Lever, Ashby, Workday, Oracle Cloud HCM, BambooHR, Workable, Recruitee, SmartRecruiters, Personio, Rippling, Teamtailor, Breezy HR, Gem$1.50New + removed jobs
bovi/greenhouse-lever-ashby-job-scraperGreenhouse, Lever, Ashby, Recruitee, SmartRecruiters, Personio (no Workday)$1.50n/a
fantastic-jobs/greenhouse-jobs-api / workday-jobs-apiOne ATS per Actor$2.00n/a
memo23/career-site-ats-jobs-api116 ATS platforms$4.00 + $0.03 per runn/a

Source: Apify Store API (api.apify.com/v2/store, field currentPricingInfo), fetched Oct 25, 2026 (competitor rows; this Actor's platform list updated Oct 26, 2026). Competitor prices can change at any time. "n/a" means not checked.

FAQ

Is it legal to scrape job postings? (Not legal advice.) This Actor reads only public job postings that companies publish so that they get distributed, through the public JSON endpoints that power their own careers pages. It uses no login, collects no personal data about candidates or employees, and doesn't bypass any access control. You are responsible for how you use the data, e.g. respecting each site's terms when you republish it.

Will I get rate-limited or blocked? Unlikely at normal volumes. The Actor sends at most 5 parallel requests by default (maxConcurrency), and retries 429/5xx errors with exponential backoff (maxRetries). No proxies are needed. If a board fails anyway, it is reported in OUTPUT and the other boards still finish.

How do I run it on a schedule? In Apify Console, open the Actor, save your input as a task, then add a Schedule (e.g. daily at 08:00). Turn on Only new jobs so each run returns only fresh postings.

Can I send the jobs to Google Sheets, Slack, Zapier, Make or my own app? Yes. Use Apify integrations (Google Sheets, Slack, email, Zapier, Make, n8n and others) on the Actor or task, or add a webhook that calls your URL when a run succeeds. You can also read the dataset through the Apify API in JSON, CSV or Excel format.

Can AI agents use it? Yes. It can be called through the Apify API and the Apify MCP server. The input and output fields are fully described so agents can call it correctly.

Why are some fields null? The ATS doesn't publish them (see the platform table). Nothing is invented: salary is parsed from text only when an explicit currency range appears, and salary.source says so.

Can it search all jobs on Greenhouse or Workday by keyword? No. These ATSs have no public cross-company search. You list the company boards you care about (or company names from the built-in list), and the Actor fetches and filters them.

Workday boards with more than 2,000 jobs? Workday's public list endpoint appears to cap at 2,000 (NVIDIA reports exactly total: 2000). Use keywords or postedWithinDays to narrow very large boards.

What happens if I set a low timeout or a max charge? The Actor stops cleanly and saves what it has (see Stops early instead of timing out and Pricing).

More tools from SteadyScrape

  • Career Site Jobs Search: search open jobs by keyword across tens of thousands of company career sites, with remote, country, company and date filters.
  • Remote Jobs API: remote-only jobs from employer career sites, filtered by where you can work from (countries, regions, time zones).

Feedback and support

Found a bug, need another ATS, want a company added to the built-in list, or want a new field? Please open an issue in the Issues tab of this Actor.

Data sources and credits

The built-in company list was compiled from these open datasets, and every board was then re-checked live:

  • job-board-aggregator by Riley Dorrington (MIT License).
  • job-board-directory by kalebconfer-sys (CC0 1.0, public domain).
  • Hiring data from LastRound AI, licensed under CC BY 4.0. Source: LastRound AI Salary Transparency Study 2026 (dataset). Changes: the company/board entries were filtered to boards that were live with open jobs, normalized to platform:slug form and merged with the other sources.
  • SmartRecruiters company IDs were added by hand and checked live.
  • ats-career-page-urls by latmay, licensed under CC BY 4.0 (Rippling, Teamtailor, Breezy HR, Gem and Oracle Cloud HCM boards). Changes: reduced to board identifiers, filtered to boards that were live with open jobs, company names read from the boards.
  • state-of-ats-2026 by Kayvan Zahiri (MIT License): Oracle Cloud HCM career-site hosts.
  • Board URLs found in the public Common Crawl URL index.

Job postings themselves are fetched live from each company's public careers board at run time.