ATS Jobs Scraper: Greenhouse, Lever, Ashby & Workday avatar

ATS Jobs Scraper: Greenhouse, Lever, Ashby & Workday

Pricing

from $2.00 / 1,000 job scrapeds

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

ATS Jobs Scraper: Greenhouse, Lever, Ashby & Workday

Scrape every open job from a company's ATS by domain or board URL. Auto-detects Greenhouse, Lever, Ashby, Workday, SmartRecruiters and Workable from the careers page and pulls official public JSON feeds. Flat job schema, salary, remote flag, filters. No proxies.

Pricing

from $2.00 / 1,000 job scrapeds

Rating

0.0

(0)

Developer

Majd Hijazin

Majd Hijazin

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

ATS Jobs Scraper — Greenhouse, Lever, Ashby, Workday, SmartRecruiters

Give it a company domain, get every open job back. ATS Jobs Scraper finds a company's careers page, detects which applicant tracking system (ATS) it uses, and pulls all open positions from that ATS's official public job feed. You get one clean, flat dataset row per job: title, department, location, remote flag, employment type, posted date, apply URL, salary when published, and optional full description.

  • 6 ATSs, one schema: Greenhouse jobs, Lever jobs, Ashby jobs, Workday jobs, SmartRecruiters jobs and Workable jobs all come out in the same format.
  • Domain in, jobs out: pass stripe.com or crowdstrike.com. You don't need to know the board URL or slug.
  • Official JSON feeds, no HTML guessing: data comes from boards-api.greenhouse.io, api.lever.co, api.ashbyhq.com, Workday's cxs JSON, api.smartrecruiters.com and Workable's public widget API. These are the same feeds the companies' own careers pages use, so the data is complete, current and stable.
  • No proxies, no browser: plain HTTPS. This keeps runs fast (10+ companies in under a minute) and cheap.
  • $0.002 per job. You pay $0.01 per company only when an ATS is actually found. Domains with no supported ATS cost nothing.

Common uses: hiring-signal lead generation (who is hiring SDRs or data engineers right now), job board and aggregator feeds, competitor hiring intelligence, recruiting and sourcing pipelines, labor-market research and AI agents that need structured job data.


How it works

  1. Careers page scraper. For each domain the Actor fetches the homepage, follows careers/jobs links (including careers. / jobs. subdomains) and common paths like /careers. It finds ATS references in links, embeds, iframes, scripts and Next.js payloads. It obeys robots.txt and fetches at most one HTML page per second per host.
  2. ATS slug probe (fallback). If the site links to no ATS (common with custom React careers pages), the Actor tries the public ATS APIs with slugs derived from the domain, e.g. stripe.com → greenhouse:stripe. A probe counts only when the board's own company name, or text in its postings, matches the domain. This keeps it from attributing another company's board.
  3. Official feed. Jobs are read from the ATS's public JSON API, paging where the API requires it (Workday, SmartRecruiters).
  4. Normalize, filter, dedupe. Every record is mapped to the schema below. Your filters are applied, results are sorted newest first, and maxJobsPerCompany is enforced before anything is saved or charged.
ATSDetected fromFeed usedPosted dateSalary
Greenhouseboards.greenhouse.io, job-boards.greenhouse.io, embed ?for=boards-api.greenhouse.io/v1/boards/{slug}/jobs?content=truefirst_published (exact)parsed from pay-range text
Lever (US & EU)jobs.lever.co, jobs.eu.lever.coapi.lever.co/v0/postings/{slug}createdAt (exact)salaryRange (structured)
Ashbyjobs.ashbyhq.com, embedded boardsapi.ashbyhq.com/posting-api/job-board/{slug}publishedAt (exact)compensation tiers (structured)
Workday*.wdN.myworkdayjobs.com, wdN.myworkdaysite.com/wday/cxs/{tenant}/{site}/jobs"Posted N days ago" (day precision), exact with descriptions onparsed from description
SmartRecruitersjobs. / careers.smartrecruiters.comapi.smartrecruiters.com/v1/companies/{id}/postingsreleasedDate (exact)parsed from description
Workableapply.workable.com, *.workable.comapply.workable.com/api/v1/widget/accounts/{slug}published_on (date)parsed from description

Input

FieldTypeWhat it does
domainsarray of stringsCompany websites, e.g. ["stripe.com", "linear.app"]. ATS is auto-detected.
boardUrlsarray of stringsKnown boards: any board URL, or shorthands greenhouse:figma, lever:palantir, lever:eu/slug, ashby:ramp, workday:visa/Visa@wd5, smartrecruiters:ServiceNow, workable:huggingface.
keywordstringKeeps jobs whose title, department or team contain all the words. "machine learning" engineer matches the quoted phrase and the word.
locationstringKeeps jobs whose location contains the text. Use `
remotebooleanKeeps only remote jobs.
postedWithinDaysintegerKeeps only jobs first published in the last N days. Jobs with no date are excluded.
maxJobsPerCompanyinteger (default 500)Caps the number of jobs saved and charged per company, newest first.
includeDescriptionboolean (default false)Adds the plain-text descriptionText. For Workday it also adds the exact posting date and employment type.
detectBySlugboolean (default true)Turns the slug-probe fallback on or off.
maxConcurrencyinteger (default 4)Number of companies processed in parallel. Each host is still rate-limited.

Example: engineering jobs posted in the last 30 days at four companies

{
"domains": ["stripe.com", "linear.app", "crowdstrike.com"],
"boardUrls": ["lever:palantir"],
"keyword": "engineer",
"postedWithinDays": 30,
"maxJobsPerCompany": 50
}

Example: every open job at a list of target accounts (lead generation)

{ "domains": ["ramp.com", "notion.so", "datadoghq.com", "airbnb.com", "servicenow.com", "visa.com"] }

Output

One dataset item per job. Every field is always present; unknown values are null.

{
"company": "Ramp",
"domain": "ramp.com",
"ats": "ashby",
"atsSlug": "ramp",
"jobId": "b7514711-8a29-4bd2-a97a-967be14e336f",
"title": "Senior Backend Engineer | Token Spend Management",
"department": "Engineering",
"team": "Backend",
"location": "New York, NY (HQ); Remote (Canada); Remote (US)",
"remote": true,
"workplaceType": "hybrid",
"employmentType": "Full-time",
"postedAt": "2026-10-20T13:40:20.264Z",
"postedAtApproximate": false,
"updatedAt": null,
"applyUrl": "https://jobs.ashbyhq.com/ramp/b7514711-8a29-4bd2-a97a-967be14e336f/application",
"jobUrl": "https://jobs.ashbyhq.com/ramp/b7514711-8a29-4bd2-a97a-967be14e336f",
"descriptionText": null,
"salaryMin": 204000,
"salaryMax": 280000,
"salaryCurrency": "USD",
"salaryPeriod": "YEAR",
"salaryText": "$204K - $280K",
"scrapedAt": "2026-10-20T18:14:55.512Z",
"sourceUrl": "https://api.ashbyhq.com/posting-api/job-board/ramp?includeCompensation=true"
}
FieldMeaning
company, domainCompany name (from the ATS, else the website) and the domain you submitted (null for direct boards).
ats, atsSluggreenhouse · lever · ashby · workday · smartrecruiters · workable, plus the board identifier (Workday: tenant/site).
jobIdThe ATS's own job ID (Workday: requisition ID). Stable across runs, so you can diff runs to find new or closed roles.
title, department, teamAs published.
location, remote, workplaceTypeLocation text (multiple locations joined with ; ). remote is true/false/null. workplaceType is remote/hybrid/onsite/null.
employmentTypeFull-time, Part-time, Contract, Internship, or the raw value.
postedAt, postedAtApproximate, updatedAtISO 8601 UTC. postedAtApproximate is true when the date comes from Workday's relative label.
applyUrl, jobUrlDirect application link and public job page.
descriptionTextPlain text, only when includeDescription is on.
salaryMin, salaryMax, salaryCurrency, salaryPeriod, salaryTextStructured pay from Ashby and Lever, otherwise a pay range stated in the posting ($150,000—$200,000 USD). null when the employer publishes none.
scrapedAt, sourceUrlWhen the record was fetched and from which public ATS endpoint.

The run also writes an OUTPUT record in the key-value store with one entry per input. Each entry has the detected boards, the detection method (careers_page, api_slug_probe, direct_input), job counts, timing, a clear status (ok, no_matching_jobs, no_ats_found, website_unreachable, ats_error, budget_exhausted, invalid_input) and any errors. The dataset has three views: Overview, Salaries and All fields.

Pricing (pay per event)

EventPriceWhen it is charged
company-resolved$0.01Once per input domain where at least one supported ATS board was found and read.
job-scraped$0.002Once per job saved to the dataset, after your filters and maxJobsPerCompany.

You are never charged for domains with no supported ATS, unreachable websites, invalid input, or ATS detection on direct boardUrls (those pay only per job).

Examples:

  • 10 company domains, 50 jobs each: 10 × $0.01 + 500 × $0.002 = $1.10
  • All 3,614 open jobs at 12 large employers (Stripe, OpenAI, Visa, ServiceNow…, capped at 500 each): $7.35
  • Checking 1,000 domains for engineering roles posted this week, 120 with matches: about $1.20 + $0.002 per matching job

Spending limit. Set Maximum cost per run (maxTotalChargeUsd) in the run options. The Actor never charges past it. When the budget runs out, it saves what has been paid for, marks the remaining companies budget_exhausted in OUTPUT, and finishes successfully. It does not charge a company fee unless the budget also covers that company's jobs. If the budget can't pay for even one job, the run stops right away with BUDGET_TOO_LOW.

Call it from the API, code or an AI agent

HTTP (synchronous, returns the jobs):

curl -X POST "https://api.apify.com/v2/acts/impressionable_lupine~ats-jobs-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"domains":["linear.app","figma.com"],"keyword":"engineer","maxJobsPerCompany":20}'

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('impressionable_lupine/ats-jobs-scraper').call({ domains: ['stripe.com'], postedWithinDays: 7 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python:

from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("impressionable_lupine/ats-jobs-scraper").call(run_input={"domains": ["crowdstrike.com"], "remote": True})
jobs = list(client.dataset(run["defaultDatasetId"]).iterate_items())

MCP (Claude, Cursor, any MCP client). Add the Apify MCP server with this Actor enabled:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?actors=impressionable_lupine/ats-jobs-scraper",
"headers": { "Authorization": "Bearer <APIFY_TOKEN>" }
}
}
}

Then ask: "Which of these 20 companies are hiring data engineers in Europe? Use ats-jobs-scraper." The agent calls the Actor with domains, keyword and location, and gets the structured jobs back.

Tested on real companies

Local end-to-end run, 20 Oct 2026, 14 domains, no proxies. 12 of the 12 companies on a supported ATS resolved, with 3,614 jobs in 48 seconds: Linear, Ramp and OpenAI (Ashby); Figma, Stripe, Airbnb and Datadog (Greenhouse); Palantir (Lever); Visa and CrowdStrike (Workday); ServiceNow (SmartRecruiters); Hugging Face (Workable). The two negative controls returned a clear free no_ats_found: NVIDIA (Eightfold, not supported) and Bosch (careers host disallows crawlers in robots.txt).

Limitations

  • Supported ATSs only: Greenhouse, Lever, Ashby, Workday, SmartRecruiters and Workable. Companies on iCIMS, Taleo, SuccessFactors, Eightfold, Phenom, BambooHR, Teamtailor, Personio or a fully in-house system come back as no_ats_found and are not charged. If you know a company's board URL on a supported ATS, pass it in boardUrls.
  • robots.txt is respected on company websites. If a careers site disallows crawlers, detection by page is skipped, and the slug probe or a direct boardUrls entry is the way in.
  • Workday returns at most 2,000 jobs per site through its public feed. Dates in listings are "Posted N days ago" (day precision; "30+ days" has no exact date) unless includeDescription is on. Department isn't exposed in listings.
  • Slug probing only accepts boards whose name or postings match the domain. Companies whose ATS slug differs from their domain (e.g. BoschGroup) need a careers-page link or a boardUrls entry.
  • Salary appears only when the employer publishes it. Text-derived ranges are conservative and need a currency symbol on both ends.
  • Each run reads live data. To track new or closed roles, schedule the Actor and compare jobIds between runs.

FAQ

Is it legal to scrape ATS job boards? The Actor reads only public job postings from the official, unauthenticated feeds the ATS vendors provide for careers pages. No login, no personal data, and robots.txt is honoured on company sites. Check that your use fits your jurisdiction and the sites' terms.

How is this different from a LinkedIn or Indeed scraper? It goes to the source. ATS feeds are where companies publish first, they include roles never syndicated to job boards, and they carry the ATS's job ID, exact posting date and the direct apply link, with no duplicates or reposts.

Do I need the Greenhouse/Lever slug? No. Give the domain. If you already have the board URL or slug, put it in boardUrls to skip detection and the $0.01 company fee.

Why was a domain no_ats_found? The company uses an ATS that isn't supported, its careers page loads jobs from an unsupported source, or robots.txt blocked the careers host. The OUTPUT record shows which pages were checked and why. You are not charged.

Can I get only new jobs? Use postedWithinDays: 1 on a daily schedule, or diff jobId across runs.

How fast is it? About 2–10 s per company for Greenhouse, Lever, Ashby and Workable. Large Workday sites take 10–40 s because the feed pages 20 jobs at a time. Companies run in parallel.

Does it use proxies? No. Official feeds don't need them, and that's why the price per job can be low.

What happens if an ATS changes its API? Each adapter validates the response shape. A change shows up as an explicit ATS_FORMAT_CHANGED error for that company, never as silently wrong data.


Keywords: ats jobs scraper, greenhouse jobs, lever jobs, workday jobs, careers page scraper, ashby jobs scraper, smartrecruiters jobs, workable jobs, job postings API, company jobs API, hiring signals, job board scraper.