ATS Jobs: Greenhouse, SmartRecruiters, Personio | $1.49/1k avatar

ATS Jobs: Greenhouse, SmartRecruiters, Personio | $1.49/1k

Pricing

from $1.49 / 1,000 job postings

Go to Apify Store
ATS Jobs: Greenhouse, SmartRecruiters, Personio | $1.49/1k

ATS Jobs: Greenhouse, SmartRecruiters, Personio | $1.49/1k

Open jobs from company career boards on Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Recruitee, Personio and Teamtailor. Give board URLs or company names; get one normalized row per job: title, location, remote flag, salary, dates, apply link, advert text. No API keys, no login.

Pricing

from $1.49 / 1,000 job postings

Rating

0.0

(0)

Developer

Raffy

Raffy

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

What does ATS Jobs Scraper do?

ATS Jobs Scraper reads the public job boards that companies host on eight applicant-tracking systems (ATS) - Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Recruitee, Personio and Teamtailor - and returns one normalized row per open job. You give it a list of companies; it gives you every posting they have open right now, in the same columns whichever system the company uses: title, department, location, remote flag, employment type, salary range where the ATS publishes one, dates, posting and apply links, and the full advert as plain text.

It works as a Greenhouse API, Lever API and Ashby API alternative in one call: no API key, no account on any of the systems, no browser and no proxy. Each company is one plain HTTP request to the endpoint the company's own careers page uses, so a run over dozens of companies finishes in seconds and the data is first-hand - never a repost from an aggregator.

It does not log in, does not read private applicant data and does not return recruiter or hiring-manager names, e-mail addresses or phone numbers.

Use cases for this job board API

  • Hiring-signal lead generation - feed in your target-account list and see which accounts are hiring, for which teams and where. Ten open "Data Engineer" roles is a buying signal for data tooling; a first "Head of Security" role is one for security vendors. Filter with titleKeywords and you pay only for the roles that matter to you.
  • Job board and newsletter aggregation - pull the openings of the companies you cover straight from the source, with stable jobIds for de-duplication and direct applyUrls.
  • Recruiting and talent-market research - track which departments grow at competitors, how much of their hiring is remote, and what pay ranges they publish.
  • Sales and investor research - headcount plans show up on a careers page long before they show up anywhere else.
  • Automation - schedule a daily run and send new rows to Google Sheets, Airtable, Supabase or a CRM through Apify integrations, webhooks, n8n, Make or Zapier. Diff on ats + companySlug + jobId to get "new jobs today".

Supported applicant-tracking systems

ATSExample entryAlso acceptedNotes
Greenhousehttps://boards.greenhouse.io/stripehttps://job-boards.greenhouse.io/stripe, greenhouse:stripePay range when the company publishes pay transparency ranges.
Leverhttps://jobs.lever.co/palantirlever:palantir, https://jobs.eu.lever.co/<slug>, lever-eu:<slug>Workplace type, team and country on every posting.
Ashbyhttps://jobs.ashbyhq.com/rampashby:rampStructured salary (min, max, currency, period) when the company shows compensation.
SmartRecruitershttps://jobs.smartrecruiters.com/BoschGroupsmartrecruiters:BoschGroupNeeds the company id from the board URL. The advert text takes one extra request per job.
Workablehttps://apply.workable.com/bluegroundworkable:bluegroundCompany boards on apply.workable.com.
Recruiteehttps://bunq.recruitee.comrecruitee:bunqUse the <company>.recruitee.com address, not the company's own careers domain.
Personiohttps://holidu.jobs.personio.depersonio:holidu, .jobs.personio.comRead in English; monthly or yearly salary when published.
Teamtailorhttps://career.teamtailor.comteamtailor:career.teamtailor.comHost-based: give the address of the careers site.

You can also type just the company name (stripe, ramp). The Actor then tries the eight systems in the order of the table above until one lists jobs for that name, and records which one matched in the ats column. That costs up to 8 small requests per spelling of the name, so a board URL or ats:slug is faster and exact. When no system knows the name you get one free not_found row for that company - an entry never disappears silently.

What data can ATS Jobs Scraper extract?

Every ok row has the same columns. A value the ATS does not publish is null; nothing is guessed from the advert text.

FieldTypeDescription
statusstringok, not_found or error (see below)
companystringCompany display name as the ATS publishes it; derived from the slug for Lever and Ashby, which publish none
companySlugstringThe company's identifier on the ATS (the careers host name for Teamtailor)
atsstringgreenhouse, lever, ashby, smartrecruiters, workable, recruitee, personio or teamtailor
jobIdstringThe posting's id on that ATS; unique together with ats and companySlug
titlestringJob title
departmentstringDepartment, when published
teamstringTeam within the department (Lever, Ashby)
locationstringPrimary location as displayed on the board
locationsarrayEvery location listed for the posting, primary first
countrystringISO code (Lever, SmartRecruiters, Recruitee, Workable, Teamtailor) or country name (Ashby); null for Greenhouse and Personio
workplaceTypestringremote, hybrid or onsite, only when the ATS has an explicit workplace field (Lever, Ashby, SmartRecruiters, Recruitee)
isRemotebooleanThe ATS's remote flag; for Greenhouse, Personio and Teamtailor, whether the location text says Remote
employmentTypestringFull-time, Part-time, Contract, Temporary, Internship, Permanent, or the ATS's own wording
salaryMin, salaryMaxnumberPay range from the ATS's structured pay fields only
salaryCurrencystringISO 4217 code, e.g. USD
salaryPeriodstringyear, month, week, day or hour, when stated
postedAtstringWhen the posting was published, ISO 8601 UTC
updatedAtstringWhen it was last updated (Greenhouse, Recruitee)
urlstringPublic posting URL
applyUrlstringDirect link to the application form, when published
descriptionTextstringFull advert as plain text; null when includeDescription is off
sourceEndpointstringThe public ATS endpoint the row was read from
scrapedAtstringISO 8601 time of extraction
errorstringReason, on not_found and error rows only

SmartRecruiters rows can also carry descriptionError: the reason why the advert text could not be fetched. The rest of that row is still complete.

Result status (tri-state output)

statusMeaningBilled?
okOne open job posting.Yes
not_foundThe company has no board on the checked system(s), its board lists no open jobs, or no job matched your filters. One row per company, with the reason in error.No
errorThe board could not be read after retries (network error, block, or a changed response format). error says why.No

How to scrape Greenhouse, Lever, Ashby and other ATS job boards

  1. Open the Actor in Apify Console and click Try for free.
  2. Put one company per line into Companies or job board URLs: a board URL, an ats:slug pair, or a company name.
  3. Optionally narrow the run with Title keywords, Location contains, Remote jobs only or Posted within (days). Filters run before a row is written, so you only pay for matches.
  4. Set Maximum results (the default 20 keeps a first run cheap) and, if one large employer should not use up the run, Maximum results per company.
  5. Click Start. Records appear in the dataset in real time; open the Output tab or Export them as JSON, CSV, Excel, XML or HTML.

To automate it, use the API tab (Node.js, Python, curl examples) or add a Schedule.

Input

See the Input tab for the full schema. The main options:

FieldTypeDefaultDescription
companiesarray of stringsthree sample boardsBoard URLs, ats:slug pairs or company names, one per entry
titleKeywordsarray of strings-Keep a job when its title contains any of these (case-insensitive)
locationContainsstring-Keep a job when its location, extra locations or country contains this text
remoteOnlybooleanfalseKeep only remote postings
postedWithinDaysinteger-Keep only jobs published in the last N days (falls back to the updated date)
maxItemsinteger20Stop after this many rows
maxItemsPerCompanyinteger- (prefilled 7)Cap per company
includeDescriptionbooleantrueAdd descriptionText; turn off for lighter, faster runs
startUrlsarray of stringsthe same three boardsAlias of companies for tools that always send startUrls
proxyConfigurationobjectApify Proxy offNot needed; the boards answer datacenter IPs

Example input (the prefilled default):

{
"companies": ["greenhouse:duolingo", "ashby:linear", "lever:spotify"],
"maxItems": 20,
"maxItemsPerCompany": 7,
"includeDescription": true
}

A hiring-signal run over your own account list:

{
"companies": ["https://boards.greenhouse.io/stripe", "https://jobs.ashbyhq.com/ramp", "palantir", "smartrecruiters:BoschGroup"],
"titleKeywords": ["data engineer", "analytics", "machine learning"],
"postedWithinDays": 30,
"includeDescription": false,
"maxItems": 500
}

Output

You can download the dataset in various formats such as JSON, HTML, CSV or Excel. Real rows from a run with the default input on 2026-09-20 (descriptionText shortened here), followed by the real not_found row a run gave for a company name that no system knows:

[
{
"status": "ok",
"company": "Duolingo",
"companySlug": "duolingo",
"ats": "greenhouse",
"jobId": "8705196002",
"title": "Ad Sales Lead - West",
"department": "Business",
"team": null,
"location": "Remote - California",
"locations": ["Remote - California"],
"country": null,
"workplaceType": null,
"isRemote": true,
"employmentType": null,
"salaryMin": 152000,
"salaryMax": 228000,
"salaryCurrency": "USD",
"salaryPeriod": null,
"postedAt": "2026-08-13T13:22:34.000Z",
"updatedAt": "2026-09-03T16:23:10.000Z",
"url": "https://careers.duolingo.com/jobs/8705196002?gh_jid=8705196002",
"applyUrl": "https://careers.duolingo.com/jobs/8705196002?gh_jid=8705196002",
"descriptionText": "Our mission at Duolingo is to develop the best education in the world and make it universally available. ...",
"sourceEndpoint": "https://boards-api.greenhouse.io/v1/boards/duolingo/jobs?content=true&pay_transparency=true",
"scrapedAt": "2026-09-20T19:16:13.558Z"
},
{
"status": "ok",
"company": "Spotify",
"companySlug": "spotify",
"ats": "lever",
"jobId": "2193db3f-77c5-43b8-b030-8f92c9882bf1",
"title": "Android Engineer - Experience",
"department": "Engineering",
"team": "Experience",
"location": "London",
"locations": ["London", "Stockholm"],
"country": "GB",
"workplaceType": "hybrid",
"isRemote": false,
"employmentType": "Permanent",
"salaryMin": null,
"salaryMax": null,
"salaryCurrency": null,
"salaryPeriod": null,
"postedAt": "2026-06-23T11:29:45.805Z",
"updatedAt": null,
"url": "https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1",
"applyUrl": "https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1/apply",
"descriptionText": "We design Spotify’s consumer experience—end to end, moment to moment, across every screen, platform, and partner integration. ...",
"sourceEndpoint": "https://api.lever.co/v0/postings/spotify?mode=json",
"scrapedAt": "2026-09-20T19:16:16.121Z"
},
{
"url": "https://apify.com/glasswing/ats-jobs-scraper",
"status": "not_found",
"error": "No public job board was found for \"zzqq no such company 123\" on any of the supported systems (greenhouse, lever, ashby, smartrecruiters, workable, recruitee, personio, teamtailor). Give the board URL or \"ats:slug\" (for example greenhouse:stripe) if you know where the company posts its jobs.",
"scrapedAt": "2026-09-20T19:19:11.702Z",
"company": "zzqq no such company 123",
"companySlug": "zzqqnosuchcompany123",
"ats": null,
"sourceEndpoint": "https://api.smartrecruiters.com/v1/companies/zzqqnosuchcompany123/postings?limit=1"
}
]

How much does it cost to scrape ATS job boards?

This Actor uses pay-per-event pricing:

EventPriceCharged when
Actor start$0.005 per runOnce when the run starts. The platform charges one event per GB of memory and the Actor runs on 1 GB, so this is one event.
Job posting$0.00149 per jobOne job posting with status: ok was saved to the dataset.

1,000 jobs cost about $1.50 ($0.005 to start plus 1,000 x $0.00149 = $1.495); 100 jobs cost about $0.15 ($0.154), and the default 20-job run about $0.03 ($0.0348). You are never charged for a row with status not_found or error, never for a job your filters excluded, and never twice for the same posting in one run. The free Apify plan's $5 of monthly credit covers about 3,350 jobs in a single run.

You can cap spending per run with Maximum results and with the run's Max total charge option; the Actor stops gracefully when either limit is reached and keeps everything it has already saved.

Integrations, exports and API access

Results export to CSV, JSON, Excel, XML and HTML from the Output tab or the dataset API. From there, Apify integrations and webhooks push the same rows into Google Sheets, Airtable or a CRM, plus Slack, Amazon S3 or your own endpoint - directly, or through Zapier, Make and n8n.

The Actor can also be called from the Apify API (Node.js, Python and curl snippets are on the API tab), from the Apify MCP server, or by any AI agent that can call a tool: inputs are plain strings, numbers and booleans, a call with no arguments runs the three sample boards, and every row carries status and error, so an agent can tell "this company is not hiring" apart from "this board could not be read" without parsing prose.

Tips

  • Prefer a board URL or ats:slug over a bare name: it is exact and saves the auto-detection requests.
  • Put all your companies in one run instead of many single-company runs; you pay the start fee once and the boards are read in parallel.
  • Set includeDescription to false when you only need the hiring signal (company, title, department, location). Greenhouse and Workable responses get much smaller, SmartRecruiters needs no per-job request, and the price per row is unchanged.
  • Use maxItemsPerCompany when one employer in the list has thousands of openings.
  • Schedule a daily run with postedWithinDays: 1 for a "new jobs today" feed.

Limitations

  • It needs the company list. The Actor reads the boards you name; it is not a keyword search across all companies on an ATS. Finding out which ATS a company uses is on you, or on the auto-detection, which only tries the company name as a slug.
  • Auto-detection is a best effort. It matches a name only when the company's slug on the ATS is the name itself (stripe) or its compact or hyphenated form (bosch group -> boschgroup, bosch-group), and a different company can own the same slug. At most 100 bare names are auto-detected per run. When it matters, give the board URL.
  • Salary only where the ATS publishes structured pay. Ashby compensation, Greenhouse pay ranges, and the salary fields of Lever, Recruitee, Personio and Teamtailor are read; pay that an employer only mentions inside the advert text stays in descriptionText. Workable and SmartRecruiters publish no structured pay.
  • Fields differ by system. department, team, country, workplaceType, employmentType and updatedAt are null where the ATS has no such field; the field table above says which. Lever and Ashby publish no company display name, so company is derived from the slug there.
  • SmartRecruiters: about 5,000 postings per company per run at most, and the advert text costs one extra request per job.
  • Personio is read in English (language=en); a tenant that writes its adverts only in another language can come back with an empty descriptionText.
  • Recruitee boards must be given as <company>.recruitee.com; a company's own careers domain does not serve the public endpoint.
  • A board URL with a typo gives a not_found row that carries the endpoint URL and HTTP 404 rather than the company columns.
  • Only published, public postings are visible. If a system changes its response format, rows come back as error rather than silently wrong; report it in the Issues tab and the Actor is updated quickly.

FAQ

Do I need an API key for Greenhouse, Lever, Ashby or the other systems? No. The Actor reads the public, keyless endpoints that the companies' own careers pages use. All you need is an Apify account.

How do I know which ATS a company uses? Open its careers page and look at the address of a job or of the "Apply" button: boards.greenhouse.io, jobs.lever.co, jobs.ashbyhq.com, jobs.smartrecruiters.com, apply.workable.com, *.recruitee.com, *.jobs.personio.de and *.teamtailor.com are the giveaways. Paste that URL as it is. Or type the company name and let the Actor try.

Can I search all companies for a keyword? No. This Actor goes deep on the companies you list rather than wide across a whole system. titleKeywords filters the jobs of those companies.

Does it return recruiter names, e-mails or phone numbers? No. Some of these systems include the posting's creator, owner or a mailbox address in their responses; the Actor never copies those fields, and it masks e-mail addresses and phone numbers that an employer typed into the advert text.

Why is salaryMin empty for most rows? Most employers do not publish pay as a structured field. The Actor does not guess numbers out of prose, so an empty value means "not published in a structured way", never "unknown to us".

Why did I get fewer rows than maxItems? The companies had fewer open jobs, the filters excluded the rest, maxItemsPerCompany capped them, or the run hit your Max total charge limit. Check the run log for "Stopping gracefully".

What happens when a company has no open jobs or nothing matches my filters? You get one free not_found row for that company with the reason, so your pipeline can tell "not hiring" from "not checked".

Can I use this Actor from an AI agent or MCP client? Yes. Inputs are plain values, every row is self-describing (status plus error), and results can be fetched via the dataset API or the Apify MCP server.

This Actor extracts only data that companies publish on their public job boards, and only business data about jobs and hiring companies: job titles, adverts, departments, locations, workplace and employment types, pay ranges, dates, company names and links.

It does not emit recruiter, hiring-manager, creator or owner names, e-mail addresses or phone numbers. Where a system's public response contains such fields the Actor does not copy them, and as an extra safeguard e-mail addresses and phone numbers that an employer typed into the advert text are replaced with [email removed] and [phone removed] before the row is saved. The Actor does not log in, does not solve captchas and does not circumvent access controls.

Job adverts can nevertheless mention individuals. Personal data is protected by the GDPR in the European Union and by other regulations around the world; you should not process personal data without a legitimate reason. If you are unsure whether your reason is legitimate, consult your lawyers. You are responsible for complying with the terms of service of the systems and companies whose boards you read, and with applicable law, when you use the extracted data.

This Actor is an independent tool. It is not affiliated with, endorsed by or sponsored by Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Recruitee, Personio, Teamtailor or any company whose jobs it lists. All trademarks belong to their respective owners.