ATS Jobs Scraper: Greenhouse, Lever, Workday, Personio +9
Pricing
$1.50 / 1,000 job results
ATS Jobs Scraper: Greenhouse, Lever, Workday, Personio +9
Get normalized job postings from any company's career site via the public job-board APIs and feeds of 13 ATS: Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio, Teamtailor, BambooHR, Breezy HR, Pinpoint, JazzHR and Workday. Salary, remote flag, filters, pay per job.
Pricing
$1.50 / 1,000 job results
Rating
0.0
(0)
Developer
Matija Sever
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
ATS Jobs Scraper: Greenhouse, Lever, Workday, Personio and 9 more
Get every open job from any company's career site as clean, normalized JSON. Give the Actor a list of
companies (career page URLs, ats:slug shorthands, the company's own careers page or just a name) and it
returns one item per job with the same fields for all 13 supported applicant tracking systems (ATS):
title, locations, countries, remote/hybrid, department, employment type, salary range, publication date,
full description and the apply link.
It reads only the public job-board APIs and feeds that the ATS vendors serve for career sites (documented APIs where they exist, otherwise the same public JSON or XML the career page itself loads). No login, no browser, no proxies needed, no personal data. That makes it fast (hundreds of jobs per second for API-based boards), cheap and reliable.
Only need one platform? Single-platform editions with the same engine, output and price: Workday Jobs Scraper, Greenhouse Jobs Scraper, Lever Jobs Scraper and Ashby Jobs Scraper.
Supported applicant tracking systems
| ATS | Example input | Public source used | Salary | Notes |
|---|---|---|---|---|
| Greenhouse | https://boards.greenhouse.io/airbnb | Job Board API (boards-api.greenhouse.io) | Yes (pay transparency ranges) | US and EU (job-boards.eu.greenhouse.io) boards, embedded boards |
| Lever | https://jobs.lever.co/palantir | Postings API, US and EU hosts | Yes | EU boards (jobs.eu.lever.co) detected automatically |
| Ashby | https://jobs.ashbyhq.com/linear | Job Posting API | Yes | Compensation tiers included |
| Workable | https://apply.workable.com/skroutz/ | Job widget API | No | |
| SmartRecruiters | https://jobs.smartrecruiters.com/Ubisoft2 | Posting API | No | One extra request per job for descriptions |
| Recruitee | https://bunq.recruitee.com | Careers Site API | Yes | Custom domains detected from the careers page |
| Personio | https://1komma5grad.jobs.personio.de | XML job feed | Yes, when published | Optional language (en, de, ...) |
| Teamtailor | https://polestar.teamtailor.com | Career site RSS feed | No | Custom domains supported |
| BambooHR | https://switch2.bamboohr.com/careers | Careers site JSON | Yes (parsed from text) | One extra request per job |
| Breezy HR | https://vetsez.breezy.hr | Careers JSON feed | Yes (parsed from text) | |
| Pinpoint | https://skims.pinpointhq.com | postings.json feed | Yes | No publication date in the feed |
| JazzHR | https://aerotech.applytojob.com/apply | XML job feed | No | |
| Workday | https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite | Career site JSON (CXS) | No | Max 2,000 results per search (Workday limit) |
A single job link from any of these boards works too; the Actor resolves it to the company board.
What can you use it for?
- Job boards and aggregators: power a niche board (a country, a stack, remote-only, startups of a VC portfolio) directly from company ATS data instead of reposted ads.
- Job alerts and monitoring: schedule the Actor daily with Only new jobs turned on and get only postings that appeared since the last run (and pay only for those).
- Sales and recruiting intelligence: hiring is a buying signal. Track which companies open roles in data, security or sales, how fast teams grow and where.
- Salary research: Greenhouse, Lever, Ashby, Recruitee, Personio, Pinpoint and others publish pay ranges; the Actor returns them as numbers with currency and period.
- AI agents (MCP): agents can answer "which of these 30 companies hire remote ML engineers in Europe?" in one call. All fields have clear names and descriptions.
How to use it
- Open the Actor and add companies to Companies, one per line. Any of these formats works:
- a board URL:
https://jobs.lever.co/palantir,https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite - a shorthand:
greenhouse:airbnb,lever:palantir,personio:1komma5grad,workday:nvidia.wd5/NVIDIAExternalCareerSite - the company's own careers page:
https://www.bunq.com/careers(the embedded ATS board is detected) - a bare name:
openai(every supported ATS is probed for a board with that name)
- a board URL:
- Optionally set filters (keywords, locations, remote only, posted within N days, departments, employment types).
- Click Start. Results appear in the Output tab; a per-company report is saved as
RUN_SUMMARY.
Input example
{"companies": ["https://boards.greenhouse.io/airbnb","lever:palantir","https://1komma5grad.jobs.personio.de","https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"],"keywords": ["engineer", "data"],"locations": ["Germany", "Remote"],"postedWithinDays": 14,"maxJobsPerCompany": 200,"includeDescription": true}
| Field | What it does |
|---|---|
companies (required) | Career page URLs, ats:slug shorthands, company careers pages or names. |
keywords / keywordMatch | Whole-word match in the title (default) or title and description. engineer* = prefix match. |
excludeKeywords | Drop titles containing any of these words (e.g. senior, intern). |
locations | City, region, country name or ISO code (DE, US, GB), or Remote. |
remoteOnly | Only fully remote jobs. |
postedWithinDays | Only jobs published in the last N days. |
departments | Department or team contains any of these terms. |
employmentTypes | full_time, part_time, contract, temporary, internship, apprenticeship, volunteer. |
maxJobsPerCompany / maxTotalJobs | Caps. Newest jobs first where the ATS publishes dates; on very large paginated boards (Workday, SmartRecruiters) listing stops once enough matches are found. |
includeDescription / includeDescriptionHtml | Plain-text description (default on) and/or original HTML. |
onlyNewJobs / stateKey | Monitoring mode: skip jobs returned by earlier runs with the same key. |
Output example
Each job is one dataset item. Every item has the same keys; values an ATS does not publish are null.
{"company": "Airbnb","company_slug": "airbnb","ats": "greenhouse","job_id": "8318155","title": "Senior Compliance Lead, EMEA","url": "https://careers.airbnb.com/positions/8318155?gh_jid=8318155","apply_url": "https://careers.airbnb.com/positions/8318155?gh_jid=8318155","locations": ["Brussels", "Dublin, Ireland", "London, United Kingdom"],"countries": ["BE", "IE", "GB"],"is_remote": false,"workplace_type": "hybrid","department": "Business Operations/Analysis","team": null,"employment_type": null,"employment_type_raw": null,"salary_min": 130000,"salary_max": 160000,"salary_currency": "EUR","salary_period": "year","salary_text": "Belgium Annual Pay Range: EUR 130,000 - 160,000","posted_at": "2026-10-23T14:32:32Z","updated_at": "2026-10-23T14:32:32Z","description_text": "Airbnb was born in 2007 when two hosts welcomed three guests ...","source_url": "https://boards-api.greenhouse.io/v1/boards/airbnb/jobs?content=true&pay_transparency=true","scraped_at": "2026-10-25T16:38:00Z"}
Field notes:
workplace_typeisremote,hybrid,onsiteornull(not stated by the company).is_remoteistruefor fully remote jobs and jobs that offer remote locations.countriesholds ISO 3166-1 alpha-2 codes taken from the ATS's structured data or recognized location names (e.g.BerlinbecomesDE). It is empty when the location is ambiguous.employment_typeis normalized across vendors and languages (Vollzeit,FullTime,Permanentall becomefull_time);employment_type_rawkeeps the original value.posted_at/updated_atare ISO 8601 UTC. Workday dates come from the job detail; JazzHR dates are derived from the job's creation timestamp; Pinpoint publishes no date.
The Output tab offers three views: Overview, Salaries and All fields.
Run summary
The key-value store record RUN_SUMMARY lists every input with its status, the detected ATS and how many jobs
were found, matched and saved, so failed or empty boards are easy to spot:
{"status": "completed","message": "Saved 42 job(s) from 14/16 companies; 2 failed (see RUN_SUMMARY in the key-value store).","totals": {"companies": 16, "succeeded": 14, "failed": 2, "jobs_found": 4415, "jobs_saved": 42},"companies": [{"input": "openai", "status": "ok", "ats": "ashby", "company": "OpenAI", "detected_via": "name_probe","jobs_available": 793, "jobs_found": 793, "jobs_matched": 3, "jobs_saved": 3, "error": null},{"input": "https://boards.greenhouse.io/doesnotexist-xyz-123", "status": "error", "ats": "greenhouse","error": "Greenhouse board not found (HTTP 404 (not found)). Check the URL / company identifier."}]}
One failing company never fails the run: requests are retried with exponential backoff (respecting
Retry-After), every company has a timeout, and errors are reported per company.
Monitoring new jobs
Turn on Only new jobs and run the Actor on a schedule (for example daily). Each run returns only jobs that
earlier runs with the same State key have not returned, so you receive (and pay for) new postings only.
The list of returned job IDs is kept for 120 days in a named key-value store ats-jobs-scraper-state in your
account. Use a different state key for each schedule or saved task.
Tip: the first run returns all currently open jobs that match your filters. If you also set
maxJobsPerCompany, jobs held back by that cap count as new in later runs, so for monitoring prefer filters
(keywords, locations) over small caps. Already-known jobs are dropped before any per-job request, so
monitoring runs stay fast and cheap.
Use with AI agents (MCP)
The Actor works well as a tool for AI agents through the Apify MCP server: the input accepts plain company names and URLs, every field is documented, and the output is flat JSON. Tips for agents:
- Prefer URLs or
ats:slugshorthands when you know them; bare names are resolved by probing ATS vendors. - Set
maxJobsPerCompanyandkeywordsto keep results (and token usage) small; setincludeDescriptiontofalsewhen you only need titles and links. - Read
RUN_SUMMARYto see which companies had no board or no matching jobs.
Example prompt: "Use the ATS Jobs Scraper to list remote data engineering jobs posted in the last 7 days at Airbnb, Stripe, Palantir and OpenAI, with salary ranges."
Use via API
Run the Actor and get the results in one call (replace <TOKEN> and <ACTOR_ID>):
curl -X POST "https://api.apify.com/v2/acts/<ACTOR_ID>/run-sync-get-dataset-items?token=<TOKEN>" \-H "Content-Type: application/json" \-d '{"companies": ["greenhouse:airbnb", "lever:palantir"], "keywords": ["engineer"], "maxJobsPerCompany": 50}'
Python (apify-client 3.x):
from decimal import Decimalfrom apify_client import ApifyClientclient = ApifyClient("<TOKEN>")run = client.actor("<ACTOR_ID>").call(run_input={"companies": ["https://jobs.ashbyhq.com/linear"], "keywords": ["engineer"]},max_total_charge_usd=Decimal("1.00"), # optional cost cap for this run)for job in client.dataset(run.default_dataset_id).iterate_items():print(job["title"], job["locations"], job["url"])
Pricing
This Actor uses pay per event: you pay for the job postings you get, not for compute time.
| Event | Price |
|---|---|
| Job posting saved to the dataset | $1.50 per 1,000 jobs ($0.0015 per job) |
| Actor start | $0.00005 per run (Apify default) |
Examples: 10 companies with 50 matching jobs each = 500 jobs = about $0.75. A daily monitoring run over
100 companies that finds 40 new jobs costs about $0.06. Failed companies, duplicates and jobs skipped by your
filters or by Only new jobs are never charged. Set Maximum cost per run in the run options to cap
spending: the Actor stops collecting exactly when your limit is reached, and RUN_SUMMARY says so.
FAQ
Is it legal to scrape job postings? The Actor collects job advertisements that companies publish publicly in order to distribute them, through the public endpoints that the ATS vendors provide for career sites and job widgets. It does not log in, bypass access controls or collect personal data: recruiter names and contact details that some feeds contain are dropped. You remain responsible for how you use the data (for example respecting the companies' terms and any rules that apply to republishing). If in doubt, consult a lawyer.
How do I find a company's ATS? Paste the company's careers page URL: the Actor detects embedded or linked boards from 13 vendors. You can also paste any job link from the company; the board is derived from it.
Why is a field null?
Only data the company publishes is returned. For example, Workable and Teamtailor feeds have no salary,
Workday has no department, Pinpoint has no publication date.
Why did a company return 0 jobs?
Check RUN_SUMMARY: the board may not exist (error), may have no open jobs, or your filters removed
everything (jobs_found > 0 but jobs_matched = 0). SmartRecruiters returns an empty list instead of an
error for unknown company identifiers.
Does it scrape LinkedIn, Indeed or Glassdoor? No. It reads company career sites (ATS boards) directly, which are the original source of those postings.
How fresh is the data? Live: every run reads the boards at run time. There is no cached database in between.
Can you add another ATS? Open an issue in the Issues tab with an example career page URL.
Limitations
- Workday's career-site search returns at most 2,000 jobs per site; use
keywords(sent to Workday's own search) to reach specific roles on very large tenants. - Bare company names are matched against board identifiers, so a different company with the same identifier
on another ATS can be picked. Use URLs for certainty; the summary marks name matches with
detected_via: name_probe. - Career pages that load their job board only with JavaScript from an unknown source cannot be detected; pass the ATS board URL instead.