ATS Jobs Scraper & Hiring Monitor - Greenhouse, Lever, Ashby avatar

ATS Jobs Scraper & Hiring Monitor - Greenhouse, Lever, Ashby

Pricing

from $1.00 / 1,000 jobs

Go to Apify Store
ATS Jobs Scraper & Hiring Monitor - Greenhouse, Lever, Ashby

ATS Jobs Scraper & Hiring Monitor - Greenhouse, Lever, Ashby

Track which companies are hiring. Enter company domains or careers URLs; the ATS is auto-detected (Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Personio, Teamtailor, BambooHR). Get only NEW jobs since the last run, closed jobs, and a hiring summary per company.

Pricing

from $1.00 / 1,000 jobs

Rating

0.0

(0)

Developer

Ivan Petrus

Ivan Petrus

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

16 hours ago

Last modified

Categories

Share

ATS Jobs Scraper & Hiring Monitor: Greenhouse, Lever, Ashby, Workday & More

Track who is hiring, for what, and where. Enter company domains or careers-page URLs. The Actor finds the company's job board, reads it through the board's official public job-board API, and returns:

  • New jobs since the last run (monitor mode, default) or all open jobs.
  • Closed jobs: jobs that disappeared since the last run. These rows are free.
  • A hiring summary per company: open roles, change vs last run, trend, top departments and locations, remote and salary counts, new departments and new locations. These rows are free.

Supported job systems (ATS): Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Personio, Teamtailor, BambooHR.

Typical uses:

  • Sales and RevOps teams use hiring as a buying signal ("Acme just opened 5 data-engineering roles in Berlin").
  • Recruiters and agencies watch target companies.
  • Investors and analysts track headcount momentum.
  • Job boards and newsletters aggregate fresh roles from specific companies.

Sample output

A job row and the free summary row from a real Apify cloud run (Oct 2026, greenhouse:n26), shortened:

[
{
"type": "job",
"company": "N26",
"title": "AFC Operations Team Lead - French Team",
"department": "AFC Operations",
"location": "Madrid",
"employmentType": "Full-time",
"postedAt": "2026-09-17T08:31:23Z",
"url": "https://n26.com/en-eu/careers/positions/8201489?gh_jid=8201489",
"ats": "Greenhouse",
"isNew": false
},
{
"type": "summary",
"company": "N26",
"ats": "Greenhouse",
"openJobs": 44,
"detectionMethod": "explicit",
"topDepartments": [{"name": "Group Internal Audit", "count": 4}, {"name": "Risk", "count": 3}, …],
"topLocations": [{"name": "Berlin", "count": 21}, {"name": "Madrid", "count": 8}, …]
}
]

How it works

  1. Detection. For each input the Actor works out which ATS the company uses:
    • A job-board URL or ats:token is used directly (greenhouse:airbnb, https://jobs.lever.co/palantir, https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite).
    • For a domain or careers URL, it scans the company's careers pages (/careers, /jobs, careers. and jobs. subdomains, the homepage, plus a few "Careers" links) for ATS links and embeds.
    • If nothing is found, it tries the domain name as the board token on each ATS (for example, stripe.com becomes greenhouse:stripe). It picks a guessed board only if that board has open jobs. Such matches are marked detectionMethod: "slug-guess", with a confidence value.
  2. Fetching. Jobs come from the public endpoints that each ATS publishes so companies can embed job boards on their own sites. There is no login, no scraping of personal data, and normally no proxy.
  3. Diffing. The open jobs of each company are stored in a named key-value store (stateStoreName). The next run compares against them and reports new and closed jobs.

Input example

{
"companies": ["huggingface.co", "stripe.com", "https://jobs.lever.co/palantir", "greenhouse:airbnb",
"workday:nvidia.wd5/NVIDIAExternalCareerSite"],
"onlyNewJobs": true,
"firstRunBehavior": "baselineOnly",
"titleKeywords": ["engineer", "data"],
"locationKeywords": ["Germany", "Berlin", "Remote"]
}

You can also pass explicit boards as JSON: [{"ats": "greenhouse", "boardToken": "airbnb", "companyName": "Airbnb"}].

Scheduling: create a task with your company list and schedule it daily or weekly. Each run outputs only what changed.

Output

Job row (type: "job"):

{
"type": "job", "company": "Channable", "ats": "Recruitee", "jobId": "2622523",
"title": "Python Software Engineer - AI team", "department": "Engineering", "team": null,
"location": "Utrecht, Utrecht, Netherlands", "locations": ["Utrecht, Utrecht, Netherlands"], "country": "NL",
"remote": false, "workplaceType": "hybrid", "employmentType": "Full-time",
"salaryMin": 5000, "salaryMax": 7000, "salaryCurrency": "EUR", "salaryPeriod": "month", "salaryText": "5,000–7,000 EUR/month",
"postedAt": "2026-06-02T10:10:41Z", "updatedAt": "2026-10-08T01:54:04Z",
"url": "https://jobs.channable.com/o/python-software-engineer-ai-team-1", "isNew": true,
"firstSeenAt": "2026-10-08T07:46:17Z"
}

Summary row (type: "summary", free), one per company:

  • openJobs, previousOpenJobs, openJobsChange, openJobsChangePct, hiringTrend (growing / stable / shrinking).
  • newJobs, closedJobs, newJobTitles, closedJobTitles.
  • topDepartments, topLocations, newDepartments, newLocations.
  • remoteJobs, hybridJobs, jobsWithSalary, employmentTypes, newestPostedAt.
  • boardUrl, detectionMethod, detectionConfidence, listComplete, notes.

Closed-job row (type: "closedJob", free): title, department, location, URL, firstSeenAt and closedDetectedAt.

Error row (type: "error", free): companies whose job board could not be detected or read. The row says what was scanned and guessed, plus a hint on how to fix it. Companies that fail are not charged.

The dataset has table views for Jobs, Hiring summary and Closed jobs. RUN_SUMMARY in the default key-value store holds run statistics.

Data availability per ATS (honest notes)

ATSDepartmentLocation / remoteSalaryPosted dateDescription option
Greenhouseyesyes / from custom fieldswhen the company publishes pay rangesfirst published + updatedyes
Leveryes (department/team)yes / workplace typewhen published (rare)createdyes
Ashbyyesyes / remote flagoften (US companies)publishedyes
Workdayno per job (summary uses Workday's category counts)text ("3 Locations" for multi-site)noapproximate (from "Posted 3 Days Ago"; "30+ days" gives null)no
SmartRecruiterssometimesyes / remote + hybridnoreleasedno
Workableyesyes / remote flagnopublishedyes
Recruiteeyesyes / remote + hybridwhen publishedpublished + updatedyes
Personioyesofficenocreatedyes
Teamtailoryesyes / remote statusnopublishedyes
BambooHRyesyesnonono

Limits and caveats

  • Detection is not 100%.
    • Companies with an in-house careers system, or with other ATSs (iCIMS, Taleo, SuccessFactors, Jobvite and others), are reported as errors.
    • When a careers site loads its jobs with JavaScript from an unknown source, detection falls back to the guessed token.
    • A guessed token can belong to a different company with the same name, so check boardUrl on slug-guess rows. You can always force a board with ats:token.
  • Big boards.
    • Workday lists at most about 2,000 postings per career site.
    • SmartRecruiters and Workday are read 100 or 20 jobs per request.
    • When maxJobsPerCompany (default 2,000) or Workday's cap cuts the list, listComplete is false and closed-job detection is switched off for that company. New-job detection still works on the jobs that were read.
  • First run. In monitor mode the first run outputs all current jobs (or nothing with firstRunBehavior: "baselineOnly"). isNew is false on the first run.
  • Remote flag. It comes from each ATS's own field, or from "remote" in the location or title. It is null when unknown.
  • The data is company-level job postings published by the companies themselves. No candidate or employee data is collected.

Pricing (pay per event)

EventPrice
Actor start$0.003 per run
Company checked (board found and read)$0.003 per company
Job row output$0.001 per job ($1 per 1,000)

Summary, closed-job and error rows are free.

Example: monitoring 50 companies daily, with about 2 new jobs per company per day, costs about $0.003 + 50 × $0.003 + 100 × $0.001 = $0.25 per day. Use firstRunBehavior: "baselineOnly" to avoid paying for the existing backlog on the first run. maxJobsOutputPerCompany (default 500) caps job rows per company per run.

Daily alerts to Slack or email

  1. Fill in the input and click Save as a new task (one task per client or competitor set is a good pattern).
  2. In Schedules, create a schedule (for example every day at 08:00 in your time zone) and add the task.
  3. In the task's Integrations tab, add the Slack or Gmail integration to get a message when a run finishes, or a webhook on "Run succeeded" that passes the run to Zapier, Make, n8n or your own endpoint. Those tools can read the rows from https://api.apify.com/v2/datasets/{defaultDatasetId}/items and format them however you like.

Because monitor mode outputs only jobs that are new since the previous run (plus free closed-job and summary rows), every scheduled run's dataset is your alert list. An empty dataset (apart from free summary rows) means nothing changed. Turn on Apify's run-failure notifications too, so you hear about a failed run instead of silence.

Part of a small competitor-intelligence suite by the same developer. Same conventions everywhere: pay per event, failed items are never charged, and the monitors return only what changed since the last run.

FAQ

Can I monitor a company that is not detected? Paste its job-board URL or ats:token. If the ATS is not supported, open an issue with the careers URL.

Can I get only engineering jobs in Germany? Yes. Use titleKeywords / departmentKeywords and locationKeywords. The summary still covers all jobs.

Do I need a proxy? No. The job-board APIs are public. A proxy option exists in case a careers website blocks page scanning.